Skip to content

Conversation

@Shironex
Copy link
Collaborator

@Shironex Shironex commented Jan 21, 2026

  • Added support for excluding specific pipeline steps in feature management, allowing users to skip certain steps during execution.
  • Introduced a new PipelineExclusionControls component for managing exclusions in the UI.
  • Updated relevant dialogs and components to handle excluded pipeline steps, including AddFeatureDialog, EditFeatureDialog, and MassEditDialog.
  • Enhanced the getNextStatus method in PipelineService to account for excluded steps when determining the next status in the pipeline flow.
  • Updated tests to cover scenarios involving excluded pipeline steps.
image image

Summary by CodeRabbit

  • New Features

    • Add per-feature pipeline exclusion UI (create/edit/mass-edit) and a board badge showing excluded steps with contextual tooltip.
    • Project-aware dialogs and views now surface pipeline exclusion controls.
  • Bug Fixes

    • Resume and progression flows updated to correctly skip excluded pipeline steps and gracefully complete when none remain.
  • Other

    • Public type surface expanded to include additional provider and pipeline-related types.

✏️ Tip: You can customize this high-level summary in your review settings.

webdevcody and others added 3 commits January 20, 2026 18:48
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added support for excluding specific pipeline steps in feature management, allowing users to skip certain steps during execution.
- Introduced a new `PipelineExclusionControls` component for managing exclusions in the UI.
- Updated relevant dialogs and components to handle excluded pipeline steps, including `AddFeatureDialog`, `EditFeatureDialog`, and `MassEditDialog`.
- Enhanced the `getNextStatus` method in `PipelineService` to account for excluded steps when determining the next status in the pipeline flow.
- Updated tests to cover scenarios involving excluded pipeline steps.
@Shironex Shironex self-assigned this Jan 21, 2026
@Shironex Shironex added the Enhancement Improvements to existing functionality or UI. label Jan 21, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @Shironex, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant enhancement to feature management by enabling the selective exclusion of custom pipeline steps. This allows for more flexible and tailored feature workflows, where certain automated stages can be bypassed as needed. The changes encompass both the server-side logic, ensuring that pipeline execution correctly accounts for excluded steps, and the user interface, providing intuitive controls for configuring these exclusions within various feature management dialogs. The overall impact is improved adaptability in handling diverse feature development processes.

Highlights

  • Pipeline Step Exclusion: Implemented functionality to allow users to exclude specific steps from a custom pipeline during feature execution, providing greater control over workflow.
  • UI Integration: Introduced a new PipelineExclusionControls component for managing excluded steps, integrated into AddFeatureDialog, EditFeatureDialog, and MassEditDialog.
  • Backend Logic Updates: Modified AutoModeService to filter out excluded pipeline steps during execution and enhanced PipelineService.getNextStatus to correctly determine the next status, skipping excluded steps.
  • Visual Indicators: Added a new badge to Kanban cards to visually indicate when a feature has excluded pipeline steps, showing the count of skipped steps.
  • Type and Test Coverage: Updated core Feature types to include excludedPipelineSteps and added comprehensive unit tests for the new exclusion logic in PipelineService.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link

coderabbitai bot commented Jan 21, 2026

📝 Walkthrough

Walkthrough

This PR adds per-feature pipeline step exclusions (types, UI controls, and plumbing) and updates backend pipeline progression to skip excluded steps, including resume handling when the current or all remaining steps are excluded. It also expands several provider/type exports and bumps package versions.

Changes

Cohort / File(s) Summary
Type exports & Feature model
libs/types/src/feature.ts, libs/types/src/index.ts, libs/types/README.md, apps/server/src/providers/types.ts, apps/server/src/providers/index.ts
Added excludedPipelineSteps?: string[] to Feature. Expanded re-exports to include provider types (AgentDefinition, ReasoningEffort, SystemPromptPreset, ConversationMessage, ContentBlock, ValidationResult, Mcp*ServerConfig variants, etc.).
Pipeline progression & resume logic
apps/server/src/services/pipeline-service.ts, apps/server/src/services/auto-mode-service.ts
getNextStatus gained excludedStepIds? to skip excluded steps. Auto-mode resume flow now inspects unfiltered steps, detects excluded current steps, computes next actionable status, and gracefully completes when no steps remain.
Backend tests
apps/server/tests/unit/services/pipeline-service.test.ts
New/expanded unit tests covering exclusion-driven transitions and edge cases (skipping single/multiple steps, all-steps-excluded, dynamic current-step exclusion, skipTests variations).
UI: Pipeline exclusion controls
apps/ui/src/components/views/board-view/shared/pipeline-exclusion-controls.tsx, apps/ui/src/components/views/board-view/shared/index.ts
New PipelineExclusionControls component: per-step toggles sourced from usePipelineConfig, visual indicators, "all steps disabled" message; exported from shared barrel.
UI: Dialogs & mass-edit integration
apps/ui/src/components/views/board-view/dialogs/add-feature-dialog.tsx, .../edit-feature-dialog.tsx, .../mass-edit-dialog.tsx
Added excludedPipelineSteps state to dialog payloads and forms; wired PipelineExclusionControls; projectPath prop propagated. MassEdit tracks apply-state for exclusions and conditionally applies updates.
UI: Board & cards
apps/ui/src/components/views/board-view.tsx, .../card-badges.tsx, .../kanban-card.tsx, apps/ui/src/components/views/graph-view-page.tsx
Propagated projectPath to dialogs and badges; PriorityBadges shows pipeline-exclusion badge when feature excludes steps. Minor dependency list adjustment for feature loading.
Package versions
apps/server/package.json, apps/ui/package.json, package.json
Version bumps for server, UI, and root package to 0.13.0.

Sequence Diagram

sequenceDiagram
    participant User as User (UI)
    participant Dialog as Edit/Add/MassEdit Dialog
    participant UI as BoardView / Badges
    participant Service as AutoModeService
    participant Pipeline as PipelineService
    participant DB as Feature Storage

    User->>Dialog: Toggle pipeline step exclusions & save
    Dialog->>DB: Persist feature with `excludedPipelineSteps`
    UI->>Service: Trigger resume/execute for feature
    Service->>Service: Build allSortedSteps (unfiltered)
    Service->>Service: Check if current step is excluded
    alt Current step is excluded
        Service->>Pipeline: getNextStatus(currentStatus, config, skipTests, excludedStepIds)
        Pipeline->>Pipeline: Filter steps by excludedStepIds and compute next status
        Pipeline-->>Service: Return next status
        alt Next status is pipeline step
            Service->>Service: Determine next start index and execute remaining non-excluded steps
        else Next status is final
            Service->>DB: Mark feature complete with final status
            Service->>UI: Emit completion event
        end
    else Current step not excluded
        Service->>Service: Execute filtered steps (omit exclusions)
    end
    alt No steps remain after filtering
        Service->>DB: Mark feature completed
        Service->>UI: Emit completion event
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

Ready-To-Merge

Poem

🐰 I nibble on steps one by one,
I skip the ones that dampen the fun.
Toggles, badges, types in a row,
Pipelines hop where the devs want to go.
Hop—exclusions saved—now on we run!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: implement pipeline step exclusion functionality' accurately and clearly describes the main change in the PR, which adds support for excluding pipeline steps across the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces functionality to exclude specific pipeline steps during feature execution, enhancing flexibility in workflow management. The changes span across backend services for logic implementation and frontend components for UI controls and visual indicators. The core logic for skipping excluded steps in PipelineService and AutoModeService appears robust, and the new UI components for managing these exclusions are well-integrated. Comprehensive test cases have been added to cover various scenarios of pipeline step exclusion, which is excellent for ensuring correctness.

…8936017583-e6ni

# Conflicts:
#	apps/ui/src/components/views/board-view.tsx
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/server/src/services/auto-mode-service.ts (1)

1730-1803: Resume step number can be off when earlier steps are excluded.
startFromStepIndex is based on the unfiltered list but is logged against the filtered length, which can yield confusing messages (e.g., “step 3/2”). Consider computing the display index relative to the filtered list.

🛠️ Suggested adjustment for display index
-    const sortedSteps = allSortedSteps.filter((step) => !excludedStepIds.has(step.id));
+    const sortedSteps = allSortedSteps.filter((step) => !excludedStepIds.has(step.id));
+    const resumeIndex = stepsToExecute.length
+      ? sortedSteps.findIndex((s) => s.id === stepsToExecute[0].id)
+      : -1;
+    const resumeDisplayIndex = resumeIndex >= 0 ? resumeIndex + 1 : 1;

-    console.log(
-      `[AutoMode] Resuming pipeline for feature ${featureId} from step ${startFromStepIndex + 1}/${sortedSteps.length}`
-    );
+    console.log(
+      `[AutoMode] Resuming pipeline for feature ${featureId} from step ${resumeDisplayIndex}/${sortedSteps.length}`
+    );

-      this.emitAutoModeEvent('auto_mode_progress', {
+      this.emitAutoModeEvent('auto_mode_progress', {
         featureId,
         projectPath,
         branchName: branchName ?? null,
-        content: `Resuming from pipeline step ${startFromStepIndex + 1}/${sortedSteps.length}`,
+        content: `Resuming from pipeline step ${resumeDisplayIndex}/${sortedSteps.length}`,
       });
🧹 Nitpick comments (1)
apps/ui/src/components/views/board-view/dialogs/mass-edit-dialog.tsx (1)

40-67: Normalize excluded step order before mixed-value comparison.

Current JSON string comparison is order-sensitive and can show “mixed” even when the same steps are excluded in different orders.

♻️ Proposed tweak
 function getMixedValues(features: Feature[]): Record<string, boolean> {
   if (features.length === 0) return {};
   const first = features[0];
-  const firstExcludedSteps = JSON.stringify(first.excludedPipelineSteps || []);
+  const normalizeSteps = (steps?: string[]) => [...(steps ?? [])].sort();
+  const firstExcludedSteps = JSON.stringify(normalizeSteps(first.excludedPipelineSteps));
   return {
     model: !features.every((f) => f.model === first.model),
     thinkingLevel: !features.every((f) => f.thinkingLevel === first.thinkingLevel),
     planningMode: !features.every((f) => f.planningMode === first.planningMode),
     requirePlanApproval: !features.every(
       (f) => f.requirePlanApproval === first.requirePlanApproval
     ),
     priority: !features.every((f) => f.priority === first.priority),
     skipTests: !features.every((f) => f.skipTests === first.skipTests),
     branchName: !features.every((f) => f.branchName === first.branchName),
-    excludedPipelineSteps: !features.every(
-      (f) => JSON.stringify(f.excludedPipelineSteps || []) === firstExcludedSteps
-    ),
+    excludedPipelineSteps: !features.every(
+      (f) => JSON.stringify(normalizeSteps(f.excludedPipelineSteps)) === firstExcludedSteps
+    ),
   };
 }

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
apps/server/src/services/auto-mode-service.ts (2)

1819-1823: Inconsistent index and count in log message.

startFromStepIndex is an index into allSortedSteps (the unfiltered list), but sortedSteps.length is the count of filtered (non-excluded) steps. This produces misleading log output.

For example, with 5 total steps where 2 are excluded:

  • allSortedSteps.length = 5
  • sortedSteps.length = 3
  • If resuming from index 4, log shows "step 5/3"
🔧 Suggested fix
     // Use the filtered steps for counting
     const sortedSteps = allSortedSteps.filter((step) => !excludedStepIds.has(step.id));
+    const stepIndexInFiltered = sortedSteps.findIndex((s) => s.id === allSortedSteps[startFromStepIndex].id);
 
     console.log(
-      `[AutoMode] Resuming pipeline for feature ${featureId} from step ${startFromStepIndex + 1}/${sortedSteps.length}`
+      `[AutoMode] Resuming pipeline for feature ${featureId} from step ${stepIndexInFiltered + 1}/${sortedSteps.length}`
     );

Alternatively, use consistent numbering from the unfiltered list: ${startFromStepIndex + 1}/${allSortedSteps.length} and note excluded steps separately.


1878-1883: Same inconsistency in progress event message.

This event uses the same mixed indices pattern as the console log above.

🔧 Suggested fix
       this.emitAutoModeEvent('auto_mode_progress', {
         featureId,
         projectPath,
         branchName: branchName ?? null,
-        content: `Resuming from pipeline step ${startFromStepIndex + 1}/${sortedSteps.length}`,
+        content: `Resuming from pipeline step ${stepIndexInFiltered + 1}/${sortedSteps.length}`,
       });

Use the same stepIndexInFiltered variable suggested in the previous comment.

apps/ui/src/components/views/board-view/dialogs/mass-edit-dialog.tsx (1)

54-68: Order-dependent array comparison may show false "mixed values" indicator.

JSON.stringify comparison is order-sensitive. If two features have the same excluded steps but in different order (e.g., ['step1', 'step2'] vs ['step2', 'step1']), they'll incorrectly display as "Mixed values".

Suggested fix using sorted comparison
 function getMixedValues(features: Feature[]): Record<string, boolean> {
   if (features.length === 0) return {};
   const first = features[0];
-  const firstExcludedSteps = JSON.stringify(first.excludedPipelineSteps || []);
+  const firstExcludedSteps = JSON.stringify([...(first.excludedPipelineSteps || [])].sort());
   return {
     model: !features.every((f) => f.model === first.model),
     thinkingLevel: !features.every((f) => f.thinkingLevel === first.thinkingLevel),
     planningMode: !features.every((f) => f.planningMode === first.planningMode),
     requirePlanApproval: !features.every(
       (f) => f.requirePlanApproval === first.requirePlanApproval
     ),
     priority: !features.every((f) => f.priority === first.priority),
     skipTests: !features.every((f) => f.skipTests === first.skipTests),
     branchName: !features.every((f) => f.branchName === first.branchName),
     excludedPipelineSteps: !features.every(
-      (f) => JSON.stringify(f.excludedPipelineSteps || []) === firstExcludedSteps
+      (f) => JSON.stringify([...(f.excludedPipelineSteps || [])].sort()) === firstExcludedSteps
     ),
   };
 }
🧹 Nitpick comments (1)
apps/ui/src/components/views/board-view/dialogs/mass-edit-dialog.tsx (1)

384-400: Consider conditionally rendering the Pipeline Steps section when project context is unavailable.

projectPath is optional and can be undefined when passed to MassEditDialog (as seen in board-view.tsx where it's set to currentProject?.path). When undefined, usePipelineConfig disables its query and PipelineExclusionControls returns null because no pipeline steps are available. However, the FieldWrapper still renders its container with the "Pipeline Steps" label and checkbox, creating an empty-looking field that may confuse users.

Suggested fix: wrap in conditional
           {/* Pipeline Exclusion */}
+          {projectPath && (
             <FieldWrapper
               label="Pipeline Steps"
               isMixed={mixedValues.excludedPipelineSteps}
               willApply={applyState.excludedPipelineSteps}
               onApplyChange={(apply) =>
                 setApplyState((prev) => ({ ...prev, excludedPipelineSteps: apply }))
               }
             >
               <PipelineExclusionControls
                 projectPath={projectPath}
                 excludedPipelineSteps={excludedPipelineSteps}
                 onExcludedStepsChange={setExcludedPipelineSteps}
                 testIdPrefix="mass-edit-pipeline"
               />
             </FieldWrapper>
+          )}

Alternatively, if the section should always be visible, consider adding a loading or empty state message inside the FieldWrapper.

@Shironex Shironex merged commit 7bee547 into v0.14.0rc Jan 21, 2026
8 checks passed
@Shironex Shironex deleted the feature/v0.13.0rc-1768936017583-e6ni branch January 21, 2026 11:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement Improvements to existing functionality or UI.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants