diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml
new file mode 100644
index 00000000..7dab6afe
--- /dev/null
+++ b/.github/workflows/pr-check.yml
@@ -0,0 +1,33 @@
+name: PR Build Check
+
+on:
+ pull_request:
+ branches:
+ - "*"
+ push:
+ branches:
+ - main
+ - master
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: "20"
+ cache: "npm"
+ cache-dependency-path: app/package-lock.json
+
+ - name: Install dependencies
+ working-directory: ./app
+ run: npm ci
+
+ - name: Run build:electron
+ working-directory: ./app
+ run: npm run build:electron
diff --git a/app/src/components/views/analysis-view.tsx b/app/src/components/views/analysis-view.tsx
index 4a6d7237..1fb2852d 100644
--- a/app/src/components/views/analysis-view.tsx
+++ b/app/src/components/views/analysis-view.tsx
@@ -1,7 +1,12 @@
"use client";
import { useCallback, useState } from "react";
-import { useAppStore, FileTreeNode, ProjectAnalysis } from "@/store/app-store";
+import {
+ useAppStore,
+ FileTreeNode,
+ ProjectAnalysis,
+ Feature,
+} from "@/store/app-store";
import { getElectronAPI } from "@/lib/electron";
import {
Card,
@@ -763,7 +768,17 @@ ${Object.entries(projectAnalysis.filesByExtension)
throw new Error("Features API not available");
}
- for (const feature of detectedFeatures) {
+ // Convert DetectedFeature to Feature by adding required id and status
+ for (const detectedFeature of detectedFeatures) {
+ const feature: Feature = {
+ id: `feature-${Date.now()}-${Math.random()
+ .toString(36)
+ .substr(2, 9)}`,
+ category: detectedFeature.category,
+ description: detectedFeature.description,
+ steps: detectedFeature.steps,
+ status: "backlog" as const,
+ };
await api.features.create(currentProject.path, feature);
}
diff --git a/app/src/components/views/interview-view.tsx b/app/src/components/views/interview-view.tsx
index 144be421..354858b8 100644
--- a/app/src/components/views/interview-view.tsx
+++ b/app/src/components/views/interview-view.tsx
@@ -1,7 +1,7 @@
"use client";
import { useState, useCallback, useRef, useEffect } from "react";
-import { useAppStore } from "@/store/app-store";
+import { useAppStore, Feature } from "@/store/app-store";
import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
@@ -313,11 +313,11 @@ export function InterviewView() {
);
// Create initial feature in the features folder
- const initialFeature = {
+ const initialFeature: Feature = {
id: `feature-${Date.now()}-0`,
category: "Core",
description: "Initial project setup",
- status: "backlog",
+ status: "backlog" as const,
steps: [
"Step 1: Review app_spec.txt",
"Step 2: Set up development environment",
@@ -325,6 +325,9 @@ export function InterviewView() {
],
skipTests: true,
};
+ if (!api.features) {
+ throw new Error("Features API not available");
+ }
await api.features.create(fullProjectPath, initialFeature);
const project = {
diff --git a/app/src/components/views/settings-view/components/delete-project-dialog.tsx b/app/src/components/views/settings-view/components/delete-project-dialog.tsx
index 0ac5870b..c60ce76f 100644
--- a/app/src/components/views/settings-view/components/delete-project-dialog.tsx
+++ b/app/src/components/views/settings-view/components/delete-project-dialog.tsx
@@ -8,7 +8,7 @@ import {
DialogTitle,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
-import type { Project } from "@/store/app-store";
+import type { Project } from "@/lib/electron";
interface DeleteProjectDialogProps {
open: boolean;
@@ -49,14 +49,19 @@ export function DeleteProjectDialog({
{project.name}
-{project.path}
++ {project.name} +
++ {project.path} +
- The folder will remain on disk until you permanently delete it from Trash. + The folder will remain on disk until you permanently delete it from + Trash.
- Let's set up your development environment. We'll check for required - CLI tools and help you configure them. + Let's set up your development environment. We'll check for + required CLI tools and help you configure them.
@@ -143,7 +148,8 @@ function WelcomeStep({ onNext }: { onNext: () => void }) {- Anthropic's powerful AI assistant for code generation and analysis + Anthropic's powerful AI assistant for code generation and + analysis
curl -fsSL https://claude.ai/install.sh | bash
-
irm https://claude.ai/install.ps1 | iex
- Subscription Token
-Use your Claude subscription (no API charges)
++ Subscription Token +
++ Use your Claude subscription (no API charges) +
{claudeCliStatus?.installed ? ( <>1. Run this command in your terminal:
++ 1. Run this command in your terminal: +
claude setup-token
-
API Key
-Pay-per-use with your Anthropic API key
++ Pay-per-use with your Anthropic API key +
Subscription
-Use your Claude subscription
-No API charges
++ Subscription +
++ Use your Claude subscription +
++ No API charges +
API Key
-Use Anthropic API key
++ Use Anthropic API key +
Pay-per-use
Claude is ready to use!
++ Claude is ready to use! +
- {getAuthMethodLabel() && `Using ${getAuthMethodLabel()}. `}You can proceed to the next step + {getAuthMethodLabel() && `Using ${getAuthMethodLabel()}. `}You + can proceed to the next step
- {getAuthMethodLabel() && `Authenticated via ${getAuthMethodLabel()}. `} + {getAuthMethodLabel() && + `Authenticated via ${getAuthMethodLabel()}. `} You can proceed to complete setup
@@ -1381,22 +1523,34 @@ function CompleteStep({ onFinish }: { onFinish: () => void }) { // Main Setup View export function SetupView() { - const { currentStep, setCurrentStep, completeSetup, setSkipClaudeSetup, setSkipCodexSetup } = - useSetupStore(); + const { + currentStep, + setCurrentStep, + completeSetup, + setSkipClaudeSetup, + setSkipCodexSetup, + } = useSetupStore(); const { setCurrentView } = useAppStore(); const steps = ["welcome", "claude", "codex", "complete"] as const; - type StepName = typeof steps[number]; + type StepName = (typeof steps)[number]; const getStepName = (): StepName => { - if (currentStep === "claude_detect" || currentStep === "claude_auth") return "claude"; - if (currentStep === "codex_detect" || currentStep === "codex_auth") return "codex"; + if (currentStep === "claude_detect" || currentStep === "claude_auth") + return "claude"; + if (currentStep === "codex_detect" || currentStep === "codex_auth") + return "codex"; if (currentStep === "welcome") return "welcome"; return "complete"; }; const currentIndex = steps.indexOf(getStepName()); const handleNext = (from: string) => { - console.log("[Setup Flow] handleNext called from:", from, "currentStep:", currentStep); + console.log( + "[Setup Flow] handleNext called from:", + from, + "currentStep:", + currentStep + ); switch (from) { case "welcome": console.log("[Setup Flow] Moving to claude_detect step"); @@ -1445,10 +1599,7 @@ export function SetupView() { }; return ( -