From 73d2680b83ccbdbd8dfec2d319533e98b379b830 Mon Sep 17 00:00:00 2001
From: bndw <ben@bdw.to>
Date: Wed, 4 Mar 2026 21:36:32 -0800
Subject: feat: Thread optional `phase` param into `db/sessions.ts::cre… (+7
 more)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

- ✅ Thread optional `phase` param into `db/sessions.ts::createSession()`
- ✅ Thread optional `phase` param into `ipc/handlers.ts` sessions:create handler
- ✅ Thread optional `phase` param into `preload.ts` createSession API
- ✅ Update Plan phase system prompt to gracefully handle missing research.md
- ✅ Update Implement phase system prompt to gracefully handle missing plan.md
- ✅ Create `renderer/src/components/NewSessionModal.tsx`
- ✅ Update `App.tsx`: add modal state, split handler, add modal JSX
- ✅ Add modal CSS to `globals.css`
---
 renderer/src/components/NewSessionModal.tsx | 60 +++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)
 create mode 100644 renderer/src/components/NewSessionModal.tsx

(limited to 'renderer/src/components/NewSessionModal.tsx')

diff --git a/renderer/src/components/NewSessionModal.tsx b/renderer/src/components/NewSessionModal.tsx
new file mode 100644
index 0000000..ad5dae9
--- /dev/null
+++ b/renderer/src/components/NewSessionModal.tsx
@@ -0,0 +1,60 @@
+import React, { useState, useEffect } from "react";
+import type { Phase } from "../types";
+
+interface NewSessionModalProps {
+  onConfirm: (phase: Phase) => void;
+  onCancel: () => void;
+}
+
+const phaseOptions: { phase: Phase; label: string; description: string }[] = [
+  { phase: "research",  label: "Research",  description: "Understand the codebase and requirements" },
+  { phase: "plan",      label: "Plan",      description: "Create a detailed implementation strategy" },
+  { phase: "implement", label: "Implement", description: "Execute the implementation plan" },
+];
+
+export function NewSessionModal({ onConfirm, onCancel }: NewSessionModalProps) {
+  const [selected, setSelected] = useState<Phase>("research");
+
+  // Close on Escape
+  useEffect(() => {
+    const onKey = (e: KeyboardEvent) => { if (e.key === "Escape") onCancel(); };
+    window.addEventListener("keydown", onKey);
+    return () => window.removeEventListener("keydown", onKey);
+  }, [onCancel]);
+
+  return (
+    <div className="modal-backdrop" onClick={onCancel}>
+      <div className="modal" onClick={(e) => e.stopPropagation()}>
+
+        <div className="modal-header">
+          <span className="modal-title">New Session</span>
+          <button className="modal-close" onClick={onCancel}>×</button>
+        </div>
+
+        <div className="modal-body">
+          <p className="modal-prompt">Choose where to start</p>
+          <div className="phase-cards">
+            {phaseOptions.map(({ phase, label, description }) => (
+              <button
+                key={phase}
+                className={`phase-card${selected === phase ? " selected" : ""}`}
+                onClick={() => setSelected(phase)}
+              >
+                <span className="phase-card-label">{label}</span>
+                <span className="phase-card-desc">{description}</span>
+              </button>
+            ))}
+          </div>
+        </div>
+
+        <div className="modal-footer">
+          <button className="modal-btn-secondary" onClick={onCancel}>Cancel</button>
+          <button className="modal-btn-primary" onClick={() => onConfirm(selected)}>
+            Create
+          </button>
+        </div>
+
+      </div>
+    </div>
+  );
+}
-- 
cgit v1.2.3

