Skip to content

Conversation

@NomadicDaddy
Copy link

@NomadicDaddy NomadicDaddy commented Dec 27, 2025

This PR introduces a comprehensive feature validation system for the Kanban board that allows users to validate whether backlog features are already implemented in the codebase. The validation uses AI analysis to determine implementation status and automatically moves fully implemented features to the "Waiting Approval" lane.

Features Added

Individual Feature Validation

  • Validate checkbox on each backlog feature card
  • Shows spinning loader during validation
  • Displays detailed validation results (assessment, reasoning, evidence)
  • Automatically moves fully implemented features to "Waiting Approval"
  • Button is disabled during validation and when "Validate All" is running

Bulk Validation ("Validate All")

  • Lane-level "Validate All" button in the Backlog lane header
  • Validates all backlog features sequentially in board order (top to bottom)
  • Shows loading state with spinner and "Validating..." text
  • Button is disabled during validation to prevent conflicts
  • Includes 1-second delay between validations to avoid API overload

Validation Logic

  • Prompts the AI agent with: "Your task is to review this feature and the existing codebase and determine whether or not it has been fully/partially/not implemented"
  • Returns structured assessment: FULLY_IMPLEMENTED, PARTIALLY_IMPLEMENTED, or NOT_IMPLEMENTED
  • Provides detailed reasoning and evidence for the assessment
  • Features marked as FULLY_IMPLEMENTED are automatically moved to "Waiting Approval"

Summary by CodeRabbit

  • New Features
    • Added feature validation capability with individual "Validate" button on each feature card and "Validate all backlog" button for bulk validation.
    • Validation results display assessment status (fully/partially/not implemented), reasoning, and evidence.
    • Automatically moves fully validated features to approval state.
    • Real-time loading indicators show validation progress across cards.

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

@coderabbitai
Copy link

coderabbitai bot commented Dec 27, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

This pull request introduces a feature validation system that integrates an AgentService on the server with validation UI controls on the client. A new POST /validate-feature endpoint is added that uses an agent to assess feature implementation status. The UI surfaces validation actions at the board, card, and action levels with loading states and result handling.

Changes

Cohort / File(s) Summary
Server-side route integration
apps/server/src/index.ts
Updated feature routes initialization to pass AgentService dependency
Feature routes factory
apps/server/src/routes/features/index.ts
Extended createFeaturesRoutes signature to accept AgentService; registered new POST /validate-feature route using new handler
Feature validation handler
apps/server/src/routes/features/routes/validate-feature.ts
New route handler that creates agent sessions, builds validation prompts, parses agent responses to extract assessment/reasoning/evidence, and includes comprehensive error handling with session cleanup
UI board-view integration
apps/ui/src/components/views/board-view.tsx
Initialized column-features hook early; added validation handlers to useBoardActions; propagated validation callbacks and column-features getter to child components
Board actions hook
apps/ui/src/components/views/board-view/hooks/use-board-actions.ts
Extended hook to accept getColumnFeatures parameter; added handleValidateFeature and handleValidateAllBacklog handlers that call validation API and manage feature transitions
Kanban board component
apps/ui/src/components/views/board-view/kanban-board.tsx
Added backlog validation flow with isValidatingAll state; new "Validate all backlog" button with loading indicator; propagated validation props to KanbanCard instances
Kanban card and actions
apps/ui/src/components/views/board-view/components/kanban-card/kanban-card.tsx, apps/ui/src/components/views/board-view/components/kanban-card/card-actions.tsx
Extended props to accept onValidate callback and isValidatingAll state; added Validate button with loading spinner and Check icon in CardActions
HTTP API client
apps/ui/src/lib/http-api-client.ts
Added HTTP error handling for POST/GET/PUT/DELETE methods; introduced validateFeature method to post validation requests
Electron API interface
apps/ui/src/lib/electron.ts
Extended FeaturesAPI with new validateFeature method signature

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant UI as UI Component
    participant Hook as Board Actions Hook
    participant Client as HTTP Client
    participant Server as Features Route
    participant Agent as AgentService
    
    User->>UI: Click Validate Feature Button
    UI->>Hook: handleValidateFeature(feature)
    Hook->>Hook: Mark feature as validating
    Hook->>Client: validateFeature(projectPath, featureId)
    
    Client->>Server: POST /api/features/validate-feature
    
    Server->>Server: Load feature from featureLoader
    alt Feature Not Found
        Server-->>Client: 404 Error
    else Feature Found
        Server->>Agent: Create session with feature metadata
        Server->>Agent: Initialize conversation
        Server->>Agent: Send validation prompt
        
        alt Agent Fails
            Agent-->>Server: Error response
            Server->>Agent: Cleanup session
            Server-->>Client: 500 Error
        else Agent Succeeds
            Agent-->>Server: Text response
            Server->>Server: Parse assessment/reasoning/evidence
            Server->>Agent: Cleanup session
            Server-->>Client: 200 OK with validation result
        end
    end
    
    Client-->>Hook: Validation result
    Hook->>Hook: Update feature metadata
    alt Assessment = FULLY_IMPLEMENTED
        Hook->>Hook: Move to waiting_approval
    end
    Hook->>Hook: Clear validating state
    Hook-->>UI: Update UI
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

Enhancement

Poem

🐰 A validation hop through agents so wise,
Feature checks bloom before our eyes,
From backlog cards to waiting skies,
The rabbit validates with flair,
Buttons glow, spinners spin with care!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'feature/validate-features' is vague and uses a branch naming convention rather than describing the actual change to reviewers. Use a descriptive title that summarizes the main change (e.g., 'Add feature validation system with AI-powered implementation assessment').
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @NomadicDaddy, 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 implements a new AI-driven feature validation system for the Kanban board. It enables users to verify the implementation status of backlog features, either individually or in a batch, and automatically transitions fully implemented items to a 'Waiting Approval' state. This enhancement aims to improve workflow efficiency by leveraging AI to assess code against feature descriptions.

Highlights

  • AI-Powered Feature Validation: Introduces a system to validate if backlog features are implemented using AI analysis.
  • Individual Feature Validation: Adds a 'Validate' checkbox to each feature card, showing a loader during validation and detailed results (assessment, reasoning, evidence). Fully implemented features are automatically moved to 'Waiting Approval'.
  • Bulk Validation: A 'Validate All' button in the Backlog lane header allows sequential validation of all backlog features, with a loading state and a 1-second delay between validations to prevent API overload.
  • Structured AI Assessment: The AI agent is prompted to determine if a feature is 'FULLY_IMPLEMENTED', 'PARTIALLY_IMPLEMENTED', or 'NOT_IMPLEMENTED', providing reasoning and evidence.

🧠 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.

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 a valuable feature for validating backlog items against the existing codebase using an AI agent. The implementation is well-structured, with clear separation of concerns between the backend route, UI hooks, and components. The logic for handling both individual and bulk validation is robust, including good UI feedback with loading states and error handling. My review focuses on improving the backend handler's type safety, parsing logic, and error handling to make it even more resilient.

) {
return async (req: any, res: any) => {
try {
const { projectPath, featureId }: ValidateFeatureRequest = req.body;
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The type ValidateFeatureRequest is used here but is not defined or imported. This will cause a TypeScript error. You should define it within this file or in a shared types file. For example:

interface ValidateFeatureRequest {
  projectPath: string;
  featureId: string;
}

Comment on lines 88 to 92
try {
await agentService.deleteSession(session.id);
} catch (cleanupError) {
console.error('[ValidateFeature] Failed to cleanup session:', cleanupError);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

In this catch block, you attempt to clean up the agent session. However, if the initial session creation at lines 56-61 failed in a way that session is undefined but no error was thrown, accessing session.id here would cause a TypeError. This would prevent the proper error response from being sent to the client. The same issue exists in the cleanup block on lines 102-106.

You should add a check to ensure session is defined before trying to access its properties, for example by wrapping this try-catch block in an if (session) { ... }.

const assessmentMatch = response.match(
/ASSESSMENT:\s*\*{0,2}(FULLY_IMPLEMENTED|PARTIALLY_IMPLEMENTED|NOT_IMPLEMENTED)\*{0,2}/
);
const reasoningMatch = response.match(/REASONING:\s*\*{0,2}([^\n*]+)\*{0,2}/);
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The regex for parsing REASONING is a bit brittle. The character class [^\n*]+ will stop matching at the first newline OR the first asterisk. This means if the reasoning text contains an asterisk (e.g., for emphasis or in a code snippet like *.log), the reasoning will be truncated. It also prevents multi-line reasoning.

A more robust approach would be to match non-greedily until the next section (EVIDENCE:) or a double newline. This would better handle variations in the AI's output. I'd also recommend trimming the result on line 130 (e.g., reasoningMatch?.[1]?.trim()).

Suggested change
const reasoningMatch = response.match(/REASONING:\s*\*{0,2}([^\n*]+)\*{0,2}/);
const reasoningMatch = response.match(/REASONING:\s*\*{0,2}([\s\S]+?)(?=\n\s*\*{0,2}EVIDENCE:|\n\n|$)/);

Comment on lines +172 to +179
if (!response.ok) {
const errorText = await response.text();
console.error(
`[HttpApiClient] POST ${endpoint} failed: ${response.status} ${response.statusText}`,
errorText
);
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

It's great that you've added error handling for non-2xx responses in the post method. This significantly improves the robustness of the API client. This same pattern of checking response.ok and throwing an error should be applied to the get, put, and delete methods as well to ensure consistent error handling across all HTTP requests.

featureLoader: FeatureLoader,
agentService: AgentService
) {
return async (req: any, res: any) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The request and response objects are typed as any. For better type safety and autocompletion, it's recommended to use the specific types from Express, Request and Response.

Suggested change
return async (req: any, res: any) => {
return async (req: Request, res: Response) => {

/ASSESSMENT:\s*\*{0,2}(FULLY_IMPLEMENTED|PARTIALLY_IMPLEMENTED|NOT_IMPLEMENTED)\*{0,2}/
);
const reasoningMatch = response.match(/REASONING:\s*\*{0,2}([^\n*]+)\*{0,2}/);
const evidenceMatch = response.match(/EVIDENCE:\s*\*{0,2}([\s\S]*?)\*{0,2}(?=\n\n|$)/);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Similar to the reasoningMatch regex, this one can be improved. The trailing \*{0,2} could mistakenly consume asterisks that are part of the evidence text. It's safer to remove it from the main pattern and rely on the lookahead and trim() to clean up the result. I'd also recommend trimming the result on line 131 (e.g., evidenceMatch?.[1]?.trim()).

Suggested change
const evidenceMatch = response.match(/EVIDENCE:\s*\*{0,2}([\s\S]*?)\*{0,2}(?=\n\n|$)/);
const evidenceMatch = response.match(/EVIDENCE:\s*\*{0,2}([\s\S]+?)(?=\n\n|$)/);

@NomadicDaddy NomadicDaddy marked this pull request as draft December 27, 2025 18:36
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: 3

🧹 Nitpick comments (4)
apps/ui/src/lib/http-api-client.ts (2)

165-235: Non‑2xx HTTP responses now throw – verify callers handle this new behavior

post, get, put, and httpDelete now:

  • Log body text for non‑ok responses.
  • Throw Error("HTTP <status>: <statusText>") instead of returning the parsed JSON body.

This is a behavior change from the previous implementation that would return whatever JSON the server sent (often { success: false, error: ... }). Any call sites that rely on result.success/result.error for 4xx/5xx responses but do not wrap the call in try/catch will now see rejected promises instead.

Consider:

  • Auditing high-traffic and UX-critical callers to ensure they try/catch these methods.
  • Optionally, standardizing on a response envelope (e.g., always returning { success, error? }) even for non‑2xx by not throwing, and letting higher layers decide, if that better matches existing patterns.

575-576: features.validateFeature wiring matches server contract

The new features.validateFeature call correctly posts { projectPath, featureId } to /api/features/validate-feature and will be typed by FeaturesAPI.validateFeature. For extra clarity and IDE help, you could make the response type explicit:

validateFeature: (projectPath: string, featureId: string) =>
  this.post<ReturnType<ElectronAPI['features']>['validateFeature'] extends (...args: any) => Promise<infer R> ? R : unknown>(
    '/api/features/validate-feature',
    { projectPath, featureId },
  )

Optional, current implementation is acceptable.

apps/ui/src/components/views/board-view.tsx (1)

372-381: Column‑aware validation wiring is solid; double‑check interaction with filtering for completed/verified counts

Using useBoardColumnFeatures before useBoardActions and passing getColumnFeatures into both the actions hook and KanbanBoard cleanly ties validation to the visible column ordering. The new onValidate / onValidateAllBacklog props are also wired correctly into the board.

One behavioral detail to verify: completedFeatures and getColumnFeatures('verified') likely respect searchQuery and worktree filters. That means:

  • Completed features modal and
  • The “Archive All Verified” dialog count

may now reflect only the filtered subset rather than all project-wide completed/verified features. If previous UX expected global counts, you may want to source those from the raw feature list instead of the column-filtered view.

Also applies to: 383-405, 1074-1076

apps/ui/src/components/views/board-view/hooks/use-board-actions.ts (1)

43-45: Validation handlers are well‑structured; consider a couple of small hardenings

The new validation flow in this hook is generally solid:

  • getColumnFeatures plumbs column ordering into handleValidateAllBacklog so bulk validation follows visible board order.
  • handleValidateFeature:
    • Marks a per‑feature metadata["validating-<id>"] flag before calling the API.
    • Interprets the validation result and, on FULLY_IMPLEMENTED, moves the feature to waiting_approval and persists it.
    • Uses try/catch/finally to clear the validating flag even on failures (unless the feature was moved).
  • Both single and bulk validation are wrapped in try/catch, so they cooperate correctly with the new throwing HTTP helpers.

A few small improvements to consider:

  1. Defensive handling if validation is unexpectedly missing
    Types declare validation?, but the code assumes it exists whenever response.success is true:

    const { validation } = response;
    // ...
    validation.assessment

    To avoid a hard runtime failure if the server ever responds with { success: true } but no validation (e.g., a bug or version skew), you could guard:

    if (!response.validation) {
      toast.error('Validation failed', { description: 'No validation payload returned.' });
      return;
    }
    const { validation } = response;
  2. Metadata field is purely UI‑local
    Using feature.metadata to track the validating-<id> flag is fine, but it depends on the underlying Feature shape tolerating arbitrary metadata. If you later introduce a strongly typed metadata property on Feature, this pattern may need revisiting. For now, it’s acceptable but worth a brief comment near the first metadata usage to document that it’s UI-only state.

  3. Bulk validation UX
    handleValidateAllBacklog already adds a 1s delay between validations, which is good for rate limiting. If you haven’t already, you may also want to surface an “is validating all” boolean in state (passed as isValidatingAll) to:

    • Disable per-card validate buttons during bulk runs.
    • Disable the “Validate All” trigger while it’s already running.

    From the props on KanbanCard/CardActions, it looks like you’re partially set up for this; just ensure the state toggling is wired where this handler is invoked.

Overall, the structure is good; these are just guardrails to make failure modes clearer and future type evolution smoother.

Also applies to: 74-75, 868-1006, 1028-1029

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b60e8f0 and 58f4800.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • apps/server/src/index.ts
  • apps/server/src/routes/features/index.ts
  • apps/server/src/routes/features/routes/validate-feature.ts
  • apps/ui/src/components/views/board-view.tsx
  • apps/ui/src/components/views/board-view/components/kanban-card/card-actions.tsx
  • apps/ui/src/components/views/board-view/components/kanban-card/kanban-card.tsx
  • apps/ui/src/components/views/board-view/hooks/use-board-actions.ts
  • apps/ui/src/components/views/board-view/kanban-board.tsx
  • apps/ui/src/lib/electron.ts
  • apps/ui/src/lib/http-api-client.ts
🧰 Additional context used
🧬 Code graph analysis (5)
apps/server/src/routes/features/routes/validate-feature.ts (1)
apps/server/src/services/feature-loader.ts (1)
  • FeatureLoader (22-384)
apps/ui/src/components/views/board-view/hooks/use-board-actions.ts (3)
apps/ui/src/store/app-store.ts (1)
  • Feature (256-272)
libs/types/src/feature.ts (1)
  • Feature (24-58)
apps/ui/src/lib/electron.ts (1)
  • getElectronAPI (720-729)
apps/server/src/index.ts (1)
apps/server/src/routes/features/index.ts (1)
  • createFeaturesRoutes (18-38)
apps/ui/src/components/views/board-view/kanban-board.tsx (2)
apps/ui/src/lib/utils.ts (1)
  • cn (5-7)
apps/ui/src/components/ui/hotkey-button.tsx (1)
  • HotkeyButton (169-288)
apps/ui/src/components/views/board-view/components/kanban-card/card-actions.tsx (1)
apps/ui/src/components/ui/button.tsx (1)
  • Button (108-108)
🔇 Additional comments (9)
apps/server/src/index.ts (1)

147-147: Features routes correctly wired with AgentService

Passing agentService into createFeaturesRoutes aligns with the updated route factory and keeps feature validation using the shared AgentService instance. No issues here.

apps/server/src/routes/features/index.ts (1)

15-21: Feature validation route is cleanly integrated into the features router

The route factory’s new agentService dependency and the /validate-feature POST registration (with validatePathParams('projectPath')) look consistent with the rest of the features API and server wiring. No issues spotted.

Also applies to: 31-35

apps/ui/src/components/views/board-view/components/kanban-card/kanban-card.tsx (1)

29-33: Validation props are cleanly threaded through KanbanCard

Adding onValidate and isValidatingAll to KanbanCardProps and forwarding them to CardActions is done cleanly and doesn’t affect existing behavior. This keeps the card component thin and lets CardActions own the validation UI logic. No issues here.

Also applies to: 58-62, 171-189

apps/ui/src/components/views/board-view/components/kanban-card/card-actions.tsx (2)

13-14: LGTM! Props and imports are correctly added.

The new isValidatingAll and onValidate props are properly typed and integrated into the component signature. The icon imports support the validation UI.

Also applies to: 21-21, 34-34, 41-41, 54-54


307-329: LGTM! Validate button implementation is solid.

The button correctly:

  • Guards against concurrent validation (per-feature and global states)
  • Shows appropriate loading indicators
  • Prevents event propagation to avoid card selection
  • Includes accessibility attributes
apps/ui/src/components/views/board-view/kanban-board.tsx (4)

96-109: LGTM! Loading state management is well-structured.

The wrapper correctly:

  • Prevents concurrent executions with a guard
  • Uses try/finally to ensure state cleanup
  • Leverages useCallback for performance

167-196: LGTM! Validate All button has appropriate loading states.

The button correctly:

  • Shows loading spinner and disabled state during validation
  • Updates styling and title text based on state
  • Uses semantic icons (CheckCircle/Loader2)

197-208: Verify whether the hotkey should be disabled.

The hotkeyActive={false} prop disables the keyboard shortcut for starting next features, meaning users can only click the button. Was this intentional, or should the hotkey remain active?

If the hotkey should be active, apply this change:

🔎 Enable the keyboard shortcut
                           <HotkeyButton
                             variant="ghost"
                             size="sm"
                             className="h-6 px-2 text-xs text-primary hover:text-primary hover:bg-primary/10"
                             onClick={onStartNextFeatures}
                             hotkey={shortcuts.startNext}
-                            hotkeyActive={false}
+                            hotkeyActive={true}
                             data-testid="start-next-button"
                           >

243-243: LGTM! Props are correctly passed to KanbanCard.

The validation callback and loading state are properly propagated to individual cards.

Also applies to: 246-246

Comment on lines 1 to 158
/**
* Validate feature route - Uses AI agent to check if a feature is already implemented
*/

import type { Request, Response } from 'express';
import { FeatureLoader } from '../../../services/feature-loader.js';
import { AgentService } from '../../../services/agent-service.js';
import { getErrorMessage, logError } from '../common.js';
import type { Feature } from '@automaker/types';

export function createValidateFeatureHandler(
featureLoader: FeatureLoader,
agentService: AgentService
) {
return async (req: any, res: any) => {
try {
const { projectPath, featureId }: ValidateFeatureRequest = req.body;

// Load the feature
const feature = await featureLoader.get(projectPath, featureId);
if (!feature) {
return res.status(404).json({
success: false,
error: 'Feature not found',
});
}

// Create a validation prompt
const validationPrompt = `Your task is to review this feature and the existing codebase and determine whether or not it has been fully/partially/not implemented.
Feature Details:
- Title: ${feature.title}
- Category: ${feature.category}
- Description: ${feature.description}
Please analyze the codebase and provide your assessment in the following format (plain text, no markdown):
ASSESSMENT: [FULLY_IMPLEMENTED|PARTIALLY_IMPLEMENTED|NOT_IMPLEMENTED]
REASONING: [Brief explanation of your decision]
EVIDENCE: [Specific code/files that support your assessment]
Be thorough in your analysis. Check for:
- Related components, functions, or classes
- Test files
- Configuration changes
- Documentation updates
- Any other relevant implementation details
If the feature is FULLY_IMPLEMENTED, it should be complete and ready for approval.
If PARTIALLY_IMPLEMENTED, explain what's missing.
If NOT_IMPLEMENTED, explain why you believe this feature hasn't been addressed.`;

// Create a temporary session for validation
let session;
try {
// First create the session metadata
session = await agentService.createSession(
`Feature Validation: ${feature.title}`,
projectPath,
projectPath
);

// Then initialize the conversation session in memory
await agentService.startConversation({
sessionId: session.id,
workingDirectory: projectPath,
});
} catch (sessionError) {
console.error('[ValidateFeature] Failed to create session:', sessionError);
return res.status(500).json({
success: false,
error: 'Failed to create agent session',
});
}

// Send the validation prompt to the agent
let result;
try {
result = await agentService.sendMessage({
sessionId: session.id,
message: validationPrompt,
workingDirectory: projectPath,
});
} catch (messageError) {
console.error('[ValidateFeature] Failed to send message:', messageError);

// Clean up the session if it exists
try {
await agentService.deleteSession(session.id);
} catch (cleanupError) {
console.error('[ValidateFeature] Failed to cleanup session:', cleanupError);
}

return res.status(500).json({
success: false,
error: 'Failed to send message to agent',
});
}

if (!result.success) {
// Clean up the session
try {
await agentService.deleteSession(session.id);
} catch (cleanupError) {
console.error('[ValidateFeature] Failed to cleanup session:', cleanupError);
}

return res.status(500).json({
success: false,
error: 'Failed to validate feature',
});
}

// Parse the agent response
const response = result.message?.content || '';
console.log('[ValidateFeature] Raw AI Response:', response);

const assessmentMatch = response.match(
/ASSESSMENT:\s*\*{0,2}(FULLY_IMPLEMENTED|PARTIALLY_IMPLEMENTED|NOT_IMPLEMENTED)\*{0,2}/
);
const reasoningMatch = response.match(/REASONING:\s*\*{0,2}([^\n*]+)\*{0,2}/);
const evidenceMatch = response.match(/EVIDENCE:\s*\*{0,2}([\s\S]*?)\*{0,2}(?=\n\n|$)/);

console.log('[ValidateFeature] Regex matches:');
console.log(' - Assessment match:', assessmentMatch);
console.log(' - Reasoning match:', reasoningMatch);
console.log(' - Evidence match:', evidenceMatch);

const assessment = assessmentMatch?.[1] || 'NOT_IMPLEMENTED';
const reasoning = reasoningMatch?.[1] || 'Unable to determine reasoning';
const evidence = evidenceMatch?.[1] || 'No specific evidence provided';

console.log('[ValidateFeature] Extracted values:');
console.log(' - Assessment:', assessment);
console.log(' - Reasoning:', reasoning);
console.log(' - Evidence:', evidence?.substring(0, 200) + '...');

// Clean up the session
await agentService.deleteSession(session.id);

return res.json({
success: true,
validation: {
assessment,
reasoning,
evidence,
fullResponse: response,
},
});
} catch (error) {
console.error('[ValidateFeature] Error:', error);
return res.status(500).json({
success: false,
error: (error as Error).message,
});
}
};
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Define ValidateFeatureRequest and tighten error/session handling

The overall validation flow (load feature → create agent session → send structured prompt → parse ASSESSMENT/REASONING/EVIDENCE → clean up session) looks good, but there are a few concrete issues and improvement opportunities:

  1. Missing ValidateFeatureRequest definition/import (likely compile error)
    You destructure with a typed annotation:

    const { projectPath, featureId }: ValidateFeatureRequest = req.body;

    but no ValidateFeatureRequest type is defined or imported in this file. Unless it’s a global ambient type, this will fail type-checking. A simple local definition is probably enough here:

    interface ValidateFeatureRequest {
      projectPath: string;
      featureId: string;
    }

    Place it above createValidateFeatureHandler.

  2. Inconsistent use of shared error utilities
    You import getErrorMessage and logError from ../common.js but never use them, and instead call console.error directly. For consistency with other routes and better logging, consider:

    } catch (error) {
      logError('[ValidateFeature] Error validating feature', error);
      return res.status(500).json({
        success: false,
        error: getErrorMessage(error),
      });
    }
  3. Session cleanup in unexpected error paths
    You correctly clean up the session in most early‑return error branches and on the happy path:

    • After failed sendMessage
    • When result.success is false
    • After successful parsing

    However, if an exception is thrown after sendMessage succeeds but before deleteSession(session.id) (e.g., due to an unexpected response shape or a regex edge case), the outer catch currently does not attempt to delete the session, which could leave orphaned session metadata. Consider tracking sessionId separately and cleaning it up in the outer catch when available.

  4. Regex robustness / logging volume (optional)

    • The regexes are reasonably defensive, but any deviation from the expected format falls back to NOT_IMPLEMENTED. If the model ever returns slightly different formatting, that may pessimistically classify real implementations as not implemented. You might want to log a warning in that case or relax the patterns slightly.
    • Logging the full raw AI response plus all regex matches on every validation could be quite noisy in production logs. It may be worth guarding these logs behind a debug flag or log level.

Addressing (1) is essential for compilation; (2) and (3) improve reliability and consistency; (4) is a nice-to-have.

🤖 Prompt for AI Agents
apps/server/src/routes/features/routes/validate-feature.ts lines 1-158: add a
local ValidateFeatureRequest interface above createValidateFeatureHandler to
define { projectPath: string; featureId: string } so the destructuring is
properly typed; replace console.error usages in the outer catch and
session-related error handlers with the imported logError and return errors
using getErrorMessage(error) for consistent logging/response; and ensure session
cleanup on any thrown exception by tracking sessionId (e.g., capture session?.id
into a local variable after creation) and attempting
agentService.deleteSession(sessionId) in the outer catch before returning.

Comment on lines 47 to 48
onValidate?: (feature: Feature) => void;
onValidateAllBacklog?: () => void;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Type signature should reflect async usage.

onValidateAllBacklog is awaited on Line 105, but its type signature declares it as returning void rather than Promise<void>.

🔎 Proposed type fix
   onValidate?: (feature: Feature) => void;
-  onValidateAllBacklog?: () => void;
+  onValidateAllBacklog?: () => Promise<void>;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onValidate?: (feature: Feature) => void;
onValidateAllBacklog?: () => void;
onValidate?: (feature: Feature) => void;
onValidateAllBacklog?: () => Promise<void>;
🤖 Prompt for AI Agents
In apps/ui/src/components/views/board-view/kanban-board.tsx around lines 47-48,
the prop onValidateAllBacklog is declared as returning void but is awaited at
line 105; change its type from () => void to () => Promise<void> so it reflects
async usage, and update any call-sites/implementations to return a Promise (or
be async functions) to satisfy the new signature.

Comment on lines +343 to +355
validateFeature: (
projectPath: string,
featureId: string
) => Promise<{
success: boolean;
validation?: {
assessment: 'FULLY_IMPLEMENTED' | 'PARTIALLY_IMPLEMENTED' | 'NOT_IMPLEMENTED';
reasoning: string;
evidence: string;
fullResponse: string;
};
error?: string;
}>;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add validateFeature to the mock Features API to avoid runtime/type breakage

The new FeaturesAPI.validateFeature signature looks good and matches the server route shape. However, createMockFeaturesAPI() (later in this file) still returns an object without validateFeature, even though its return type is FeaturesAPI. This can cause:

  • TypeScript errors (object missing required property).
  • Runtime failures in web/mock mode when api.features.validateFeature is invoked.

Consider adding a no-op/mock implementation, e.g.:

Proposed mock implementation
 function createMockFeaturesAPI(): FeaturesAPI {
   // Store features in mock file system using features/{id}/feature.json pattern
   return {
@@
     generateTitle: async (description: string) => {
       console.log('[Mock] Generating title for:', description.substring(0, 50));
       // Mock title generation - just take first few words
       const words = description.split(/\s+/).slice(0, 6).join(' ');
       const title = words.length > 40 ? words.substring(0, 40) + '...' : words;
       return { success: true, title: `Add ${title}` };
     },
+    validateFeature: async (projectPath: string, featureId: string) => {
+      console.log('[Mock] Validating feature (mock):', { projectPath, featureId });
+      return {
+        success: true,
+        validation: {
+          assessment: 'PARTIALLY_IMPLEMENTED',
+          reasoning: 'Mock validation – backend validation is not available in web preview.',
+          evidence: 'No real code analysis performed in mock mode.',
+          fullResponse: 'Mock validation response.',
+        },
+      };
+    },
   };
 }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In apps/ui/src/lib/electron.ts around lines 343-355, the mock Features API
returned by createMockFeaturesAPI is missing the new validateFeature method
which causes TypeScript and runtime breakage; add a validateFeature
implementation that matches the declared signature (projectPath: string,
featureId: string) => Promise<{ success: boolean; validation?: { assessment:
'FULLY_IMPLEMENTED' | 'PARTIALLY_IMPLEMENTED' | 'NOT_IMPLEMENTED'; reasoning:
string; evidence: string; fullResponse: string; }; error?: string }> and return
a safe no-op/mock response (e.g., resolve success: true with a default
validation object or resolve success: false with an error) so callers can invoke
api.features.validateFeature without crashes and types remain satisfied.

@webdevcody
Copy link
Collaborator

closing, too many conflicts

@webdevcody webdevcody closed this Jan 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants