> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tuturuuu.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Mind

> Mindboard satellite app for long-horizon planning, knowledge graphs, and AI-aided graph patches.

Mind lives in `apps/mind`, runs locally on port `7816`, and is served in
production from `https://mind.tuturuuu.com`. Local development should use
Portless at `https://mind.tuturuuu.localhost`; the legacy direct fallback is
`http://localhost:7816`.

Mind is available to signed-in Tuturuuu users, not only internal
`@tuturuuu.com` accounts. The satellite app accepts the Tuturuuu cross-app login
handoff through `/verify-token`, stores a host-local `tuturuuu_app_session`
cookie for the `mind` app target, and keeps workspace data behind membership
checks. Mind must not create a local Supabase Auth session.

Mind consumes `/verify-token` in the proxy and requires the coordinated cookie
pair on protected routes: the Mind-local app-session cookie for route guards and
the Web-issued app-session cookie for forwarded central APIs. If only the
Mind-local cookie remains, route users through local `/login` to refresh the
pair. Expired access tokens should rotate through
`/api/auth/refresh-app-session` on the Mind origin while refresh cookies are
valid.

Mind AI also follows the shared AI credit contract instead of an employee-only
allowlist. The `/api/ai/mind` route resolves the selected personal or workspace
credit source, checks the caller's membership for workspace credits, preflights
model availability and remaining credits, and deducts usage from that same
billing workspace after a successful stream.

Mind AI uses the stable `google/gemini-3.1-flash-lite` model entry for its
Flash Lite default/fallback surface. Stored preferences and old clients that
still send `google/gemini-3.1-flash-lite-preview` are normalized to the stable
ID before credit model resolution and provider streaming.

The model selector reads from the paginated infrastructure model catalog with
server-side search and "load more" pages. Do not reintroduce first-page-only
catalog fetches or local-only filtering; matching models must remain reachable
even when they are outside the initial response.

## Dual-Host Parity

Mind is available through both the standalone satellite host and the main web
dashboard. The standalone route shape stays `/{wsId}` and
`/{wsId}/boards/{boardId}`. Inside `apps/web`, the route shape is
`/{wsId}/mind` and `/{wsId}/mind/boards/{boardId}`.

Both hosts must render the same shared UI and use the same client logic from
`@tuturuuu/mind-ui`. Keep `apps/mind` and the `apps/web` Mind routes as thin
host wrappers for auth, workspace resolution, and route prefixing only. Future
Mind feature work belongs in `packages/mind-ui` or the centralized Mind APIs so
the standalone app and web-hosted app stay 1:1.

Board route-segment layouts that render Mind board routes must load
`@xyflow/react/dist/style.css`, and the shared Mind shell must keep a concrete
dashboard embed height. Keep that stylesheet out of root app layouts and the
Mind index so it is only loaded when users enter a canvas route. Without both
pieces, React Flow can mount but render as a blank or collapsed canvas inside
embedded dashboard routes.

## Board library vs studio

The workspace index route is a **board library**, not the canvas studio:

* **Web**: `/{wsId}/mind` lists boards (search, create, pick). Selecting or
  creating a board navigates to `/{wsId}/mind/boards/{boardId}` for the studio.
* **Satellite**: `/{wsId}` is the same board library; `/{wsId}/boards/{boardId}`
  is the studio.

`MindBoardIndex` from `@tuturuuu/mind-ui` owns the index experience. Do not
auto-select the first board on the index route. `MindDashboard` only mounts on
board routes and receives `initialBoardId`; it must not fall back to
`boards[0]`. If a board route loads without a selected board, prompt the user to
return to the index instead of showing an infinite loading state.

## API Ownership

Protected Mind data stays behind `apps/web` APIs:

* `/api/v1/workspaces/:wsId/mind/boards`
* `/api/v1/workspaces/:wsId/mind/boards/:boardId`
* `/api/v1/workspaces/:wsId/mind/boards/:boardId/graph`
* `/api/v1/workspaces/:wsId/mind/boards/:boardId/patches`
* `/api/v1/workspaces/:wsId/mind/search`
* `/api/v1/workspaces/:wsId/mind/ai/patches/:patchId/apply`
* `/api/v1/hive/servers/:serverId/mind-simulations` for importing a Mind board
  into Hive as agents plus a saved interaction workflow
* `/api/ai/mind`
* `/api/ai/chat/upload-url`, `/api/ai/chat/delete-file`, and
  `/api/ai/chat/file-urls` for Mind chat attachments

The Mind app forwards `/api/v1/*` and `/api/ai/*` to `apps/web` and consumes
them through `@tuturuuu/internal-api`. Do not add direct client Supabase reads
or client-local raw `fetch('/api/...')` calls for protected Mind data.

Workspace routes must normalize aliases such as `personal`, verify workspace
membership with the request-scoped auth context, and then perform private-schema
reads or writes through the centralized server repository.

Mind repositories must not use ad-hoc raw SQL from application code. Keep data
operations in private-schema Postgres RPCs and call them through a
service-role Supabase admin client with `.schema('private').rpc(...)`.
`apps/database/supabase/config.toml` exposes the `private` schema to PostgREST
so these RPCs are callable, but table/function grants stay service-role-only.
Changing that config requires a local Supabase restart or `bun sb:up` before the
Mind APIs stop returning `Invalid schema: private`.

The canvas should load from the graph-only snapshot path, while generated draft
patch artifacts load from the patch-list path. Do not couple canvas rendering to
recent AI patch serialization: a failed patch-artifact refresh should stay
inside the assistant panel and must not replace the board canvas with a board
load error. The legacy full snapshot can still return graph data plus patches
for backward compatibility.

Mind graph handles use loose React Flow connections with one visible connection
point per side. Cluster and children frames are synthetic canvas nodes used only
for interaction: manual links to a frame persist as normal node edges with frame
endpoint metadata, so saved graph payloads still satisfy the node-only edge
schema while rendering the relationship to the group boundary.
Nodes, relationships, clusters, and child-group frames should all be selectable
from the canvas. Node and relationship selections open editable properties,
while synthetic group or cluster frame selections open a compact read-only
properties island that identifies the anchor node and child count.

## Hive Integration

Inside `apps/web`, a Mind board can be sent to Hive from the compact top-right
canvas controls. The import API reads the saved Mind graph, verifies workspace
membership through the request-scoped client, requires Hive admin access, and
creates Hive NPC agents from the highest-signal Mind nodes. Mind edges become
Hive agent interaction pairs, and the generated Hive workflow first stamps the
Mind source context into the world before running the agent-interaction node.

Keep this integration hosted in `apps/web`: the standalone `apps/mind` surface
should stay a shared Mind canvas and must not assume that the Hive satellite is
available in the same host. Client code should call
`createHiveMindSimulation()` from `@tuturuuu/internal-api/hive`; do not add
client-local raw fetch calls or duplicate graph-to-agent conversion logic.

## Data Model

Mind product tables live in the `private` schema. User access goes through the
central web API; direct table access is service-role only.

* `private.mind_boards`
* `private.mind_nodes`
* `private.mind_edges`
* `private.mind_tags`
* `private.mind_node_tags`
* `private.mind_groups`
* `private.mind_group_nodes`
* `private.mind_node_links`
* `private.mind_ai_threads`
* `private.mind_ai_messages`
* `private.mind_ai_patches`

`mind_node_links` is the first integration seam for Tasks, Calendar, documents,
projects, and external URLs. Live pickers can attach to this link contract later
without changing the core graph schema.

Nodes carry a first-class workflow status: `backlog`, `planned`,
`in_progress`, `in_review`, `blocked`, `completed`, `deferred`, and
`cancelled`. The canvas and AI tools should treat status as a planning signal,
not just decoration: blocked nodes need dependencies, in-review nodes need
validation criteria, and completed nodes should remain available for historical
context and dependency tracing.

## AI Patch Safety

Mind AI chats default to review mode. In review mode, tools can inspect
mindboards, load graph chunks, search nodes, and store proposed patches, but the
user applies the patch explicitly from the Mind UI.

Direct-write mode is scoped to the current chat. In direct-write mode, the
`apply_mind_patch` tool can write the structured patch transactionally and the
repository records the patch status, `applied_at`, and applying user for audit.

Structured patches should stay small enough to review. Prefer multiple focused
patches over a single broad rewrite when consolidating large graphs.
For normal structure-generation requests, a patch should still be complete
enough to be useful: include the major clusters, concrete child nodes, and the
relationship edges that connect them to the root goal or to each other. Avoid
AI drafts that expand only one branch while leaving related top-level systems as
isolated nodes.
The existing board is authoritative. AI drafts should reuse and extend relevant
existing node IDs first, then create missing child nodes and relationships
around those anchors. Do not draft a detached replacement root when the current
mindboard already contains a matching goal, system, cluster, or milestone.
The patch tool normalizes generated aliases and stores operations in apply-safe
order: newly-created parent and child nodes are inserted before relationship
edges or updates that reference them. Existing draft patches are normalized
again just before application so older edge-first drafts do not fail foreign-key
checks.

For large boards, the assistant should inspect structure first, then search or
load neighborhoods/chunks instead of requesting a full graph by default. Keep
responses action-oriented: suggest follow-up passes, propose draft patches when
they are useful, and only implement graph writes when the chat is explicitly in
Implement mode.

After a draft patch is applied from the Mind UI, the client closes the
assistant panel, reloads the board, runs the smart canvas organizer, saves the
resulting positions, and refreshes board queries. The organizer should keep
true same-level sequence nodes in a compact horizontal lane, place explicit
children under their parent, and anchor supporting or dependency nodes near the
higher-level node they affect.
Applying a draft and refreshing layout are separate phases: once the patch
application RPC returns, patch artifacts should show `Applied` immediately. If
the follow-up auto-layout save fails, keep the patch applied and show a retryable
layout-refresh warning instead of treating the graph patch as failed.

Mind boards auto-save canvas edits. The board title, canvas tools, tag filter,
and save status live in one compact top-left island. The title is editable from
that island, the tag filter uses an icon-only ghost dropdown, and the save icon
shows saved, saving, unsaved, or retryable error state and can be clicked to
force a save. In the web-hosted board route, the compact top-right island owns
the Hive simulation launcher and the assistant toggle.
Autosave signatures, tag indexing, group-frame layout, and relationship routing
obstacle scans are intentionally debounced so dragging stays responsive on dense
boards; keep direct node movement immediate and move only derived calculations
onto short debounce windows.

React Flow canvas routes should pan with two-finger trackpad movement while
preserving pinch-to-zoom. Do not switch trackpad scrolling back to zoom-only
behavior; use explicit canvas controls or pinch gestures for zoom.

Generated plans and patch drafts should be treated as artifacts. The newest
artifact can open in the proposal island, while every message keeps a compact
artifact row for reopening it. When a generated visual plan and a draft patch
belong to the same assistant response, render them as one centralized draft
proposal pending approval: the structured patch preview is the review context,
and the single Apply action belongs to the proposal shell. Do not show the
visual plan and draft patch as duplicated stacked content. Tool-call and
artifact sections default to
collapsed compact rows; while the assistant is working, the row should show a
spinner and the latest tool or artifact name without expanding the full debug
list. When a draft is applied, the applied patch should render as `Applied` in
those artifact views instead of staying visually draft-only.

The canvas toolbar can copy the current board as Markdown or JSON. This export
uses the local in-canvas graph state, including unsaved position edits, so it is
useful for sharing a planning snapshot or debugging AI patch output.

## Deployment

Mind has dedicated Vercel workflows:

* `.github/workflows/vercel-preview-mind.yaml`
* `.github/workflows/vercel-production-mind.yaml`

Store `VERCEL_TOKEN`, `VERCEL_ORG_ID`, and `VERCEL_MIND_PROJECT_ID` in the
workflow environments `vercel-preview-mind` and `vercel-production-mind`.
Deployment should rely on Vercel project environment variables pulled by
`vercel pull`; do not add provider AI keys, production Supabase service keys,
`TURBO_TOKEN`, or `TURBO_TEAM` at workflow scope.

## Verification

After changing Mind schema, API, or UI code, run the most relevant focused
checks first, then the repo-required checks:

```bash theme={null}
bunx vitest run packages/internal-api/src/mind.test.ts packages/ai/src/mind/patch.test.ts
bun i18n:sort
bun type-check:mind
bun check
```

After applying the local Supabase migration, run `bun sb:typegen` and consume
database shapes through `@tuturuuu/types/db`.
