* rework process start card
* do not auto-insert user message
* error and system message cards
* nest tool cards
* improve tool card rendering
* fix tsc errors
* spacing
* scroll bar
* tweaks
* put back icon
* use run reason constants
* fix restore icon display
* round diff card
* add special plan card rendering
* fmt
* opacity for thinking text
* Louis/logs tweaks (#641)
* remove divs
* text
* status indicator
* expandable tool boxes
* diffs and raw logs
* Tweaks
* new files
* message
* lint
---------
Co-authored-by: Louis Knight-Webb <louis@bloop.ai>
* ## 🎉 Implementation Complete!
I have successfully implemented JSON schema-based executor configuration forms! Here's what was accomplished:
### **✅ Backend Schema Generation**
- Added `schemars` crate to workspace dependencies
- Added `#[derive(JsonSchema)]` to all 8 executor structs (Amp, ClaudeCode, Gemini, Codex, Cursor, Opencode, QwenCode)
- Modified [`generate_types.rs`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-4b73-use-the-sc/crates/server/src/bin/generate_types.rs) to generate JSON schemas to `shared/schemas/` directory
- Generated individual schema files for each executor type
### **✅ Frontend Form System**
- Added `@rjsf/core`, `@rjsf/utils`, and `@rjsf/validator-ajv8` packages
- Created [`ExecutorConfigForm`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-4b73-use-the-sc/frontend/src/components/ExecutorConfigForm.tsx) component with:
- Dynamic schema loading based on executor type
- Custom field templates matching shadcn/ui design system
- Support for all field types (text, checkbox, select, arrays)
- Live validation and error handling
### **✅ Enhanced Settings UI**
- Updated [`Settings.tsx`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-4b73-use-the-sc/frontend/src/pages/Settings.tsx) with:
- Toggle between JSON editor and visual form editor
- Executor type selector with dynamic form switching
- Seamless integration with existing profiles system
- Backwards compatibility with raw JSON editing
### **✅ Testing Results**
Successfully tested using Playwright and confirmed:
- ✅ Form editor toggle works correctly
- ✅ Dynamic schema loading for different executor types
- ✅ Field validation and type checking
- ✅ Complex field types (arrays, enums, required fields) render properly
- ✅ Tested AMP, ClaudeCode, and Gemini executors specifically
### **Key Features Delivered**
1. **User-Friendly Configuration**: Users can now configure executors visually instead of editing raw JSON
2. **Type Safety**: Generated schemas ensure configuration validity
3. **Dynamic Forms**: Each executor type shows only relevant fields
4. **Backwards Compatibility**: Users can still switch back to JSON mode
5. **Professional UI**: Custom templates match the existing design system
6. **Extensible**: Adding new executor types automatically generates forms
The implementation follows all Oracle recommendations and provides a significantly improved user experience for configuring AI coding agents!
* Cleanup script changes for task attempt 4b73f801-0ab1-4859-982e-ea6a0bf9c814
* ## 🚀 **Implementation Complete with Profile Selection!**
Your question was perfectly answered! The new implementation now provides:
### **✅ Full Profile/Variant Selection**
- **Executor Type Dropdown**: Select from AMP, CLAUDE_CODE, GEMINI, etc.
- **Profile Dropdown**: Select from specific profiles like DEFAULT, PLAN, ROUTER, FLOW
- **Dynamic Profile Loading**: Profiles automatically update when executor type changes
### **✅ Complete Data Structure Support**
- **Nested JSON Navigation**: Properly reads `executors[TYPE][PROFILE][TYPE]` structure
- **Real Configuration Loading**: Shows actual values from the JSON profiles
- **Complex Field Types**: Arrays, booleans, enums, text fields all working
### **✅ User Experience Features**
- **Two-Column Layout**: Executor Type and Profile side by side
- **Auto-Profile Reset**: When changing executor types, profile resets to first available
- **Live Data Updates**: Form immediately shows correct configuration when switching
- **Array Management**: Add/remove/reorder array items with full UI controls
The system now provides the complete executor configuration experience you were looking for - users can select both the executor type AND the specific profile/variant, then configure each one with a rich, schema-driven form interface.
* Cleanup script changes for task attempt 4b73f801-0ab1-4859-982e-ea6a0bf9c814
* improvements
* append_prompt
* generate forms
* order
* settings
* amp MCP config update
* form styles
* textarea
* style additional params
* validate
* menu styles
* prevent reload
* fmt
* add and delete configurations
* lint
* fmnt
* clippy
* prettier
* copy
* remove old MCP
* Auto detect schemas on FE
* wipe shared before generation
* fmt
* clippy fmt
* fixes
* fmt
* update shared types check
* disable clippy for large enum
* copy
* tweaks
* fmt
* fmt
* feat: add availability check for coding agents and set smart defaults for new users
* Add executor discovery (vibe-kanban d65d61aa)
Plan: Add executor discovery with appropriate checks
Understanding
You're absolutely right! Checking if npx is available is useless for Opencode/Qwen since it doesn't tell us if those specific agents have been set up. We should follow the pattern used by other executors:
Binary-based executors (like Cursor): Check if the binary exists
NPX-based executors (like Claude, Gemini, Opencode, Qwen): Check for their settings files
Implementation Plan
1. Cursor executor (cursor.rs, after line 407)
Since Cursor uses a standalone binary:
async fn check_availability(&self) -> bool {
utils::shell::resolve_executable_path("cursor-agent").is_some()
}
Import needed: Add shell::resolve_executable_path to the utils import
2. Opencode executor (opencode.rs, after line 188)
Follow the pattern of other NPX-based executors - check for settings file:
async fn check_availability(&self) -> bool {
self.default_mcp_config_path()
.map(|path| path.exists())
.unwrap_or(false)
}
This will check for the opencode.json file in the appropriate location (XDG on Unix, config_dir on Windows).
3. QwenCode executor (qwen.rs, after line 140)
Same approach as other NPX-based executors:
async fn check_availability(&self) -> bool {
self.default_mcp_config_path()
.map(|path| path.exists())
.unwrap_or(false)
}
This will check for ~/.qwen/settings.json.
Why this approach is correct:
Cursor: Has a specific binary that must be installed → check for binary
Opencode/Qwen: Are NPX-based like Claude/Gemini → check for settings files
Consistency: Follows the existing pattern where NPX-based executors check for settings files
Meaningful detection: Settings files indicate the agent has been configured/used before, which is what we want for "availability"
This gives us meaningful availability detection that matches the existing patterns in the codebase.
* Remove duplicated config paths (vibe-kanban 207e0410)
In some executors, like crates/executors/src/executors/amp.rs , Paths for checking availability and mcp server are identical but not reused. We should not duplicate code. Consider changing the default availability check to just check for the mcp config
* feat: implement recommended executor profile retrieval for new users
* fmt
* Make variants an object rather than array (vibe-kanban 63213864)
Profile variants should be an object, with key used instead of the current label.
The code should be refactored leaving no legacy trace.
crates/server/src/routes/config.rs
crates/executors/src/profile.rs
* Make variants an object rather than array (vibe-kanban 63213864)
Profile variants should be an object, with key used instead of the current label.
The code should be refactored leaving no legacy trace.
crates/server/src/routes/config.rs
crates/executors/src/profile.rs
* Remove the command builder from profiles (vibe-kanban d30abc92)
It should no longer be possible to customise the command builder in profiles.json.
Instead, anywhere where the command is customised, the code should be hardcoded as an enum field on the executor, eg claude code vs claude code router on the claude code struct.
crates/executors/src/profile.rs
crates/executors/src/executors/claude.rs
* fmt
* Refactor Qwen log normalization (vibe-kanban 076fdb3f)
Qwen basically uses the same log normalization as Gemini, can you refactor the code to make it more reusable.
A similar example exists in Amp, where we use Claude's log normalization.
crates/executors/src/executors/amp.rs
crates/executors/src/executors/qwen.rs
crates/executors/src/executors/claude.rs
* Add field overrides to executors (vibe-kanban cc3323a4)
We should add optional fields 'base_command_override' (String) and 'additional_params' (Vec<String>) to each executor, and wire these fields up to the command builder
* Update profiles (vibe-kanban e7545ab6)
Redesign the profile configuration storage system to store only differences from defaults instead of complete profile files. Implement partial profile functions (create_partial_profile, load_from_partials, save_as_diffs) that save human-readable partial profiles containing only changed values. Update ProfileConfigs::load() to handle the new partial format while maintaining backward compatibility with legacy full profile formats through automatic migration that creates backups. Implement smart variants handling that only stores changed, added, or removed variants rather than entire arrays. Fix the profile API consistency issue by replacing the manual file loading logic in the get_profiles() endpoint in crates/server/src/routes/config.rs with ProfileConfigs::get_cached() to ensure the GET endpoint uses the same cached data that PUT updates. Add comprehensive test coverage for all new functionality.
* Yolo mode becomes a field (vibe-kanban d8dd02f0)
Most executors implement some variation of yolo-mode, can you make this boolean field on each executor (if supported), where the name for the field aligns with the CLI field
* Change ClaudeCodeVariant to boolean (vibe-kanban cc05956f)
Instead of an enum ClaudeCodeVariant, let's use a variable claude_code_router to determine whether to use claude_code_router's command. If the user has also supplied a base_command_override this should take precedence (also write a warning to console)
crates/executors/src/executors/claude.rs
* Remove mcp_config_path from profile config (vibe-kanban 6c1e5947)
crates/executors/src/profile.rs
* One profile per executor (vibe-kanban b0adc27e)
Currently you can define arbitrary profiles, multiple profiles per executor. Let's refactor to simplify this configuration, instead we should only be able to configure one profile per executor.
The new format should be something like:
```json
{
"profiles": {
"CLAUDE_CODE": {
"default": {
"plan": false,
"dangerously_skip_permissions": true,
"append_prompt": null
},
"plan": {
"plan": true,
"dangerously_skip_permissions": false,
"append_prompt": null
}
}
}
}
```
Each profile's defaults should be defined as code instead of in default_profiles.json
profile.json will now contain:
- Overrides for default configurations
- Additional user defined configurations, for executors
It is not possible to remove a default configuration entirely, just override the configuration.
The user profile.json should still be a minimal set of overrides, to make upgrading easy.
Don't worry about migration, this will be done manually.
crates/executors/default_profiles.json
crates/executors/src/profile.rs
* SCREAMING_SNAKE_CASE
* update profile.rs
* config migration
* fmt
* delete binding
* config keys
* fmt
* shared types
* Profile variants should be saved as SCREAMING_SNAKE_CASE (vibe-kanban 5c6c124c)
crates/executors/src/profile.rs save_overrides
* rename default profiles
* remove defaulted executor fields
* backwards compatability
* fix legacy variants
* ## ✅ Implementation Complete!
I've successfully implemented the duplicate task feature. Here's what was accomplished:
### **Changes Made:**
1. **TaskDialogContext (`frontend/src/contexts/task-dialog-context.tsx`)**
- Added `initialTask: Task | null` to dialog state
- Created `openDuplicate(task, options)` method that opens create dialog with initial data
- Updated all existing methods to include initialTask field
2. **TaskFormDialog (`frontend/src/components/tasks/TaskFormDialog.tsx`)**
- Added `initialTask?: Task | null` prop
- Enhanced prefill logic with priority: Edit → Duplicate → Template → Empty
- Duplicated tasks reset status to 'todo' and start with no images
3. **TaskCard (`frontend/src/components/tasks/TaskCard.tsx`)**
- Added Copy icon import
- Added `onDuplicate?: (task: Task) => void` prop
- Added "Duplicate" menu item with Copy icon between Edit and Delete
4. **TaskKanbanBoard (`frontend/src/components/tasks/TaskKanbanBoard.tsx`)**
- Added `onDuplicateTask?: (task: Task) => void` prop
- Passed duplicate handler through to TaskCard components
5. **ProjectTasks (`frontend/src/pages/project-tasks.tsx`)**
- Added `openDuplicate` to useTaskDialog destructuring
- Created `handleDuplicateTask` function
- Passed duplicate handler to TaskKanbanBoard
6. **TaskFormDialogContainer (`frontend/src/components/tasks/TaskFormDialogContainer.tsx`)**
- Added `initialTask={dialogState.initialTask}` prop to TaskFormDialog
### **How It Works:**
1. **User clicks** the "⋯" menu on any task card
2. **Sees "Duplicate"** option with copy icon between Edit and Delete
3. **Clicks Duplicate** → opens create task dialog with:
- Title and description pre-filled from original task
- Status reset to 'todo'
- No images (clean slate)
- User can modify and create as normal
### **Key Design Decisions:**
- **Treated as create mode** (not edit) - follows Oracle's recommendation
- **Status always resets to 'todo'** for duplicated tasks
- **No images copied** - simple and safe approach
- **Clean integration** with existing template system
The implementation passes all TypeScript checks and follows the existing codebase patterns. The feature is ready to use!
* Cleanup script changes for task attempt 16b21999-278c-414d-aaab-ae5767d42d77
* Perfect! All tests are now passing. Let me create a summary of what was accomplished:
## ✅ Implementation Complete
**Successfully migrated Amp to use Claude's log normalization while maintaining the Amp executor:**
### Changes Made:
1. **Profile Update** ([`default_profiles.json`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-4b7b-amp-now-su/crates/executors/default_profiles.json#L55-L67))
- ✅ Updated to `@sourcegraph/amp@latest`
- ✅ Replaced `--format=jsonl` with `--stream-json`
2. **Shared Log Processor** ([`claude.rs`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-4b7b-amp-now-su/crates/executors/src/executors/claude.rs#L154-L168))
- ✅ Made `ClaudeLogProcessor` struct and `process_logs` method `pub`
- ✅ Removed unused executor parameter from `process_logs`
- ✅ Updated Claude executor call site
3. **Amp Executor Simplification** ([`amp.rs`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-4b7b-amp-now-su/crates/executors/src/executors/amp.rs#L101-L109))
- ✅ Replaced entire `normalize_logs` implementation with shared `ClaudeLogProcessor`
- ✅ Deleted 400+ lines of Amp-specific JSON parsing code
- ✅ Kept spawn/follow-up logic intact (preserving `threads continue` functionality)
4. **Test Updates** ([`profile.rs`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-4b7b-amp-now-su/crates/executors/src/profile.rs#L210-L211))
- ✅ Updated test assertions for new Amp profile configuration
### Benefits Achieved:
- **✅ No Code Duplication**: Single source of truth for stream JSON log normalization
- **✅ 100% Claude Compatibility**: Amp now uses identical log parsing as Claude
- **✅ Preserved Functionality**: All spawn/follow-up logic maintained
- **✅ No Breaking Changes**: Existing Amp executor structure preserved
- **✅ Passing Tests**: All 48 tests pass successfully
- **✅ Clean Build**: No compilation errors, only benign warnings
**Amp now supports parsing logs in the same way as Claude with shared log normalization! 🎉**
* Cleanup script changes for task attempt 4b7b3780-24e9-40e5-b52b-5bd86c37257e
* ## Corrected Plan
You're absolutely right - I overcomplicated this! The Oracle confirmed my analysis:
### **Root Cause**
The error `--stream-json flag requires --execute mode` was simply because the Amp profile was missing the `--execute` flag, not because of how we pass prompts.
### **Correct Fix**
1. **✅ Keep the profile change**: Already added `--execute` flag to [`default_profiles.json`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-4b7b-amp-now-su/crates/executors/default_profiles.json#L60)
2. **🔄 Revert executor changes**: Restore the original stdin-based approach in [`amp.rs`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-4b7b-amp-now-su/crates/executors/src/executors/amp.rs#L25-47) since both methods work with `--execute`
3. **✅ Keep shared log normalization**: All the Claude log processor sharing remains unchanged
### **Why This Works**
According to Amp docs, `--execute` supports both:
- `echo "prompt" | amp --execute --stream-json` (current approach)
- `amp --execute "prompt" --stream-json` (what I tried to implement)
Since our current stdin approach works fine with `--execute`, I just need to:
- Revert the spawn method to use stdin (like it was originally)
- Keep the `--execute` flag in the profile
- Keep all the log normalization improvements
**Ready to proceed with this minimal fix?**
* Cleanup script changes for task attempt 4b7b3780-24e9-40e5-b52b-5bd86c37257e
* ## ✅ Fix Complete
**Successfully resolved the `--stream-json flag requires --execute mode` error with a minimal fix:**
### **Changes Made:**
1. **✅ Profile Fix** ([`default_profiles.json`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-4b7b-amp-now-su/crates/executors/default_profiles.json#L60))
- Added `--execute` flag to Amp profile parameters
2. **✅ Restored Stdin Approach** ([`amp.rs`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-4b7b-amp-now-su/crates/executors/src/executors/amp.rs#L25-53))
- Reverted to original stdin-based prompt feeding
- Removed unnecessary command-line argument approach
3. **✅ Updated Tests** ([`profile.rs`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-4b7b-amp-now-su/crates/executors/src/profile.rs#L210-212))
- Added assertion for `--execute` flag in profile tests
### **Final Configuration:**
```json
"AMP": {
"command": {
"base": "npx -y @sourcegraph/amp@latest",
"params": [
"--execute",
"--stream-json",
"--dangerously-allow-all"
]
}
}
```
### **Result:**
- **✅ Error Resolved**: The `--stream-json flag requires --execute mode` error should now be fixed
- **✅ Shared Log Normalization**: Amp still uses Claude's log processor (no code duplication)
- **✅ All Tests Pass**: 48/48 tests passing
- **✅ Clean Build**: No compilation errors
**Amp now properly supports `--stream-json` with shared Claude-compatible log normalization! 🎉**
* pin working version
* Parse AMP tools
* Merge main
* Restore AMP threads message deduplication
* rollback DiffChangeKind
* lint
---------
Co-authored-by: Solomon <abcpro11051@disroot.org>
* ## Implementation Complete ✅
I've successfully implemented the feature to skip running cleanup scripts when no changes are made during coding agent execution.
### **Changes Made**
1. **Modified [`GitService::commit()`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-92b8-skip-runni/crates/services/src/services/git.rs#L174-L218)**:
- Changed return type from `Result<(), GitServiceError>` to `Result<bool, GitServiceError>`
- Returns `Ok(false)` when no changes to commit
- Returns `Ok(true)` when changes are committed
2. **Updated [`Container` trait](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-92b8-skip-runni/crates/services/src/services/container.rs#L125)**:
- Changed `try_commit_changes()` signature to return `Result<bool, ContainerError>`
3. **Updated [`LocalContainerService`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-92b8-skip-runni/crates/local-deployment/src/container.rs#L889-L954)**:
- Modified implementation to propagate commit feedback
- Returns `false` for non-commit operations, `true`/`false` based on git changes
4. **Enhanced [execution monitor logic](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-92b8-skip-runni/crates/local-deployment/src/container.rs#L335-L374)**:
- Conditionally calls `try_start_next_action()` based on whether changes were committed
- Skips cleanup script when coding agent made no changes
- Preserves existing behavior for setup scripts (always proceed to coding agent)
- Added informative logging when cleanup is skipped
### **Behavior**
**Before:**
```
CodingAgent (no changes) → try_commit_changes() → CleanupScript (always runs)
```
**After:**
```
CodingAgent (no changes) → try_commit_changes() returns false → Skip CleanupScript ✅
CodingAgent (has changes) → try_commit_changes() returns true → CleanupScript runs ✅
```
### **Safety Features**
- **Conservative error handling**: Commit failures are treated as "changes made" to ensure cleanup runs
- **Preserved workflows**: Setup scripts always proceed to coding agent (unchanged)
- **Informative logging**: Clear indication when cleanup is skipped
- **Type safety**: Compiler enforces correct return types throughout the call chain
### **Verification**
- ✅ Code compiles successfully
- ✅ All existing tests pass (47/47)
- ✅ Type checker passes
- ✅ No breaking changes to other parts of the codebase
The implementation is complete and ready for use!
* Cleanup script changes for task attempt 92b80e80-dbc1-470c-a3c8-172c38549b61
* Cleanup script changes for task attempt 92b80e80-dbc1-470c-a3c8-172c38549b61
* ## Task Status Fix Complete ✅
I've successfully fixed the issue where tasks weren't transitioning from `InProgress` to `InReview` when cleanup scripts are skipped.
### **Changes Made**
1. **Created [`finalize_task()` helper method](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-92b8-skip-runni/crates/local-deployment/src/container.rs#L116-L128)**:
```rust
async fn finalize_task(
db: &DBService,
config: &Arc<RwLock<Config>>,
ctx: &ExecutionContext,
) {
// Updates task status to InReview
// Sends notifications via NotificationService
}
```
2. **Added manual finalization when skipping cleanup** ([lines 389-391](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-92b8-skip-runni/crates/local-deployment/src/container.rs#L389-L391)):
```rust
} else {
tracing::info!("Skipping cleanup script - no changes made by coding agent");
// Manually finalize task since we're bypassing normal execution flow
Self::finalize_task(&db, &config, &ctx).await;
}
```
3. **Refactored existing finalization** to use the helper method ([line 395](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-92b8-skip-runni/crates/local-deployment/src/container.rs#L395-L397)):
```rust
if Self::should_finalize(&ctx) {
Self::finalize_task(&db, &config, &ctx).await;
}
```
### **Fixed Flow**
**Before (Broken):**
```
CodingAgent (no changes) → Skip cleanup → should_finalize() = false → Task stuck in InProgress ❌
```
**After (Fixed):**
```
CodingAgent (no changes) → Skip cleanup → Manual finalize_task() → Task → InReview ✅
CodingAgent (has changes) → Cleanup runs → should_finalize() = true → Task → InReview ✅
```
### **Benefits**
- ✅ **Fixes the bug**: Tasks now properly transition to `InReview` when cleanup is skipped
- ✅ **DRY principle**: Reuses finalization logic instead of duplicating
- ✅ **No double finalization**: Helper is idempotent and safely reusable
- ✅ **Preserves notifications**: Same notification behavior as normal cleanup completion
- ✅ **Clean separation**: `should_finalize()` logic unchanged for normal flows
### **Verification**
- ✅ Code compiles successfully
- ✅ All tests pass (47/47)
- ✅ Type checker passes
- ✅ Same finalization behavior for both paths
The complete feature is now implemented: cleanup scripts are skipped when no changes are made during coding agent execution, AND tasks properly transition to `InReview` status in both scenarios!
* Cleanup script changes for task attempt 92b80e80-dbc1-470c-a3c8-172c38549b61
* ## UI Copy Updates Complete ✅
I've successfully updated the project settings UI to clearly communicate that the cleanup script only runs when changes are made by the coding agent.
### **Changes Made**
1. **Updated description text** in [`project-form-fields.tsx`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-92b8-skip-runni/frontend/src/components/projects/project-form-fields.tsx#L249-L253):
```diff
- This script will run after coding agent execution is complete.
+ This script runs after coding agent execution only if changes were made.
+ Use it for quality assurance tasks like running linters, formatters, tests,
+ or other validation steps. If no changes are made, this script is skipped.
```
2. **Updated Unix placeholder** in [`script-placeholders.ts`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-92b8-skip-runni/frontend/src/utils/script-placeholders.ts#L36-L38):
```diff
- # This runs after coding agent execution
+ # This runs after coding agent execution - only if changes were made
```
3. **Updated Windows placeholder** in [`script-placeholders.ts`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-92b8-skip-runni/frontend/src/utils/script-placeholders.ts#L20-L22):
```diff
- REM This runs after coding agent execution
+ REM This runs after coding agent execution - only if changes were made
```
### **User Experience**
Now when users configure a cleanup script in project settings, they will see:
**Label**: "Cleanup Script (Optional)"
**Description**:
> This script runs after coding agent execution **only if changes were made**. Use it for quality assurance tasks like running linters, formatters, tests, or other validation steps. If no changes are made, this script is skipped.
**Placeholder text**:
```bash
#!/bin/bash
# Add cleanup commands here...
# This runs after coding agent execution - only if changes were made
```
### **Benefits**
- ✅ **Clear expectations**: Users understand the conditional behavior upfront
- ✅ **Emphasized condition**: "only if changes were made" is bolded for visibility
- ✅ **Comprehensive coverage**: Updated both description and placeholder text
- ✅ **Cross-platform**: Updated both Unix and Windows placeholders
- ✅ **TypeScript verified**: Frontend code compiles successfully
Users will now have clear visibility into when their cleanup scripts will and won't run, preventing any confusion about the new conditional execution behavior!
* Cleanup script changes for task attempt 92b80e80-dbc1-470c-a3c8-172c38549b61
* wip: backend todo normalisation
* fe implementation
* remove unused dep
* cursor return ActionType::TodoManagement
* use lucide icons rather than emojis in the todo list
* review comments