From dfa4a3369f237584fc6372109a0512d08bd462de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Flor=C3=AAncio?= Date: Sun, 29 Mar 2026 11:36:07 +0100 Subject: [PATCH] feat: add Feature Dev workflow and improve default workflow prompts (#481) --- .../backend/config/workflows/architecture.yml | 30 +- apps/backend/config/workflows/feature-dev.yml | 266 ++++++++++++++++++ apps/backend/config/workflows/loader_test.go | 135 +++++++++ .../config/workflows/plan-and-build.yml | 48 +++- apps/backend/config/workflows/pr-review.yml | 11 +- .../workspace/workspace-workflows-dialogs.tsx | 7 +- 6 files changed, 464 insertions(+), 33 deletions(-) create mode 100644 apps/backend/config/workflows/feature-dev.yml create mode 100644 apps/backend/config/workflows/loader_test.go diff --git a/apps/backend/config/workflows/architecture.yml b/apps/backend/config/workflows/architecture.yml index 5652048f29..62a892d8c5 100644 --- a/apps/backend/config/workflows/architecture.yml +++ b/apps/backend/config/workflows/architecture.yml @@ -20,24 +20,36 @@ steps: allow_manual_move: true prompt: | [ARCHITECTURE PHASE] - Analyze and design the architecture for this task. + Analyze and design the architecture for this task. Do NOT write any code. - Before creating the design, ask the user clarifying questions if anything is unclear or ambiguous about the requirements. Use the ask_user_question_kandev tool to get answers before proceeding. + {{task_prompt}} - When including diagrams in your design (architecture, sequence, flowcharts, etc.), always use mermaid syntax in code blocks. + STEP 1: UNDERSTAND THE REQUIREMENTS + If anything is unclear or ambiguous, ask the user clarifying questions using the ask_user_question_kandev tool before proceeding. + + STEP 2: EXPLORE THE CODEBASE + - Find similar features and understand how they are architected. + - Identify existing patterns, abstractions, and conventions. + - Map integration points, data flow, and system boundaries. + + STEP 3: DESIGN THE ARCHITECTURE + Create a design that includes: + 1. Component overview — what each component does and how they interact + 2. Interfaces and contracts — how components communicate (APIs, events, shared types) + 3. Data flow — how data moves through the system from input to output + 4. File structure — which files will be created or modified + 5. Trade-offs — alternative approaches considered and why the recommended one was chosen + 6. Risks and open questions — what could go wrong, what needs further investigation + + When including diagrams (architecture, sequence, flowcharts, etc.), always use mermaid syntax in code blocks. IMPORTANT: Save your design using the create_task_plan_kandev MCP tool with the task_id provided in the session context. After saving the plan, STOP and wait for user review. The user will review your design in the UI and may edit it. - Do not create any other files during this phase - only use the MCP tool to save the plan. - - {{task_prompt}} + Do not create any other files during this phase — only use the MCP tool to save the plan. events: on_enter: - type: enable_plan_mode - type: auto_start_agent - on_turn_complete: - - type: disable_plan_mode - - type: move_to_next - id: review name: Review diff --git a/apps/backend/config/workflows/feature-dev.yml b/apps/backend/config/workflows/feature-dev.yml new file mode 100644 index 0000000000..0a4a62842c --- /dev/null +++ b/apps/backend/config/workflows/feature-dev.yml @@ -0,0 +1,266 @@ +id: feature-dev +name: Feature Dev +description: >- + Full development lifecycle: spec with user review, implementation with TDD, + automated code review, QA verification, draft PR, and CI fixup. Ideal for + features that need quality gates between phases. + +steps: + - id: todo + name: Todo + position: 0 + color: bg-neutral-400 + allow_manual_move: true + + - id: spec + name: Spec + position: 1 + color: bg-purple-500 + is_start_step: true + show_in_command_panel: true + allow_manual_move: true + prompt: | + [SPEC PHASE] + Analyze this task and create a detailed implementation plan. Do NOT write any code yet. + + {{task_prompt}} + + STEP 1: UNDERSTAND THE PROBLEM + - If anything is unclear or ambiguous, ask the user clarifying questions using the ask_user_question_kandev tool before proceeding. + - Identify: what problem is being solved, who benefits, what are the constraints. + + STEP 2: EXPLORE THE CODEBASE + - Find similar features and understand how they are implemented. + - Identify the architecture and patterns in the relevant area. + - Map integration points, data flow, and extension points. + - Check if the repo has a decision log (e.g. docs/decisions/) and read relevant decisions. + + STEP 3: DESIGN THE SOLUTION + - Propose 2-3 approaches with trade-offs and your recommendation. + - Map which files will be created or modified and what each is responsible for. + - When including diagrams (architecture, sequence, flowcharts), use mermaid syntax in code blocks. + + IMPORTANT: Save your plan using the create_task_plan_kandev MCP tool with the task_id provided in the session context. + After saving the plan, STOP and wait for user review. The user will review your plan in the UI and may edit it. + Do not create any other files during this phase — only use the MCP tool to save the plan. + events: + on_enter: + - type: enable_plan_mode + - type: auto_start_agent + on_exit: + - type: disable_plan_mode + + - id: work + name: Work + position: 2 + color: bg-blue-500 + show_in_command_panel: true + allow_manual_move: true + prompt: | + [WORK PHASE] + Implement the task following the approved plan. + + {{task_prompt}} + + STEP 1: RETRIEVE THE PLAN + Before starting, retrieve the task plan using get_task_plan_kandev with the task_id from the session context. + Review the plan carefully, including any edits the user may have made. + Acknowledge the plan and any user modifications before proceeding. + + STEP 2: IMPLEMENT + Use a TDD strategy — for each behavior: + + 1. Write a failing test that asserts the expected behavior + 2. Run the test — confirm it fails with the expected assertion error (not a compile error) + 3. Write the minimum code to make it pass + 4. Run the test — confirm it passes + 5. Refactor while keeping tests green + 6. Commit the change + + Build incrementally — one behavior at a time, tests passing at every step. + Follow existing codebase conventions (naming, patterns, file organization). + You can update the plan during implementation using update_task_plan_kandev if needed. + + STEP 3: STOP CONDITIONS + - If you hit a blocker (missing dependency, unclear requirement, test fails repeatedly): stop and ask the user. + - If a fix requires an architectural change (new DB table, new service layer, switching libraries): stop and ask. + - After 3 failed fix attempts on the same issue: stop, question the approach, ask the user. + events: + on_enter: + - type: auto_start_agent + + - id: review + name: Review + position: 3 + color: bg-yellow-500 + show_in_command_panel: true + allow_manual_move: true + prompt: | + [REVIEW PHASE] + Review the changes made in the Work phase for quality, security, and correctness. + + {{task_prompt}} + + STEP 1: DETERMINE WHAT TO REVIEW + Determine the default branch (e.g. main, master) and diff against it: + - Run: git remote show origin | grep 'HEAD branch' to find the default branch name + - Run: git diff origin/...HEAD --name-only to get the list of changed files + Read each changed file in full — understand the surrounding code, not just the diff. + + STEP 2: REVIEW THE CHANGES + Review across these layers (skip layers that don't apply): + + Security (blockers if found): + - No secrets, tokens, or credentials in code + - Input validation at system boundaries + - No SQL injection, XSS, command injection, or path traversal + - Auth and authorization checks on new endpoints + + Logic & correctness: + - Edge cases handled (empty input, nil/null, zero, max values) + - Error paths covered and not silently swallowed + - Race conditions in concurrent code + + Performance: + - No N+1 queries (loop with individual DB calls) + - No memory leaks (unclosed connections, streams, listeners) + + Code quality: + - No dead code, unused imports, or commented-out code + - No speculative code (unused flags, one-off abstractions with single call site) + - Deep nesting (>3 levels) — suggest early returns + + STEP 3: FIX OR REPORT + - Fix directly any issues you can resolve confidently (dead code, unused imports, missing early returns). + - For issues needing the author's input, report with file:line, why it matters, and how to fix. + - Only report findings you're >=80% confident about. + + Do NOT report issues on code that was not modified in this branch. + events: + on_enter: + - type: reset_agent_context + - type: auto_start_agent + + - id: qa + name: QA + position: 4 + color: bg-orange-500 + show_in_command_panel: true + allow_manual_move: true + prompt: | + [QA PHASE] + Verify the feature works end-to-end. Your goal is to find bugs, not confirm it works. + + {{task_prompt}} + + STEP 1: UNDERSTAND WHAT WAS BUILT + Read the task description and recent commits to understand what the feature should do. + Retrieve the task plan using get_task_plan_kandev if available. + + STEP 2: TRACE THE WIRING + Before testing behavior, verify the feature is actually connected: + - Exports are imported and used (not just defined) + - API routes have consumers + - Data flows end-to-end: input -> handler -> storage -> response -> display + + STEP 3: TEST THE HAPPY PATH + Run the feature as intended. For backend changes, call the API. For frontend changes, trace the UI flow. + + STEP 4: TRY TO BREAK IT + Systematically test: + - Boundary values: empty input, nil/null, zero, negative, max values, very long strings + - Error paths: what happens when dependencies fail? + - Concurrency: simultaneous requests to the same resource + - Authorization: can the feature be accessed without proper auth? + + STEP 5: VERIFY TEST COVERAGE + Check that the implementation has tests covering the behaviors you verified. + If tests are missing for critical paths, write them. + + STEP 6: REPORT + Summarize: what was verified working, what issues were found (with file:line and how to reproduce), and what test coverage is missing. + events: + on_enter: + - type: auto_start_agent + + - id: pr + name: PR + position: 5 + color: bg-indigo-500 + show_in_command_panel: true + allow_manual_move: true + prompt: | + [PR PHASE] + Create a draft pull request for the changes. + + {{task_prompt}} + + STEP 1: PREPARE + - Run formatters and linters to ensure code is clean. + - Stage and commit any remaining changes. + - Push the branch to origin. + + STEP 2: CHECK FOR PR TEMPLATE + Look for a pull request template in the repo: + - .github/pull_request_template.md + - .github/PULL_REQUEST_TEMPLATE.md + - docs/pull_request_template.md + If found, read it and follow its structure for the PR body. + + STEP 3: CREATE DRAFT PR + Create the PR as a draft: + ```bash + gh pr create --draft --title ": " --body "" + ``` + - Title should follow Conventional Commits format if the repo uses it. + - If no PR template was found, the body should include: summary of what was built and why, validation steps, and a checklist. + + STEP 4: REPORT + Return the PR URL. + events: + on_enter: + - type: auto_start_agent + + - id: ci-fixup + name: CI Fixup + position: 6 + color: bg-amber-500 + show_in_command_panel: true + allow_manual_move: true + prompt: | + [CI FIXUP PHASE] + Wait for CI checks to complete and fix any failures. + + {{task_prompt}} + + STEP 1: FIND THE PR + Run gh pr list --head $(git branch --show-current) to find the PR number. + + STEP 2: WAIT FOR CI + Poll CI checks until they all resolve: + ```bash + gh pr checks + ``` + - Poll every 30 seconds, cap at 10 minutes. + - Once done, note which checks passed and which failed. + + STEP 3: FIX FAILURES + If any CI checks failed: + 1. Identify the failed run from gh pr checks output. + 2. Fetch failed logs: gh run view --log-failed + 3. Read the relevant source files at the failing lines. + 4. Fix the issues (lint errors, test failures, type errors). + 5. Commit and push the fix. + 6. Go back to STEP 2 and verify the fix passes. + + STEP 4: REPORT + When all checks pass, report the CI status and the PR URL. + events: + on_enter: + - type: auto_start_agent + + - id: done + name: Done + position: 7 + color: bg-green-500 + allow_manual_move: true diff --git a/apps/backend/config/workflows/loader_test.go b/apps/backend/config/workflows/loader_test.go new file mode 100644 index 0000000000..5968a89c8c --- /dev/null +++ b/apps/backend/config/workflows/loader_test.go @@ -0,0 +1,135 @@ +package workflows + +import ( + "fmt" + "testing" +) + +func TestLoadTemplates_AllValid(t *testing.T) { + templates, err := LoadTemplates() + if err != nil { + t.Fatalf("LoadTemplates() returned error: %v", err) + } + if len(templates) == 0 { + t.Fatal("LoadTemplates() returned no templates") + } + for _, tmpl := range templates { + if tmpl.ID == "" { + t.Error("template has empty ID") + } + if tmpl.Name == "" { + t.Errorf("template %q has empty name", tmpl.ID) + } + if len(tmpl.Steps) == 0 { + t.Errorf("template %q has no steps", tmpl.ID) + } + } +} + +func TestLoadTemplates_EachHasStartStep(t *testing.T) { + templates, err := LoadTemplates() + if err != nil { + t.Fatalf("LoadTemplates() returned error: %v", err) + } + + for _, tmpl := range templates { + startCount := 0 + for _, step := range tmpl.Steps { + if step.IsStartStep { + startCount++ + } + } + if startCount == 0 { + t.Errorf("template %q has no step with is_start_step: true", tmpl.ID) + } + if startCount > 1 { + t.Errorf("template %q has %d start steps (expected 1)", tmpl.ID, startCount) + } + } +} + +func TestLoadTemplates_MoveToStepReferencesExist(t *testing.T) { + templates, err := LoadTemplates() + if err != nil { + t.Fatalf("LoadTemplates() returned error: %v", err) + } + + for _, tmpl := range templates { + stepIDs := make(map[string]bool) + for _, step := range tmpl.Steps { + stepIDs[step.ID] = true + } + + for _, step := range tmpl.Steps { + // Collect all move_to_step configs from all event types + var configs []map[string]interface{} + for _, a := range step.Events.OnTurnStart { + if a.Config != nil { + configs = append(configs, a.Config) + } + } + for _, a := range step.Events.OnTurnComplete { + if a.Config != nil { + configs = append(configs, a.Config) + } + } + + for _, cfg := range configs { + stepID, ok := cfg["step_id"] + if !ok { + continue + } + ref := fmt.Sprintf("%v", stepID) + if !stepIDs[ref] { + t.Errorf("template %q, step %q: move_to_step references %q which does not exist", + tmpl.ID, step.ID, ref) + } + } + } + } +} + +func TestLoadTemplates_StepPositionsUnique(t *testing.T) { + templates, err := LoadTemplates() + if err != nil { + t.Fatalf("LoadTemplates() returned error: %v", err) + } + + for _, tmpl := range templates { + positions := make(map[int]string) + for _, step := range tmpl.Steps { + if existing, ok := positions[step.Position]; ok { + t.Errorf("template %q: steps %q and %q share position %d", + tmpl.ID, existing, step.ID, step.Position) + } + positions[step.Position] = step.ID + } + } +} + +func TestLoadTemplates_ExpectedTemplateIDs(t *testing.T) { + templates, err := LoadTemplates() + if err != nil { + t.Fatalf("LoadTemplates() returned error: %v", err) + } + + expected := map[string]bool{ + "simple": false, + "standard": false, + "architecture": false, + "pr-review": false, + "feature-dev": false, + } + + for _, tmpl := range templates { + if _, ok := expected[tmpl.ID]; ok { + expected[tmpl.ID] = true + } + } + + for id, found := range expected { + if !found { + t.Errorf("expected template %q not found", id) + } + } +} diff --git a/apps/backend/config/workflows/plan-and-build.yml b/apps/backend/config/workflows/plan-and-build.yml index 69dd6d8fc0..29ebca87e6 100644 --- a/apps/backend/config/workflows/plan-and-build.yml +++ b/apps/backend/config/workflows/plan-and-build.yml @@ -21,23 +21,31 @@ steps: prompt: | [PLANNING PHASE] Analyze this task and create a detailed implementation plan. - Do NOT make any code changes yet - only analyze and plan. + Do NOT make any code changes yet — only analyze and plan. - Before creating the plan, ask the user clarifying questions if anything is unclear or ambiguous about the requirements. Use the ask_user_question_kandev tool to get answers before proceeding. + {{task_prompt}} + STEP 1: UNDERSTAND THE REQUIREMENTS + If anything is unclear or ambiguous, ask the user clarifying questions using the ask_user_question_kandev tool before proceeding. + + STEP 2: EXPLORE THE CODEBASE + - Find similar features and understand how they are implemented. + - Identify the architecture and patterns in the relevant area. + - Map integration points and data flow. + + STEP 3: CREATE THE PLAN Create a plan that includes: 1. Understanding of the requirements - 2. Files that need to be modified or created + 2. Files that need to be modified or created, and what each is responsible for 3. Step-by-step implementation approach 4. Potential risks or considerations + 5. Alternative approaches considered and why the recommended one was chosen - When including diagrams in your plan (architecture, sequence, flowcharts, etc.), always use mermaid syntax in code blocks. + When including diagrams (architecture, sequence, flowcharts, etc.), always use mermaid syntax in code blocks. IMPORTANT: Save your plan using the create_task_plan_kandev MCP tool with the task_id provided in the session context. After saving the plan, STOP and wait for user review. The user will review your plan in the UI and may edit it. - Do not create any other files during this phase - only use the MCP tool to save the plan. - - {{task_prompt}} + Do not create any other files during this phase — only use the MCP tool to save the plan. events: on_enter: - type: enable_plan_mode @@ -51,19 +59,35 @@ steps: allow_manual_move: true prompt: | [IMPLEMENTATION PHASE] - Before starting implementation, retrieve the task plan using get_task_plan_kandev with the task_id from the session context. + Implement the task following the approved plan. + + {{task_prompt}} + + STEP 1: RETRIEVE THE PLAN + Before starting, retrieve the task plan using get_task_plan_kandev with the task_id from the session context. Review the plan carefully, including any edits the user may have made. Acknowledge the plan and any user modifications before proceeding. - Then implement the task following the plan step-by-step. + STEP 2: IMPLEMENT + Use a TDD strategy — for each behavior: + 1. Write a failing test that asserts the expected behavior + 2. Run the test — confirm it fails with the expected assertion error + 3. Write the minimum code to make it pass + 4. Run the test — confirm it passes + 5. Refactor while keeping tests green + 6. Commit the change + + Build incrementally — one behavior at a time, tests passing at every step. + Follow existing codebase conventions (naming, patterns, file organization). You can update the plan during implementation using update_task_plan_kandev if needed. - {{task_prompt}} + STEP 3: STOP CONDITIONS + - If you hit a blocker (missing dependency, unclear requirement, test fails repeatedly): stop and ask the user. + - If a fix requires an architectural change (new DB table, new service layer, switching libraries): stop and ask. + - After 3 failed fix attempts on the same issue: stop, question the approach, ask the user. events: on_enter: - type: auto_start_agent - on_turn_complete: - - type: move_to_next - id: done name: Done diff --git a/apps/backend/config/workflows/pr-review.yml b/apps/backend/config/workflows/pr-review.yml index 3b59f95bed..3bac139673 100644 --- a/apps/backend/config/workflows/pr-review.yml +++ b/apps/backend/config/workflows/pr-review.yml @@ -39,11 +39,7 @@ steps: STEP 2: REVIEW THE CHANGES - Check if any code review skill is available (e.g. /code-review, /review, or similar). - If one exists, invoke it — it has project-specific rules. - Otherwise, use the fallback review below. - - FALLBACK REVIEW (skip layers that don't apply): + Review across these layers (skip layers that don't apply): Security (blockers if found): - No secrets, tokens, or credentials in code @@ -100,14 +96,9 @@ steps: events: on_enter: - type: auto_start_agent - on_turn_complete: - - type: move_to_next - id: done name: Done position: 2 color: bg-green-500 allow_manual_move: true - events: - on_turn_start: - - type: move_to_previous diff --git a/apps/web/app/settings/workspace/workspace-workflows-dialogs.tsx b/apps/web/app/settings/workspace/workspace-workflows-dialogs.tsx index 43bda6a2a3..fe65c10306 100644 --- a/apps/web/app/settings/workspace/workspace-workflows-dialogs.tsx +++ b/apps/web/app/settings/workspace/workspace-workflows-dialogs.tsx @@ -138,11 +138,14 @@ export function CreateWorkflowDialog({ }: CreateWorkflowDialogProps) { return ( - + Add Workflow -
+