diff --git a/.env.example b/.env.example
index c9c03df..10a70c3 100644
--- a/.env.example
+++ b/.env.example
@@ -10,8 +10,14 @@
# =====================================================================
# ----- Database (CT 102 shared Postgres) -----
-# Local dev: postgresql://postgres:postgres@localhost:5432/tasks
-# Production: dedicated `echodo` user/db on CT 102
+# The database name is `echodo` everywhere — local dev, Coolify, and the
+# drizzle migration ledger all assume it. Do NOT use `tasks` (an early
+# pre-rename name); see commit 93565cd and the 2026-06 drift incident for
+# why a parallel `tasks` DB caused production OAuth to look broken when
+# it was really just connected to an empty schema.
+#
+# Local dev (Docker compose): postgresql://postgres:postgres@localhost:5432/echodo
+# Production (Coolify, CT 102): dedicated `echodo` user/db on shared Postgres
DATABASE_URL="postgresql://echodo:CHANGE_ME@192.168.68.102:5432/echodo"
# ----- Redis (CT 102 shared Redis) -----
@@ -79,7 +85,9 @@ MCP_SERVER_PORT=3001
# =====================================================================
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
-POSTGRES_DB=tasks
+# Keep this aligned with the database name in DATABASE_URL above. The
+# docker-compose files default to `tasks` (the old name) — override here.
+POSTGRES_DB=echodo
POSTGRES_PORT=5432
REDIS_PORT=6379
WEB_PORT=3000
diff --git a/AGENTS.md b/AGENTS.md
index 9a332e0..894e976 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -3,7 +3,7 @@
Operating manual for AI coding agents (Cursor, Codex, Copilot, etc.) working in this repo. Humans should read it too. Keep it short and accurate — if you change conventions in code, update this file in the same change.
> Product: **Echodo** — a multitenant task app whose backlog is mirrored as markdown under `plans/` and synced to Cursor.
-> Repo name on disk is `tasks`. Package scope is `@tasks/*`.
+> Repo name on disk is `tasks` and the package scope is `@tasks/*` (historical, pre-rename). Everything else — the database, the deploy, the public domain — is `echodo`. If you see a `tasks` database anywhere, it's an artifact of the old name; the source of truth is `echodo`.
---
@@ -55,6 +55,8 @@ Run from the repo root unless noted. Always use `pnpm`, never `npm` or `yarn`.
Before opening a PR or finishing a task, run **`pnpm lint && pnpm type-check && pnpm test`** at minimum. Run `pnpm build` if you touched build config, server entry points, or cross-package exports.
+If you edit anything under `apps/mcp-server/` or any library it imports, your changes won't be visible to MCP tool calls in the **current** Cursor chat — the MCP server is a long-lived stdio process per session and doesn't auto-reload. See the **MCP server lifecycle** section in [config/CursorSync.md](./config/CursorSync.md) for how to find and kill stale servers.
+
Tests live next to source as `*.test.ts` files. Vitest is configured per package (see `vitest.config.ts` in `packages/shared`, `packages/database`, `packages/ai`). When you add a new package that has logic worth verifying, copy one of those configs and add `test` / `test:watch` scripts to the package's `package.json`. CI gates merges on lint + type-check + test — see [.github/workflows/ci.yml](./.github/workflows/ci.yml).
---
@@ -64,6 +66,7 @@ Tests live next to source as `*.test.ts` files. Vitest is configured per package
- Local dev reads `.env` at the repo root. `.env.example` documents every variable; keep it in sync when you add a new one.
- `.env`, `*.secrets`, `*-credentials.*`, `id_rsa`, `*.key`, and `AGENT-DEPLOY.md` are gitignored. **Never** read `AGENT-DEPLOY.md` contents into a committed file, log, or PR description — it contains homelab IPs and credentials.
- Production deploys run on Coolify (CT 107) against shared Postgres/Redis on CT 102. Don't change deploy assumptions (Docker compose files, `next.config.docker.ts`) without flagging it explicitly.
+- **The Postgres database name is `echodo`**, full stop — local dev, Coolify, the drizzle migration ledger, and the docker-compose `POSTGRES_DB` all need to agree. An older `tasks` database may still exist on CT 102 as a relic of the pre-rename era; treat it as a dev sandbox at best and never point Coolify at it. The 2026-06 "Authentik SSO returns `Configuration`" incident was caused by Coolify pointing at `echodo` (correct) while a stale `tasks` database had the only initialized schema.
- `NEXT_PUBLIC_*` is the only browser-exposed prefix. Never put secrets behind it.
---
diff --git a/apps/web/components/layout/top-header.tsx b/apps/web/components/layout/top-header.tsx
index f6b4e81..3a71207 100644
--- a/apps/web/components/layout/top-header.tsx
+++ b/apps/web/components/layout/top-header.tsx
@@ -1,5 +1,6 @@
"use client";
+import { useState } from "react";
import { usePathname, useRouter } from "next/navigation";
import { signOut } from "next-auth/react";
import {
@@ -34,6 +35,7 @@ import {
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
+import { CreateWorkspaceDialog } from "@/components/workspaces/create-workspace-dialog";
import { useWorkspaceStore } from "@/lib/stores/workspace-store";
import { cn } from "@/lib/utils";
@@ -48,6 +50,7 @@ export function TopHeader({ onOpenSearch, onQuickAction }: TopHeaderProps) {
const workspace = useWorkspaceStore((s) => s.currentWorkspace);
const workspaceName = workspace?.name ?? "Workspace";
const workspaceId = workspace?.id;
+ const [createWorkspaceOpen, setCreateWorkspaceOpen] = useState(false);
const initials = workspaceName.trim().slice(0, 2).toUpperCase() || "WS";
return (
@@ -157,7 +160,7 @@ export function TopHeader({ onOpenSearch, onQuickAction }: TopHeaderProps) {
variant="outline"
size="sm"
className="w-full gap-1.5 text-xs"
- onClick={() => window.alert("Create workspace (placeholder)")}
+ onClick={() => setCreateWorkspaceOpen(true)}
>