Skip to content

feat: implement new layout components and enhance UI with glassmorphism#252

Closed
SuperComboGamer wants to merge 1 commit intomainfrom
new-ui-base
Closed

feat: implement new layout components and enhance UI with glassmorphism#252
SuperComboGamer wants to merge 1 commit intomainfrom
new-ui-base

Conversation

@SuperComboGamer
Copy link
Collaborator

@SuperComboGamer SuperComboGamer commented Dec 23, 2025

This commit introduces a new app layout structure with an AppLayout component, a TopHeader for improved navigation, and a Sidebar for project management. Additionally, it adds GlassPanel and GlassCard components to enhance the UI with a glassmorphism effect. The Kanban board and agent views have been updated to utilize these new components, improving the overall user experience and visual consistency across the application.

Summary by CodeRabbit

  • New Features

    • Redesigned UI with a modern glassmorphic aesthetic across all views
    • Enhanced layout structure featuring an updated sidebar and header
    • Improved kanban board with color-coded column accents for visual organization
    • Updated terminal view with transparency support
  • Style

    • Modernized color theme with new brand color tokens and visual effects
    • Refined visual styling for agent tools, board, and running agents views

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

This commit introduces a new app layout structure with an AppLayout component, a TopHeader for improved navigation, and a Sidebar for project management. Additionally, it adds GlassPanel and GlassCard components to enhance the UI with a glassmorphism effect. The Kanban board and agent views have been updated to utilize these new components, improving the overall user experience and visual consistency across the application.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 23, 2025

📝 Walkthrough

Walkthrough

This PR introduces a comprehensive redesign of the UI layer, adding new layout primitives (AppLayout, TopHeader, GlassCard, GlassPanel), restructuring multiple views to use these components, simplifying the Sidebar, completely rewriting the global stylesheet with a token-based theme system, and extending the app store with planning and Claude-related fields.

Changes

Cohort / File(s) Summary
Layout Primitives
apps/ui/src/components/layout/app-layout.tsx, apps/ui/src/components/layout/top-header.tsx
New AppLayout wrapper component with decorative ambient elements and Sidebar integration. New TopHeader component with title, subtitle, user toggle group, Auto Mode button, and Add Feature button.
UI Component Library
apps/ui/src/components/ui/glass-card.tsx, apps/ui/src/components/ui/glass-panel.tsx
New GlassCard and GlassPanel components with forwardRef support. GlassCard supports 'default' and 'active-blue' variants. GlassPanel supports color accents (cyan, blue, orange, green, none).
Layout Refactoring
apps/ui/src/components/layout/sidebar.tsx
Sidebar rewritten as largely static UI with simplified header, project selector, static navigation items using internal NavItem component, and footer links. Removed extensive store hooks, dialogs, and feature flags.
View Component Updates
apps/ui/src/components/views/agent-view.tsx, apps/ui/src/components/views/agent-tools-view.tsx, apps/ui/src/components/views/running-agents-view.tsx, apps/ui/src/components/views/terminal-view.tsx
Restructured major views to use TopHeader and GlassPanel/GlassCard composition instead of old Card-based layouts. Updated styling, container structure, and visual hierarchy while maintaining core logic.
Board/Kanban System
apps/ui/src/components/views/board-view.tsx, apps/ui/src/components/views/board-view/components/kanban-column.tsx, apps/ui/src/components/views/board-view/components/kanban-card/kanban-card.tsx, apps/ui/src/components/views/board-view/components/kanban-card/card-header.tsx, apps/ui/src/components/views/board-view/kanban-board.tsx, apps/ui/src/components/views/board-view/constants.ts, apps/ui/src/components/views/board-view/hooks/use-board-column-features.ts
KanbanColumn wrapped with GlassPanel and accent-based color system replacing colorClass. KanbanCard refactored to use GlassCard, removed opacity/glassmorphism/border props, redesigned hover-based actions and layout flow. Added accent property to COLUMNS constant. Type casts added for dependency resolution. BoardView replaced BoardHeader with TopHeader.
Terminal View
apps/ui/src/components/views/terminal-view/terminal-panel.tsx, apps/ui/src/config/terminal-themes.ts
Added allowTransparency option to xterm Terminal initialization. Dark theme background changed from solid '#0a0a0a' to 'transparent' for glassmorphism effect.
Styling System
apps/ui/src/styles/global.css
Complete rewrite of theme system: replaced legacy variant-heavy theming with new @theme block using token-based architecture. Introduced brand color tokens (cyan, blue, orange, green, red, purple), dark theme tokens, semantic color mappings, glass utilities (glass-sidebar, glass-panel, glass-card), and modular UI utilities. Removed extensive per-theme overrides and complex cascading rules.
Store Extensions
apps/ui/src/store/app-store.ts
Added optional planning-related fields to Feature (planSpec, planningMode, priority, branchName, model, thinkingLevel, skipTests, requirePlanApproval, summary, dependencies, startedAt). Made Feature.steps optional. Added Claude telemetry fields (claudeRefreshInterval, claudeUsage, claudeUsageLastUpdated). Extended type re-exports.
Root Layout
apps/ui/src/routes/__root.tsx
Replaced Sidebar with AppLayout wrapper. Changed inner container to full-height layout. Added z-50 to streamer panel.
Minor Updates
apps/ui/src/components/views/board-view/components/kanban-card/card-header.tsx, apps/ui/src/components/views/board-view/worktree-panel/components/worktree-tab.tsx, apps/ui/src/components/views/settings-view.tsx, index (28).html
Added hideActions prop to CardHeaderProps. Widened prBadge type to React.ReactNode. Added explicit type cast for theme handler. Created static HTML demo page showcasing the new glassy Kanban board design.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Implement planning/speckits rebase #160 — Both PRs add planning-related types (PlanSpec, planningMode, requirePlanApproval) and fields to the Feature interface and app store, extending planning capabilities.
  • terminals-mpve #172 — Both PRs significantly refactor the Sidebar component, modifying navigation structure and internal composition patterns.
  • feat: task dependency graph view #222 — Both PRs restructure the board view UI, replacing BoardHeader and updating the visual hierarchy and layout composition.

Suggested labels

refactor

Poem

🐰 A glass palace rises, where sidebars shimmer,
TopHeaders crown each view with elegant glimmer,
GlassCards and GlassPanels dance in cyan light,
Planning takes shape as tokens align just right,
The UI springs forth—frosted, bold, and bright!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
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.
✅ 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 accurately summarizes the main changes: introduction of new layout components (AppLayout, TopHeader, Sidebar) and glassmorphism-enhanced UI elements (GlassPanel, GlassCard) applied across multiple views.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch new-ui-base

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

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @SuperComboGamer, 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 delivers a comprehensive UI/UX refresh, establishing a new, consistent application layout and a modern glassmorphism aesthetic. It introduces foundational layout components and reusable glass-effect UI elements, which are then integrated across key application views like the Kanban board and agent interfaces. The changes aim to provide a more cohesive and visually appealing user experience, supported by a revamped global styling approach.

Highlights

  • New Layout Components: Introduced AppLayout as the main application wrapper and a new TopHeader component for view-specific navigation, replacing the previous BoardHeader.
  • Glassmorphism UI Elements: Added new reusable GlassPanel and GlassCard components to implement a modern glassmorphism design language across the application.
  • Sidebar Redesign: The Sidebar component has been significantly refactored and simplified, adopting the new glassmorphism styling and focusing on a streamlined navigation structure.
  • UI Integration: Existing views such as AgentToolsView, AgentView, and BoardView have been updated to utilize the new AppLayout, TopHeader, GlassPanel, and GlassCard components, enhancing visual consistency and user experience.
  • Global Styling Overhaul: The global.css file has been refactored to remove old theme-related custom variants and variables, introducing new Tailwind CSS @theme and @utility directives to support the glassmorphism design system, brand colors, and custom scrollbars.
  • Kanban Board Enhancements: Kanban cards (KanbanCard) now use GlassCard and columns (KanbanColumn) use GlassPanel with accent colors, and the Feature interface in the store has been extended with new properties for more detailed feature management.

🧠 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 significant and impressive UI overhaul, implementing a new layout system and a consistent glassmorphism design across the application. The new components like AppLayout, TopHeader, GlassPanel, and GlassCard are well-structured and greatly improve the visual consistency. The refactoring of existing views to use these new components is clean and effective, especially the simplification of the Sidebar component. I've identified a few areas for improvement, mainly concerning hardcoded values that need to be made dynamic, a minor bug with a fallback icon, and some type safety issues that should be addressed.

Comment on lines +41 to +69
<div className="px-5 pb-6 space-y-4 flex-shrink-0">
<div className="grid grid-cols-4 gap-2">
<button className="col-span-2 bg-dark-850/60 hover:bg-dark-700 text-slate-200 py-2 px-3 rounded-lg border border-white/5 flex items-center justify-center gap-2 transition text-xs font-medium shadow-lg shadow-black/20 group">
<Plus className="w-3.5 h-3.5 group-hover:text-brand-cyan transition-colors" /> New
</button>
<button className="col-span-1 bg-dark-850/60 hover:bg-dark-700 text-slate-400 hover:text-white py-2 rounded-lg border border-white/5 flex items-center justify-center transition">
<Folder className="w-3.5 h-3.5" />
<span className="ml-1 text-[10px]">0</span>
</button>
<button className="col-span-1 bg-dark-850/60 hover:bg-dark-700 text-slate-400 hover:text-white py-2 rounded-lg border border-white/5 flex items-center justify-center transition relative">
<Bell className="w-3.5 h-3.5" />
<span className="absolute top-2 right-2.5 w-1.5 h-1.5 bg-brand-red rounded-full ring-2 ring-dark-850"></span>
</button>
</div>

{/* Project Selector */}
<div className="bg-dark-850/40 border border-white/5 rounded-xl p-1 flex items-center justify-between cursor-pointer hover:border-white/10 hover:bg-dark-850/60 transition group">
<div className="flex items-center gap-3 px-2 py-1.5">
<FolderOpen className="w-4 h-4 text-brand-cyan group-hover:text-cyan-300 transition" />
<span className="text-white font-medium text-sm">test case 1</span>
</div>
<div className="flex items-center gap-1 pr-1">
<span className="w-5 h-5 rounded bg-dark-700 flex items-center justify-center text-[10px] text-slate-400 font-bold border border-white/5">
P
</span>
<MoreVertical className="w-4 h-4 text-slate-500" />
</div>
</div>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This section contains several hardcoded values and non-functional interactive elements. For example, the 'New' button, project selector, and folder count are static. These should be connected to the application's state and logic to be functional.

Comment on lines +151 to +153
<span className="flex h-5 w-5 items-center justify-center rounded-full bg-brand-cyan text-[10px] text-black font-bold shadow-glow-cyan">
3
</span>
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 number of running agents is hardcoded as 3. This should be a dynamic value fetched from the application state.

Comment on lines +5 to +36
<header className="h-16 glass-header flex items-center justify-between px-8 flex-shrink-0 z-20">
<div>
<h1 className="text-white font-bold text-lg tracking-tight">Kanban Board</h1>
<p className="text-xs text-slate-500 font-medium font-mono mt-0.5">test case 1</p>
</div>

<div className="flex items-center gap-4">
{/* User Toggle */}
<div className="flex items-center bg-dark-850/60 rounded-lg p-1 border border-white/5 h-9 shadow-inner-light">
<div className="flex items-center gap-3 px-2 border-r border-white/5 h-full mr-2">
<Users className="w-3.5 h-3.5 text-slate-400" />
{/* Toggle Switch */}
<div className="w-[28px] h-[16px] bg-[#2d3546] rounded-full relative cursor-pointer border border-white/10 transition-colors">
<div className="absolute top-[2px] right-[2px] w-[10px] h-[10px] bg-brand-cyan rounded-full shadow-[0_0_6px_rgba(6,182,212,0.6)]"></div>
</div>
</div>
<span className="text-xs text-slate-400 px-1 font-mono">3</span>
</div>

{/* Auto Mode */}
<button className="flex items-center gap-2 text-slate-300 hover:text-white px-3 py-1.5 rounded-lg border border-white/5 bg-dark-850/60 hover:bg-dark-700 transition text-xs font-medium h-9">
<Play className="w-3.5 h-3.5 fill-current" />
<span>Auto Mode</span>
</button>

{/* Add Feature */}
<button className="flex items-center gap-2 bg-brand-cyan hover:bg-cyan-400 text-dark-950 font-bold px-4 py-1.5 rounded-lg transition shadow-glow-cyan text-xs h-9 btn-hover-effect">
<Plus className="w-4 h-4" />
<span>Add Feature</span>
</button>
</div>
</header>
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 TopHeader component has some hardcoded text and non-functional UI elements. The project name 'test case 1' and user count '3' should be dynamic. The user toggle switch is currently a static element and needs an onClick handler and state management to be functional. The 'Auto Mode' and 'Add Feature' buttons also lack functionality.

Comment on lines +110 to +126
{/* Fallback to SVG if i tag fails */}
<svg
xmlns="http://www.w3.org/2000/svg"
width="14"
height="14"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="lucide lucide-trash w-3.5 h-3.5"
>
<path d="M3 6h18" />
<path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
<path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
</svg>
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This fallback SVG will be rendered along with the Lucide icon generated from the <i> tag, resulting in duplicate icons. The lucide.createIcons() script does not remove sibling elements. Please remove this fallback SVG.

Comment on lines +112 to +114
const { orderedFeatures } = resolveDependencies(map.backlog as any) as {
orderedFeatures: Feature[];
};
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 use of as any here bypasses type safety. It seems resolveDependencies expects a different Feature type than what's provided. To maintain type safety, consider mapping the features to the expected type before passing them to the function, or making resolveDependencies generic if you control its source. For example: resolveDependencies(map.backlog as BaseFeature[]) if that's the expected type.


for (const f of orderedFeatures) {
if (getBlockingDependencies(f, allFeatures).length > 0) {
if (getBlockingDependencies(f as any, allFeatures as any).length > 0) {
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 other comment in this file, the as any casts here should be avoided. This indicates a type mismatch between the Feature type used in the UI and the type expected by getBlockingDependencies. Please resolve this type incompatibility to ensure type safety.

Copy link
Contributor

@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: 8

Caution

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

⚠️ Outside diff range comments (2)
apps/ui/src/components/views/board-view/components/kanban-card/kanban-card.tsx (1)

33-36: Props declared in interface but not destructured.

opacity, glassmorphism, cardBorderEnabled, and cardBorderOpacity are defined in KanbanCardProps (lines 33-36) but are not destructured in the function parameters (line 59 ends at summary). This creates a misleading API where callers can pass these props with no effect.

Either remove from the interface or implement the functionality.

🔎 Remove unused props from interface
 interface KanbanCardProps {
   // ... other props
   summary?: string;
-  opacity?: number;
-  glassmorphism?: boolean;
-  cardBorderEnabled?: boolean;
-  cardBorderOpacity?: number;
 }

Also applies to: 59-59

apps/ui/src/store/app-store.ts (1)

547-577: Wire Claude usage actions into AppActions and persist the refresh interval

The Claude usage state/actions are well-structured, but two follow-ups are needed:

  1. AppActions is missing the new action signatures (type error)

    • setClaudeRefreshInterval, setClaudeUsageLastUpdated, and setClaudeUsage are implemented in the store but not declared in AppActions.
    • With create<AppState & AppActions>(), this object literal will have excess properties and any useAppStore((s) => s.setClaudeUsage) call will not type‑check.
  2. claudeRefreshInterval is a preference but not persisted

    • partialize currently omits claudeRefreshInterval, so user changes revert to 60 on reload.
Proposed typings & persistence fixes
@@
 export interface AppActions {
@@
   // Plan Approval actions
   setPendingPlanApproval: (
@@
   ) => void;
+
+  // Claude Usage Tracking actions
+  setClaudeRefreshInterval: (interval: number) => void;
+  setClaudeUsageLastUpdated: (timestamp: number | null) => void;
+  setClaudeUsage: (usage: ClaudeUsage | null) => void;
@@
       // Claude Usage Tracking actions
-      setClaudeRefreshInterval: (interval: number) => set({ claudeRefreshInterval: interval }),
-      setClaudeUsageLastUpdated: (timestamp: number) => set({ claudeUsageLastUpdated: timestamp }),
-      setClaudeUsage: (usage: ClaudeUsage | null) =>
+      setClaudeRefreshInterval: (interval) => set({ claudeRefreshInterval: interval }),
+      setClaudeUsageLastUpdated: (timestamp) =>
+        set({ claudeUsageLastUpdated: timestamp }),
+      setClaudeUsage: (usage) =>
         set({
           claudeUsage: usage,
           claudeUsageLastUpdated: usage ? Date.now() : null,
         }),
@@
       partialize: (state) =>
         ({
@@
           defaultPlanningMode: state.defaultPlanningMode,
           defaultRequirePlanApproval: state.defaultRequirePlanApproval,
           defaultAIProfileId: state.defaultAIProfileId,
+          claudeRefreshInterval: state.claudeRefreshInterval,
           // eslint-disable-next-line @typescript-eslint/no-explicit-any
         }) as any,

Also applies to: 586-613, 905-909, 2571-2577, 2674-2723

🧹 Nitpick comments (8)
apps/ui/src/components/layout/sidebar.tsx (1)

172-212: Consider extracting NavItem to a separate file.

The local NavItem component is well-implemented but differs from the NavItem interface in apps/ui/src/components/layout/sidebar/types.ts (which uses id instead of to and isActive). This could cause confusion.

Consider either:

  1. Extracting this component to its own file
  2. Aligning with the existing NavItem type interface
apps/ui/src/components/views/board-view/components/kanban-card/kanban-card.tsx (1)

149-151: Hardcoded fallback model name.

The fallback 'Opus 4.2' should use a constant (like DEFAULT_MODEL from @/lib/agent-context-parser) for consistency and maintainability.

🔎 Suggested fix
+import { DEFAULT_MODEL, formatModelName } from '@/lib/agent-context-parser';
+
 // In JSX:
           <span className="text-[10px] text-brand-cyan font-mono">
-            {feature.model || 'Opus 4.2'}
+            {formatModelName(feature.model ?? DEFAULT_MODEL)}
           </span>
apps/ui/src/styles/global.css (1)

4-71: Tokenized theme & glass utilities look solid; consider aligning backdrop-filter prefixes

The centralized @theme tokens and glass-* utilities are structured well and line up with the new layout/components. One minor consistency tweak you might consider later:

  • glass-sidebar, glass-header, and glass-card define both backdrop-filter and -webkit-backdrop-filter, but glass-panel only sets backdrop-filter. For Safari parity, you may want to add the -webkit- prefix there as well, unless you’re relying entirely on Lightning CSS to inject it.

Also applies to: 73-142, 144-150, 152-168

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

20-21: TopHeader is purely presentational here; consider making it data‑driven

Right now TopHeader renders a hard-coded “Kanban Board” title, subtitle, and static Auto Mode/Add Feature controls, without any connection to this view’s actual state or handlers.

If this header is meant to be reused across views (as in other files in this PR), it would scale better as a data‑driven component, e.g.:

  • Accept title/subtitle props instead of hard-coding “Kanban Board” / “test case 1”.
  • Accept callbacks like onToggleAutoMode and onAddFeature and wire them to the real board actions.

Not blocking, but moving this direction will avoid duplicate/placeholder controls and mismatched titles across views.

Also applies to: 922-924


265-275: Tighten up branchCardCounts typing to avoid unnecessary casts

The reduce implementation is correct, but this line:

const branch = (feature.branchName as string) ?? 'main';

relies on a cast that isn’t needed and can hide null/undefined at the type level.

You can let types reflect the runtime behavior more directly:

- const branch = (feature.branchName as string) ?? 'main';
+ const branch = feature.branchName ?? 'main';

This keeps the same semantics (nullish => 'main') while preserving accurate types for branchName.

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

70-81: Unify theme types instead of relying on a cast

handleSetTheme is typed against the store’s theme value and then cast to (theme: Theme) => void for AppearanceSection. That’s safe as long as Theme and the store’s theme type stay in sync, but the cast will mask future drift.

If possible, prefer a single shared Theme/ThemeMode type (re-exported from the store or settings types) so both SettingsView and AppearanceSection use the same source of truth and the cast isn’t needed.

Also applies to: 110-114

apps/ui/src/components/layout/top-header.tsx (1)

1-38: Generalize TopHeader and wire it to real actions

The visual implementation and use of the new glass/brand utilities are good, but as a shared layout piece:

  • Title/subtitle are hard-coded to “Kanban Board” / “test case 1”.
  • The user toggle, Auto Mode button, and Add Feature button are purely decorative—no props or callbacks, and the toggle isn’t even a semantic control.

Given this header is imported in multiple views, consider:

  • Adding props for title, subtitle, and handler callbacks (onToggleUsers, onToggleAutoMode, onAddFeature, etc.).
  • Converting the toggle markup into a <button> (or similar) with appropriate ARIA attributes if it’s meant to be interactive.

That will avoid misleading headers and dead controls as the layout is reused.

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

64-72: Clarify the accent-to-color mapping for status dots.

The mapping seems inconsistent: accent === 'blue' renders an orange dot (bg-brand-orange) with the comment "In Progress has orange dot in design". This creates a disconnect between the semantic meaning of the accent prop and the actual visual output.

Consider either:

  1. Renaming the accent values to match their visual purpose (e.g., 'in-progress' instead of 'blue')
  2. Or documenting this intentional mapping in the interface/component comments
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d50b15e and 379976a.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (24)
  • apps/ui/src/components/layout/app-layout.tsx
  • apps/ui/src/components/layout/sidebar.tsx
  • apps/ui/src/components/layout/top-header.tsx
  • apps/ui/src/components/ui/glass-card.tsx
  • apps/ui/src/components/ui/glass-panel.tsx
  • apps/ui/src/components/views/agent-tools-view.tsx
  • apps/ui/src/components/views/agent-view.tsx
  • apps/ui/src/components/views/board-view.tsx
  • apps/ui/src/components/views/board-view/components/kanban-card/card-header.tsx
  • apps/ui/src/components/views/board-view/components/kanban-card/kanban-card.tsx
  • apps/ui/src/components/views/board-view/components/kanban-column.tsx
  • apps/ui/src/components/views/board-view/constants.ts
  • apps/ui/src/components/views/board-view/hooks/use-board-column-features.ts
  • apps/ui/src/components/views/board-view/kanban-board.tsx
  • apps/ui/src/components/views/board-view/worktree-panel/components/worktree-tab.tsx
  • apps/ui/src/components/views/running-agents-view.tsx
  • apps/ui/src/components/views/settings-view.tsx
  • apps/ui/src/components/views/terminal-view.tsx
  • apps/ui/src/components/views/terminal-view/terminal-panel.tsx
  • apps/ui/src/config/terminal-themes.ts
  • apps/ui/src/routes/__root.tsx
  • apps/ui/src/store/app-store.ts
  • apps/ui/src/styles/global.css
  • index (28).html
🧰 Additional context used
🧬 Code graph analysis (10)
apps/ui/src/components/ui/glass-card.tsx (1)
apps/ui/src/lib/utils.ts (1)
  • cn (5-7)
apps/ui/src/components/views/board-view/hooks/use-board-column-features.ts (2)
apps/ui/src/store/app-store.ts (1)
  • Feature (267-294)
apps/server/src/services/feature-loader.ts (1)
  • Feature (20-20)
apps/ui/src/components/views/board-view/components/kanban-column.tsx (2)
apps/ui/src/components/ui/glass-panel.tsx (1)
  • GlassPanel (8-27)
apps/ui/src/lib/utils.ts (1)
  • cn (5-7)
apps/ui/src/components/layout/app-layout.tsx (1)
apps/ui/src/components/layout/sidebar.tsx (1)
  • Sidebar (23-170)
apps/ui/src/components/layout/sidebar.tsx (2)
apps/ui/src/components/layout/sidebar/types.ts (1)
  • NavItem (9-14)
apps/ui/src/lib/utils.ts (1)
  • cn (5-7)
apps/ui/src/routes/__root.tsx (1)
apps/ui/src/components/layout/app-layout.tsx (1)
  • AppLayout (9-36)
apps/ui/src/components/views/board-view.tsx (1)
apps/ui/src/components/layout/top-header.tsx (1)
  • TopHeader (3-38)
apps/ui/src/components/views/terminal-view.tsx (3)
apps/ui/src/components/layout/top-header.tsx (1)
  • TopHeader (3-38)
apps/ui/src/components/ui/glass-panel.tsx (1)
  • GlassPanel (8-27)
apps/ui/src/lib/utils.ts (1)
  • cn (5-7)
apps/ui/src/components/views/board-view/components/kanban-card/kanban-card.tsx (5)
apps/ui/src/components/ui/glass-card.tsx (1)
  • GlassCard (8-25)
apps/ui/src/components/views/board-view/components/kanban-card/card-badges.tsx (2)
  • CardBadges (38-122)
  • PriorityBadges (128-244)
apps/ui/src/components/views/board-view/components/kanban-card/card-header.tsx (1)
  • CardHeaderSection (37-314)
apps/ui/src/components/views/board-view/components/kanban-card/card-content-sections.tsx (1)
  • CardContentSections (9-50)
apps/ui/src/components/views/board-view/components/kanban-card/agent-info-panel.tsx (1)
  • AgentInfoPanel (46-273)
apps/ui/src/components/views/agent-tools-view.tsx (4)
apps/ui/src/components/layout/top-header.tsx (1)
  • TopHeader (3-38)
apps/ui/src/components/ui/glass-panel.tsx (1)
  • GlassPanel (8-27)
apps/ui/src/components/ui/glass-card.tsx (1)
  • GlassCard (8-25)
apps/ui/src/lib/utils.ts (1)
  • cn (5-7)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: e2e
🔇 Additional comments (29)
apps/ui/src/components/views/board-view/worktree-panel/components/worktree-tab.tsx (2)

3-3: LGTM! React import added for type support.

The React import is correctly added to support the React.ReactNode type used on line 91. Modern React doesn't require this import for JSX rendering, but it's necessary for TypeScript type references.


91-91: LGTM! Type widening improves flexibility.

The type change from JSX.Element | null to React.ReactNode | null is a safe enhancement that maintains current behavior while allowing more flexible badge content in the future (e.g., text nodes, fragments, or arrays). This follows React conventions where ReactNode is the standard type for renderable content.

apps/ui/src/config/terminal-themes.ts (1)

64-64: Transparent terminal background may cause readability issues.

With background: 'transparent', terminal text visibility depends entirely on the parent container's glassmorphism backdrop. If the terminal is rendered outside a properly styled glass container, text may become unreadable.

Consider adding a fallback or documenting the requirement that terminals must be wrapped in a glassmorphism-styled container.

apps/ui/src/components/layout/app-layout.tsx (1)

9-36: Clean layout structure with proper layering.

The AppLayout component properly implements the glassmorphism foundation with:

  • Ambient background blobs at z-0
  • Main content elevated at z-10
  • Sidebar integration
  • Proper overflow handling

The comment noting TopHeader is now view-specific is helpful for maintainability.

apps/ui/src/components/ui/glass-card.tsx (1)

8-26: Well-structured GlassCard component.

The implementation correctly uses forwardRef for ref forwarding, applies variant-based classes conditionally, and allows className overrides via the cn utility.

Minor consideration: The base rounded-xl p-4 classes are always applied. If a consumer needs different padding/rounding, they'd need to use !important or override classes. This is likely acceptable for design consistency.

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

5-29: Clean extension of COLUMNS with accent property.

The accent mapping logically aligns with column semantics and integrates well with the new GlassPanel/GlassCard styling system. The inline type definition keeps related code together.

index (28).html (1)

1-21: Clarify the purpose and location of this HTML prototype file.

This static HTML file appears to be a design prototype that duplicates the glassmorphism styling and Kanban layout implemented in the React components. Key concerns:

  1. File naming: index (28).html is non-standard (spaces and parentheses)
  2. Location: Should be in a /docs, /design, or /prototypes directory
  3. Maintenance burden: Style definitions duplicate those in global.css and components, risking drift

Is this intended as documentation, a design reference, or should it be removed before merge?

apps/ui/src/store/app-store.ts (1)

15-22: Planning-related Feature extensions look consistent

The new type exports, optional steps, and PlanSpec/planning fields on Feature are coherent and match how planning/approval is handled elsewhere. No correctness issues stand out here.

Also applies to: 267-293, 305-317

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

100-105: Accent forwarding into KanbanColumn is correct

Passing accent={column.accent} keeps the board data-driven and lets columns pick up the new accent styling without affecting behavior. Looks good.

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

535-547: Transparency enablement for xterm matches the new glass UI

Setting allowTransparency: true on the Terminal and driving the container background from currentTerminalTheme.background is consistent with the glassmorphism layout. No issues spotted here.

Also applies to: 2066-2074

apps/ui/src/routes/__root.tsx (1)

3-4: Root layout migration to AppLayout looks correct

Wrapping non-setup routes in AppLayout and switching the inner container to h-full under that shell is consistent with the new global layout. The streamer panel z-index bump to z-50 should also help avoid it being hidden behind new glass headers.

Also applies to: 161-178

apps/ui/src/components/views/terminal-view.tsx (3)

49-50: LGTM!

Clean imports of the new layout primitives that align with the PR's glassmorphism design system.


1419-1424: LGTM!

The new layout structure using TopHeader and GlassPanel is well-organized and consistent with other views in this PR.


1590-1623: LGTM!

The conditional rendering for active tab content, empty states, and no-tabs states is well-structured with appropriate fallbacks and actionable UI elements.

apps/ui/src/components/ui/glass-panel.tsx (1)

1-28: LGTM!

Clean, well-structured component implementation. Good use of forwardRef for ref forwarding, proper TypeScript interface extension, and the accent variant pattern aligns well with the glassmorphism design system.

apps/ui/src/components/views/running-agents-view.tsx (2)

3-4: LGTM!

Imports align with the new layout system established in this PR.


107-223: LGTM!

Well-structured refactor using the new glassmorphism components. The responsive grid layout (grid-cols-1 md:grid-cols-2 xl:grid-cols-3) provides good scaling, and the agent cards have clear visual hierarchy with status indicators and actions.

apps/ui/src/components/views/agent-view.tsx (5)

53-54: LGTM!

Clean imports for the new layout primitives.


496-514: LGTM!

The new layout structure with TopHeader and collapsible session manager sidebar is well-organized. The GlassPanel wrapping provides consistent styling with other views.


515-620: LGTM!

The chat header with model selector, tool indicator, and action buttons is well-structured. The conditional rendering for connection status and current tool provides good user feedback.


621-779: LGTM!

Message rendering is preserved with updated styling. The avatar/bubble layout, image attachment display, thinking indicator, and scroll handling are all maintained correctly within the new glass panel structure.


780-991: LGTM!

Input area implementation is comprehensive with drag-drop, paste handling, file previews, and keyboard hints. The conditional rendering based on connection state and processing status is handled correctly.

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

5-5: LGTM!

GlassPanel import aligns with the new design system.


36-95: LGTM overall!

The GlassPanel integration is clean. The conditional glow gradients and drop-zone styling enhance the visual design. The component correctly forwards the ref and maintains droppable behavior.

apps/ui/src/components/views/agent-tools-view.tsx (5)

21-23: LGTM!

Clean imports for the new layout components.


195-215: LGTM!

The new layout structure with TopHeader and GlassPanel wrapper follows the established pattern from other views in this PR. The header with gradient icon is visually consistent with the glassmorphism design.


216-290: LGTM!

The Read File tool card is well-structured with clear visual hierarchy, appropriate input styling, and good feedback for success/error states.


291-374: LGTM!

The Write File tool card maintains consistency with the Read File card pattern while appropriately using green theming for the write operation.


375-472: LGTM!

The Terminal tool card and Tool Execution Log section complete the tools grid nicely. The log section provides helpful context for developers using the console.

<div className="bg-dark-850/40 border border-white/5 rounded-xl p-1 flex items-center justify-between cursor-pointer hover:border-white/10 hover:bg-dark-850/60 transition group">
<div className="flex items-center gap-3 px-2 py-1.5">
<FolderOpen className="w-4 h-4 text-brand-cyan group-hover:text-cyan-300 transition" />
<span className="text-white font-medium text-sm">test case 1</span>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, check if the sidebar.tsx file exists and examine its content
cat -n apps/ui/src/components/layout/sidebar.tsx | head -220

Repository: AutoMaker-Org/automaker

Length of output: 9475


🏁 Script executed:

# Search for state/context patterns related to projects and agents
rg -n "runningAgents|currentProject|activeProject" --type=ts -g '!*.test.*' -g '!*.spec.*' apps/ui/src/

Repository: AutoMaker-Org/automaker

Length of output: 46013


🏁 Script executed:

# Also search for any Redux or context API usage related to agents/projects
rg -n "useSelector|useDispatch|useContext|useState" apps/ui/src/components/layout/sidebar.tsx

Repository: AutoMaker-Org/automaker

Length of output: 49


🏁 Script executed:

# Check for environment or config files that might define these values
fd -t f "config\|env\|constant" apps/ui/src/ | head -20

Repository: AutoMaker-Org/automaker

Length of output: 49


Connect hardcoded values to application state.

These hardcoded placeholder values should use the existing app state:

  • Line 60: Project name "test case 1" should come from currentProject (available in app-store.ts)
  • Line 48: Folder count "0" should be dynamic based on project data
  • Lines 151-153: Running agents badge showing "3" should use the use-running-agents hook already available in apps/ui/src/components/layout/sidebar/hooks/use-running-agents.ts

The app already provides these via state management and hooks; other sidebar components (sidebar-footer.tsx, project-selector-with-options.tsx) demonstrate the correct pattern using useAppStore() and the running agents hook.

🤖 Prompt for AI Agents
In apps/ui/src/components/layout/sidebar.tsx around lines 48, 60, and 151-153,
replace hardcoded placeholders with app state: read currentProject from
useAppStore() and render its name instead of "test case 1" (line 60), compute
and render the folder count dynamically from currentProject (line 48) rather
than "0", and replace the hardcoded running-agents count on the badge (lines
151-153) by importing and using the existing use-running-agents hook
(apps/ui/src/components/layout/sidebar/hooks/use-running-agents.ts) to get the
current count; add any needed imports (useAppStore and the hook), guard for
null/undefined currentProject, and keep existing styling/structure while
inserting the dynamic values.

onEdit: () => void;
onDelete: () => void;
onViewOutput?: () => void;
hideActions?: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

hideActions prop is declared but never used.

The hideActions prop is added to the interface and destructured in the function, but the component logic never references it. All action buttons/dropdowns still render unconditionally.

If intended to hide the header actions (as suggested by usage in kanban-card.tsx with hideActions={true}), implement the conditional logic.

🔎 Suggested implementation
       {/* Running task header */}
-      {isCurrentAutoTask && (
+      {isCurrentAutoTask && !hideActions && (
         <div className="absolute top-2 right-2 flex items-center gap-1">

Apply similar guards to the other header action sections (lines 110-123, 126-179, 182-245).

Also applies to: 44-44

🤖 Prompt for AI Agents
In
apps/ui/src/components/views/board-view/components/kanban-card/card-header.tsx
around lines 34 and 44 (and the header action blocks at 110-123, 126-179,
182-245), the hideActions prop is declared/destructured but never used; update
the component to conditionally render the header action UI when hideActions is
false. Specifically, wrap each actions section (the three blocks mentioned) in a
guard such as if (!hideActions) then render that JSX (or use { !hideActions &&
(<...>) } inline), and keep the rest of the header markup unchanged; ensure
hideActions remains optional and destructured so callers passing
hideActions={true} hide all action controls.

Comment on lines +102 to +127
<button
onClick={(e) => {
e.stopPropagation();
onDelete();
}}
className="text-slate-600 hover:text-brand-red transition"
>
<i data-lucide="trash" className="w-3.5 h-3.5"></i>
{/* Fallback to SVG if i tag fails */}
<svg
xmlns="http://www.w3.org/2000/svg"
width="14"
height="14"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="lucide lucide-trash w-3.5 h-3.5"
>
<path d="M3 6h18" />
<path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
<path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
</svg>
</button>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Duplicate icons will render - both <i> tag and inline SVG.

The delete button contains both a <i data-lucide="trash"> element (which requires vanilla JS Lucide initialization) AND an inline SVG. In React, both elements will render simultaneously, showing two trash icons.

Additionally, data-lucide attributes are for vanilla JavaScript Lucide usage, not React. Use the Trash2 component from lucide-react instead.

🔎 Proposed fix
+import { Trash2 } from 'lucide-react';
+
 // In the JSX:
           <button
             onClick={(e) => {
               e.stopPropagation();
               onDelete();
             }}
             className="text-slate-600 hover:text-brand-red transition"
           >
-            <i data-lucide="trash" className="w-3.5 h-3.5"></i>
-            {/* Fallback to SVG if i tag fails */}
-            <svg
-              xmlns="http://www.w3.org/2000/svg"
-              width="14"
-              height="14"
-              viewBox="0 0 24 24"
-              fill="none"
-              stroke="currentColor"
-              strokeWidth="2"
-              strokeLinecap="round"
-              strokeLinejoin="round"
-              className="lucide lucide-trash w-3.5 h-3.5"
-            >
-              <path d="M3 6h18" />
-              <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
-              <path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
-            </svg>
+            <Trash2 className="w-3.5 h-3.5" />
           </button>

Comment on lines +112 to +114
const { orderedFeatures } = resolveDependencies(map.backlog as any) as {
orderedFeatures: Feature[];
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Find and examine the relevant file
find . -name "use-board-column-features.ts" -type f 2>/dev/null | head -5

Repository: AutoMaker-Org/automaker

Length of output: 143


🏁 Script executed:

# Check the file size first
wc -l "$(find . -name 'use-board-column-features.ts' -type f 2>/dev/null | head -1)"

Repository: AutoMaker-Org/automaker

Length of output: 147


🏁 Script executed:

# Look at the file around lines 100-135 to understand context
file_path=$(find . -name 'use-board-column-features.ts' -type f 2>/dev/null | head -1)
if [ -n "$file_path" ]; then
  sed -n '100,135p' "$file_path"
fi

Repository: AutoMaker-Org/automaker

Length of output: 1326


🏁 Script executed:

# Also get imports and top of the file
file_path=$(find . -name 'use-board-column-features.ts' -type f 2>/dev/null | head -1)
if [ -n "$file_path" ]; then
  echo "=== Imports and top of file ===" && head -30 "$file_path"
fi

Repository: AutoMaker-Org/automaker

Length of output: 1121


🏁 Script executed:

# Find Feature type definition
rg -A 10 "export.*interface Feature|export.*type Feature" --type ts

Repository: AutoMaker-Org/automaker

Length of output: 7107


🏁 Script executed:

# Look for the dependency-resolver package location
find . -name "dependency-resolver" -type d 2>/dev/null | grep -v node_modules

Repository: AutoMaker-Org/automaker

Length of output: 93


🏁 Script executed:

# Check if it's in packages
ls -la packages/ 2>/dev/null | grep dependency

Repository: AutoMaker-Org/automaker

Length of output: 49


🏁 Script executed:

# Search for resolveDependencies and getBlockingDependencies type definitions
rg -B 5 -A 10 "export.*function.*resolveDependencies|export.*const.*resolveDependencies" --type ts

Repository: AutoMaker-Org/automaker

Length of output: 1478


🏁 Script executed:

# Check imports and type definitions in dependency-resolver
head -50 libs/dependency-resolver/src/resolver.ts

Repository: AutoMaker-Org/automaker

Length of output: 2116


🏁 Script executed:

# Look for BaseFeature definition
rg -B 2 -A 15 "export.*interface BaseFeature|export.*type BaseFeature" --type ts

Repository: AutoMaker-Org/automaker

Length of output: 49


🏁 Script executed:

# Check DependencyResolutionResult type
rg -B 2 -A 10 "DependencyResolutionResult" libs/dependency-resolver --type ts

Repository: AutoMaker-Org/automaker

Length of output: 2560


🏁 Script executed:

# Check getBlockingDependencies signature
rg -B 5 -A 10 "export.*function.*getBlockingDependencies|export.*const.*getBlockingDependencies" libs/dependency-resolver --type ts

Repository: AutoMaker-Org/automaker

Length of output: 1221


🏁 Script executed:

# Find BaseFeature definition
rg -B 2 -A 20 "interface BaseFeature|type BaseFeature" --type ts

Repository: AutoMaker-Org/automaker

Length of output: 49


🏁 Script executed:

# Compare the full Feature definitions in both locations
echo "=== UI Feature ===" && sed -n '53,90p' apps/ui/src/store/app-store.ts && echo -e "\n=== Shared types Feature ===" && sed -n '33,60p' libs/types/src/feature.ts

Repository: AutoMaker-Org/automaker

Length of output: 2247


🏁 Script executed:

# Check what fields the dependency-resolver actually uses from Feature
rg -n "feature\." libs/dependency-resolver/src/resolver.ts | head -20

Repository: AutoMaker-Org/automaker

Length of output: 1049


🏁 Script executed:

# Get the full UI Feature interface definition
sed -n '34,110p' apps/ui/src/store/app-store.ts

Repository: AutoMaker-Org/automaker

Length of output: 2074


🏁 Script executed:

# Get BaseFeature definition to understand the inheritance
rg -B 2 -A 50 "interface BaseFeature" --type ts

Repository: AutoMaker-Org/automaker

Length of output: 49


🏁 Script executed:

# Find where BaseFeature is defined
rg "BaseFeature" --type ts | grep -E "(interface|type|import|export)" | head -10

Repository: AutoMaker-Org/automaker

Length of output: 49


🏁 Script executed:

# Get the full Feature definition from app-store
sed -n '1,150p' apps/ui/src/store/app-store.ts | grep -A 80 "export interface Feature"

Repository: AutoMaker-Org/automaker

Length of output: 49


🏁 Script executed:

# Check what BaseFeature is in the shared types
rg -B 5 -A 30 "^export.*BaseFeature" libs/types/src/feature.ts

Repository: AutoMaker-Org/automaker

Length of output: 49


🏁 Script executed:

# Search for BaseFeature more broadly
rg "BaseFeature" --type ts -A 2 -B 2

Repository: AutoMaker-Org/automaker

Length of output: 1122


🏁 Script executed:

# Get the complete Feature interface from app-store.ts
cat -n apps/ui/src/store/app-store.ts | sed -n '1,200p' | tail -100

Repository: AutoMaker-Org/automaker

Length of output: 3335


🏁 Script executed:

# Check the imports in app-store.ts to see where BaseFeature comes from
head -20 apps/ui/src/store/app-store.ts

Repository: AutoMaker-Org/automaker

Length of output: 488


🏁 Script executed:

# Get the complete UI Feature definition
sed -n '40,100p' apps/ui/src/store/app-store.ts

Repository: AutoMaker-Org/automaker

Length of output: 1726


🏁 Script executed:

# Check if status field in UI Feature matches what's needed
rg -A 50 "export interface Feature extends" apps/ui/src/store/app-store.ts | head -60

Repository: AutoMaker-Org/automaker

Length of output: 2057


🏁 Script executed:

# Let's verify the actual type compatibility by checking if there's a real type error
# First, check what fields dependency-resolver actually accesses
grep -n "feature\." libs/dependency-resolver/src/resolver.ts | grep -v "const\|const\|function\|export"

Repository: AutoMaker-Org/automaker

Length of output: 941


🏁 Script executed:

# Check the status field values expected by getBlockingDependencies
sed -n '200,215p' libs/dependency-resolver/src/resolver.ts

Repository: AutoMaker-Org/automaker

Length of output: 514


🏁 Script executed:

# Now let's trace what happens - check the usage at line 112-114
sed -n '105,130p' apps/ui/src/components/views/board-view/hooks/use-board-column-features.ts

Repository: AutoMaker-Org/automaker

Length of output: 1102


🏁 Script executed:

# Final verification: Check if TypeScript would actually complain without the casts
# by looking at the tsconfig and strict settings
cat tsconfig.json | grep -A 5 '"compilerOptions"'

Repository: AutoMaker-Org/automaker

Length of output: 112


🏁 Script executed:

# Check if there are any type errors in the build
find . -name "*.ts" -path "*/node_modules" -prune -o -type f -name "tsconfig.json" -print | head -3

Repository: AutoMaker-Org/automaker

Length of output: 159


🏁 Script executed:

# Check UI tsconfig
cat apps/ui/tsconfig.json | head -40

Repository: AutoMaker-Org/automaker

Length of output: 589


🏁 Script executed:

# Verify the actual type compatibility - simulate what TypeScript would do
# by checking if UI Feature can be passed to resolveDependencies
python3 << 'EOF'
# The key question: is UI Feature assignable to shared Feature?
# UI Feature:
#   - status: 'backlog' | 'in_progress' | 'waiting_approval' | 'verified' | 'completed'
#   - dependencies?: string[]
#   - id: string
#
# Shared Feature (from @automaker/types):
#   - status?: string (optional)
#   - dependencies?: string[]
#   - id: string
#
# TypeScript's structural typing analysis:
# 1. UI Feature has all required fields from Shared Feature
# 2. Extra fields in UI Feature are allowed (structural typing)
# 3. UI Feature.status is a union type that is assignable to string
# 4. Shared Feature.status is optional, UI Feature.status is required - this is OK (providing more)
#
# CONCLUSION: No type error should occur. The casts are UNNECESSARY.

print("Type Compatibility Analysis:")
print("=" * 50)
print("\nUI Feature.status: required union type")
print("  'backlog' | 'in_progress' | 'waiting_approval' | 'verified' | 'completed'")
print("\nShared Feature.status: optional string")
print("  status?: string")
print("\nStructural Typing Result:")
print("  ✓ UI Feature IS assignable to Shared Feature")
print("  ✓ No 'as any' cast is necessary")
print("  ✓ Casts indicate misunderstanding of type system")
EOF

Repository: AutoMaker-Org/automaker

Length of output: 153


Remove unnecessary as any casts — they provide no benefit and reduce type safety.

The UI Feature type from app-store.ts is structurally compatible with the Feature type expected by @automaker/dependency-resolver (from @automaker/types). Both types have the required id, optional dependencies, and a status field. The UI version provides a more specific status type (union literal), which is perfectly valid to pass where a general string type is expected. The casts at lines 112-114 and 127 are unnecessary and should be removed.

🤖 Prompt for AI Agents
In apps/ui/src/components/views/board-view/hooks/use-board-column-features.ts
around lines 112-114 (and the related cast at line 127), remove the unnecessary
"as any" casts (and any redundant "as { orderedFeatures: Feature[] }" return
cast) so TypeScript uses the actual UI Feature type that is structurally
compatible with the resolver. Simply call resolveDependencies(map.backlog)
without casting; if you need an explicit type for the returned shape, import the
appropriate Feature type and use a precise annotation (e.g., type the variable
that receives orderedFeatures) instead of forcing "any".


for (const f of orderedFeatures) {
if (getBlockingDependencies(f, allFeatures).length > 0) {
if (getBlockingDependencies(f as any, allFeatures as any).length > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Same type safety issue: eliminate as any casts.

This line exhibits the same problem as lines 112-114: bypassing type safety with as any casts. Both f (a Feature from orderedFeatures) and allFeatures (typed as Feature[]) should already be compatible with getBlockingDependencies.

Address this together with the previous issue by properly typing the dependency-resolver functions or creating appropriate type adapters.

🤖 Prompt for AI Agents
In apps/ui/src/components/views/board-view/hooks/use-board-column-features.ts
around line 127, remove the unsafe `as any` casts when calling
getBlockingDependencies by making the function and/or its inputs correctly
typed: update getBlockingDependencies signature to accept the concrete Feature
type and Feature[] (or create a typed adapter/converter that maps the existing
values to the expected param types), then call it with `f` and `allFeatures`
directly. Ensure any downstream calls and imports reflect the new signature and
remove the other `as any` casts at lines 112-114 as part of the same type-fix.

Comment on lines +1525 to 1531
onClick={() => {
if (terminalState.isUnlocked) setTerminalUnlocked(false);
else {
// Trigger lock logic (input password)
// Ideally show dialog, but for now just toggle for UI demo
}
}}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Incomplete lock button logic when terminal is locked.

The else branch (lines 1528-1530) does nothing when clicked in the locked state. The comment suggests showing a dialog, but currently clicking the button when locked has no effect, which is confusing UX.

Consider either:

  1. Removing the button entirely when locked (since password prompt shows below)
  2. Implementing the dialog/password prompt trigger
  3. At minimum, scrolling to or focusing the password input
🔎 Suggested fix to focus password input when locked
                onClick={() => {
                  if (terminalState.isUnlocked) setTerminalUnlocked(false);
                  else {
-                   // Trigger lock logic (input password)
-                   // Ideally show dialog, but for now just toggle for UI demo
+                   // Focus the password input in the locked state UI
+                   const passwordInput = document.getElementById('password');
+                   passwordInput?.focus();
                  }
                }}
📝 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
onClick={() => {
if (terminalState.isUnlocked) setTerminalUnlocked(false);
else {
// Trigger lock logic (input password)
// Ideally show dialog, but for now just toggle for UI demo
}
}}
onClick={() => {
if (terminalState.isUnlocked) setTerminalUnlocked(false);
else {
// Focus the password input in the locked state UI
const passwordInput = document.getElementById('password');
passwordInput?.focus();
}
}}

Comment on lines +1545 to +1558
{loading ? (
<div className="absolute inset-0 flex flex-col items-center justify-center gap-4 text-muted-foreground">
<Loader2 className="w-8 h-8 animate-spin text-brand-500" />
<p>Connecting to terminal server...</p>
</div>
) : error ? (
<div className="absolute inset-0 flex flex-col items-center justify-center gap-4 text-destructive">
<AlertCircle className="w-10 h-10" />
<p className="text-lg font-medium">{error}</p>
<Button variant="outline" onClick={fetchStatus}>
<RefreshCw className="w-4 h-4 mr-2" />
Retry Connection
</Button>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Unreachable code - duplicate loading/error handling.

These loading and error conditionals (lines 1545-1558) are unreachable because the component already returns early at lines 1297-1320 for these states. This dead code adds maintenance burden and confusion.

🔎 Suggested fix to remove unreachable code
          {/* Terminal Content Area */}
          <div className="flex-1 relative bg-black/40 backdrop-blur-sm">
-           {loading ? (
-             <div className="absolute inset-0 flex flex-col items-center justify-center gap-4 text-muted-foreground">
-               <Loader2 className="w-8 h-8 animate-spin text-brand-500" />
-               <p>Connecting to terminal server...</p>
-             </div>
-           ) : error ? (
-             <div className="absolute inset-0 flex flex-col items-center justify-center gap-4 text-destructive">
-               <AlertCircle className="w-10 h-10" />
-               <p className="text-lg font-medium">{error}</p>
-               <Button variant="outline" onClick={fetchStatus}>
-                 <RefreshCw className="w-4 h-4 mr-2" />
-                 Retry Connection
-               </Button>
-             </div>
-           ) : !terminalState.isUnlocked ? (
+           {!terminalState.isUnlocked ? (

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

🤖 Prompt for AI Agents
In apps/ui/src/components/views/terminal-view.tsx around lines 1545 to 1558
there is duplicate loading/error JSX that is unreachable because the component
returns early for loading and error states at lines 1297 to 1320; remove the
block between lines 1545–1558 to eliminate the dead conditional rendering and
keep the single early-return handling (ensure no other code depends on variables
declared only inside the removed block), leaving the component to render the
main UI path when not loading/error.

Comment on lines +17 to +20
<script src="https://cdn.tailwindcss.com"></script>

<!-- Lucide Icons -->
<script src="https://unpkg.com/lucide@latest"></script>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Unpinned CDN dependencies pose security and stability risks.

Using https://cdn.tailwindcss.com and https://unpkg.com/lucide@latest without version pinning:

  • May break unexpectedly when upstream updates
  • Prevents reproducible builds
  • Potential security risk from compromised CDN resources

If this file is kept, pin specific versions.

🔎 Suggested fix
-    <script src="https://cdn.tailwindcss.com"></script>
+    <script src="https://cdn.tailwindcss.com?plugins=forms@0.5.7"></script>
     
-    <script src="https://unpkg.com/lucide@latest"></script>
+    <script src="https://unpkg.com/lucide@0.562.0"></script>

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

🤖 Prompt for AI Agents
In index (28).html around lines 17 to 20, the HTML loads Tailwind and Lucide
from unpinned CDN URLs which risks breakage and security issues; update these
script references to use specific, tested versioned URLs (e.g., replace
https://cdn.tailwindcss.com with a pinned Tailwind CDN URL for the intended
version and replace https://unpkg.com/lucide@latest with a specific Lucide
release URL), and optionally add SRI integrity and crossorigin attributes or
vendor the assets into the project/build for reproducible, secure builds.

@SuperComboGamer SuperComboGamer added the Do Not Merge Use this label if something should not be merged. label Dec 23, 2025
@webdevcody
Copy link
Collaborator

keep branch around, closing to clean up pr queue

@webdevcody webdevcody closed this Jan 14, 2026
@Shironex Shironex deleted the new-ui-base branch February 15, 2026 15:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Do Not Merge Use this label if something should not be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants