diff --git a/packages/web/src/components/ActionMenu.tsx b/packages/web/src/components/ActionMenu.tsx
new file mode 100644
index 0000000..2713446
--- /dev/null
+++ b/packages/web/src/components/ActionMenu.tsx
@@ -0,0 +1,64 @@
+import { MoreHorizontal } from "lucide-react";
+import { Button } from "@/components/ui/button";
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+import { trpc } from "@/lib/trpc";
+
+interface ActionMenuProps {
+ initiativeId: string;
+ onDelete?: () => void;
+}
+
+export function ActionMenu({ initiativeId, onDelete }: ActionMenuProps) {
+ const utils = trpc.useUtils();
+
+ const archiveMutation = trpc.updateInitiative.useMutation({
+ onSuccess: () => {
+ utils.listInitiatives.invalidate();
+ onDelete?.();
+ },
+ onError: (err) => {
+ console.error("Failed to archive initiative:", err.message);
+ },
+ });
+
+ function handleArchive() {
+ const confirmed = window.confirm(
+ "Are you sure you want to archive this initiative? It can be restored later."
+ );
+ if (!confirmed) return;
+
+ archiveMutation.mutate({
+ id: initiativeId,
+ status: "archived",
+ });
+ }
+
+ return (
+
+
+
+
+
+ Edit
+ Duplicate
+
+
+ {archiveMutation.isPending ? "Archiving..." : "Archive"}
+
+ Delete
+
+
+ );
+}
diff --git a/packages/web/src/components/SpawnArchitectDropdown.tsx b/packages/web/src/components/SpawnArchitectDropdown.tsx
new file mode 100644
index 0000000..e54bb97
--- /dev/null
+++ b/packages/web/src/components/SpawnArchitectDropdown.tsx
@@ -0,0 +1,80 @@
+import { useState } from "react";
+import { ChevronDown } from "lucide-react";
+import { Button } from "@/components/ui/button";
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+import { trpc } from "@/lib/trpc";
+
+interface SpawnArchitectDropdownProps {
+ initiativeId: string;
+ initiativeName: string;
+}
+
+export function SpawnArchitectDropdown({
+ initiativeId,
+ initiativeName,
+}: SpawnArchitectDropdownProps) {
+ const [open, setOpen] = useState(false);
+ const [successText, setSuccessText] = useState(null);
+
+ const discussMutation = trpc.spawnArchitectDiscuss.useMutation({
+ onSuccess: () => {
+ setOpen(false);
+ setSuccessText("Spawned!");
+ setTimeout(() => setSuccessText(null), 2000);
+ },
+ onError: (err) => {
+ console.error("Failed to spawn discuss architect:", err.message);
+ },
+ });
+
+ const breakdownMutation = trpc.spawnArchitectBreakdown.useMutation({
+ onSuccess: () => {
+ setOpen(false);
+ setSuccessText("Spawned!");
+ setTimeout(() => setSuccessText(null), 2000);
+ },
+ onError: (err) => {
+ console.error("Failed to spawn breakdown architect:", err.message);
+ },
+ });
+
+ const isPending = discussMutation.isPending || breakdownMutation.isPending;
+
+ function handleDiscuss() {
+ discussMutation.mutate({
+ name: initiativeName + "-discuss",
+ initiativeId,
+ });
+ }
+
+ function handleBreakdown() {
+ breakdownMutation.mutate({
+ name: initiativeName + "-breakdown",
+ initiativeId,
+ });
+ }
+
+ return (
+
+
+
+
+
+
+ Discuss
+
+
+ Breakdown
+
+
+
+ );
+}