Sistema de productividad y conocimiento personal construido desde código. Combina ejecución (tareas, proyectos, hábitos) con conocimiento vivo (notas atómicas Zettelkasten, links bidireccionales, grafo, AI copilot).
SecondMind es tu segundo cerebro en acción: una app para capturar ideas sin fricción, procesarlas en notas atómicas interconectadas, y usar ese conocimiento para alimentar proyectos, decisiones y hábitos diarios.
El proyecto nace de la experiencia de usar Notion como Segundo Cerebro y detectar sus límites: las notas entran y mueren, no hay conexiones entre ideas, la captura es lenta, y el inbox se acumula porque procesarlo es tedioso. SecondMind intenta resolver eso desde código, con un stack optimizado para instantaneidad, offline-first, y AI como copiloto.
Los principios de diseño, la teoría detrás (CODE de Tiago Forte, Zettelkasten), el modelo de datos y los flujos UX están documentados en Docs/.
- UI: React 19 + TypeScript strict + Vite + Tailwind CSS v4 + shadcn/ui (sobre Base UI)
- Estado: TinyBase v8 con custom persister Firestore
- Editor: TipTap (ProseMirror) con extensiones custom (wikilinks
@, slash commands/) - Búsqueda: Orama (FTS client-side)
- Backend: Firebase — Firestore + Cloud Functions v2 + Auth + Hosting
- AI: Claude Haiku para generación (inbox processing + auto-tagging) con la API key del usuario (BYOK) — sin key, la IA de generación queda deshabilitada; OpenAI embeddings con la key del proyecto
La fuente primaria de estado y arquitectura vigente es Spec/ESTADO-ACTUAL.md. Cada fase tiene su SPEC en Spec/; cada feature post-MVP en Spec/features/.
Beta cerrada. La app está LIVE en prod (app.getsecondmind.co, sobre v0.4.0) pero el acceso está gateado por una allowlist enforced en las Firestore rules (F50): hoy opera una única cuenta autorizada. No es registro abierto — toda cuenta fuera de la allowlist recibe
permission-denied. La apertura real de la beta llega en una versión posterior — ver el roadmap de versionado enSpec/ESTADO-ACTUAL.md.
-
Fase 0 — Setup ✅ Proyecto compilando, auth con Google, sync TinyBase ↔ Firestore, deploy a Firebase Hosting
-
Fase 0.1 — Toolkit ✅ MCPs (Firebase, Context7, Playwright, Brave Search), skills de frontend/UX, hooks de formato automático (Prettier + ESLint en PostToolUse), protección de la rama main
-
Fase 1 — MVP ✅ Primera versión usable diariamente. 9 features completas:
- F1 · Router: React Router con layout (sidebar + outlet) y rutas
/,/inbox,/notes,/notes/:noteId,/settings - F2 · Stores: TinyBase v8 con schemas de notes/links/inbox y custom persister Firestore con
merge: true - F3 · Quick Capture: modal global con shortcut
Alt+N, animación de confirmación, escribe alinboxStoresin clasificar - F4 · Editor: TipTap con StarterKit + Node custom
wikilink+ autocompletado al escribir[[. Auto-save con debounce de 2s. El JSON del doc va directo a Firestore; la metadata a TinyBase - F5 · Links bidireccionales: cada save sincroniza los wikilinks contra la colección
links/con IDs determinísticossource__target. Filtra self-links y actualizaincomingLinkIds/outgoingLinkIdsen ambas notas - F6 · Lista de notas + búsqueda: vista
/notescon FTS client-side vía Orama (rebuild on change delnotesStore), cards con título/snippet/badges/fecha relativa, y botón "Nueva nota" - F7 · BacklinksPanel: panel lateral en el editor que muestra las notas que apuntan a la actual, con contexto del párrafo. Toggleable, default abierto en desktop y cerrado en mobile. Resuelve títulos frescos haciendo join con
notesStore - F8 · Vista Inbox:
/inboxcon lista de items pendientes, acciones "Convertir a nota" y "Descartar". Badge reactivo con el count en el sidebar - F9 · Dashboard:
/con saludo contextual (mañana/tarde/noche), botón de captura rápida, card de inbox con los 3 items más recientes y card de notas recientes con las 5 últimas actualizaciones
- F1 · Router: React Router con layout (sidebar + outlet) y rutas
-
Fase 2 — Ejecución ✅ La capa de acción. 8 features completas:
- F1 · Stores y types:
tasksStore,projectsStore,objectivesStore,habitsStorecon schemas TinyBase + persister Firestore. Types para las 4 entidades +HABITSconst con los 14 hábitos hardcoded +AREASmap con las 6 áreas PARA. AlineaTaskStatusy agregaObjectiveStatusacommon.ts - F2 · Rutas y sidebar activo: 5 rutas nuevas (
/tasks,/projects,/projects/:projectId,/objectives,/habits) y activación de los 4 items del sidebar que antes estaban disabled. Active state por prefix match de NavLink - F3 · Tareas:
/taskscon tabs Hoy/Pronto/Completadas, creación inline conEnter,TaskCardcon priority badge color-coded (verde/amarillo/naranja/rojo), expand inline para editar descripción/prioridad/proyecto/fecha, y checkbox optimistic vía TinyBase. Tab "Hoy" incluye vencidas en sección separada; tab "Pronto" agrupa por día conIntl.DateTimeFormat - F4 · Proyectos:
/projectscon lista agrupada por status (En progreso → No empezados → En pausa; completados ocultos).ProjectCardcon count reactivo de tareas pendientes calculado cross-store (useTable('tasks')+useMemo). Modal de creación con área + prioridad que navega al detalle tras crear - F5 · Detalle de proyecto:
/projects/:projectIdcon header (nombre + selects de status/prioridad), barra de progreso completadas/total, sección Tareas que reusaTaskCardconprojectIdpre-asignado, y sección Notas vinculadas conNoteLinkModalque reusauseNoteSearchde Orama. Vinculación bidireccional client-sidenote.projectIds ↔ project.noteIds - F6 · Objetivos:
/objectivescon lista agrupada por área.ObjectiveCardcon progreso agregado (promedio del % de tareas completadas de cada proyecto vinculado), deadline formateado ("faltan N días" / "hoy" / "vencido hace N días"), y expand inline con<select>"+ Vincular proyecto..." que dispara el link bidireccionalobjective.projectIds ↔ project.objectiveId - F7 · Habit tracker:
/habitscon grid semanal 14×7 (14 hábitos × 7 días, lunes inicia la semana). Navegación ← → entre semanas, toggle de hoy/ayer clickeable, días pasados/futuros read-only. Barra de progreso de hoy referida al día real aunque se navegue a otra semana. IDs determinísticosYYYY-MM-DDcomorowIdydocId, con docs creados implícitamente en el primer toggle - F8 · Dashboard expandido: reestructura
/con 5 cards en grid 2×2 + hábitos full-width —TasksTodayCard(top 5 tareas de hoy con checkbox funcional),InboxCardexistente,ProjectsActiveCard(proyectos in-progress con count reactivo),RecentNotesCardexistente, yHabitsTodayCard(14 pills toggleables con barra de progreso)
- F1 · Stores y types:
-
Fase 3 — AI Pipeline ✅ Inteligencia que reduce la friccion de organizar. 6 features completas:
- F1 · Cloud Function processInboxItem:
onDocumentCreatedeninbox/{itemId}llama a Claude Haiku (claude-haiku-4-5-20251001) con tool use y schema enforcement, escribe campos flataiSuggested*(titulo, tipo, tags, area, resumen, prioridad) al doc. Secret viadefineSecret. Retry false, timeout 60s, us-central1 - F2 · Schema aiResult flat: reemplaza el placeholder
aiResult: stringdelinboxStorepor 6 campos flat. El hookuseInboxconstruye el objetoaiResultcon gateaiProcessed && aiSuggestedTitle. Cadena completa CF -> Firestore -> persister -> store -> mapper verificada - F3 · InboxItem card con sugerencias:
AiSuggestionCardcon display + edit modes. Muestra tipo/titulo/area/tags/prioridad/resumen sugeridos. Botones Aceptar (crea entidad con overrides) y Editar (expand form inline con selects + input tags comma-separated, parseo al submit). Indicator "Procesando con AI..." para items en flight. Botones fallback "Nota"/"Descartar" siempre visibles.useInboxcomponeuseTasks/useProjectsparaconvertToTask/convertToProjectconcreateTaskextendido (acepta{priority, areaId}en 1 write) - F4 · Inbox Processor: ruta
/inbox/processcon vista one-by-one. Snapshot congelado del batch al montar (permite Atras a items ya procesados sin que desaparezcan del array reactivo).InboxProcessorFormcon draft local reseteado porkey={item.id}. Read-only variant para items procesados. Progress dots clickeables. Keyboard shortcuts (Enter/Escape/ArrowLeft/ArrowRight). Pantalla done con resumen ("Procesaste N notas, M tareas, X descartados"). Grace de hidratacion dedicado (1500ms) para evitar false empty en full reload - F5 · Command Palette (Ctrl+K): modal de busqueda global con Orama FTS. Index unificado con campo
_type: 'note' | 'task' | 'project', rebuild con debounce 100ms en 3 store listeners. Query vacio muestra recientes (top 5 porupdatedAtdesc, filtra completed/archived) + acciones rapidas estaticas. Keyboard nav completo (arrows + Enter + Escape). Mouse hover sincronizado con keyboard index. Dialog base-ui con animacionesdata-starting-style/data-ending-style - F6 · Cloud Function autoTagNote:
onDocumentWrittenennotes/{noteId}genera hasta 5 tags + resumen con Claude Haiku via tool use y schema enforcement. GuardaiProcessed || !contentPlain.trim(). Cambio deonDocumentCreatedaonDocumentWrittenpara cubrir notas creadas vacias desde el editor (contenido llega en auto-save 2s despues). Fix critico:convertToNoteseteaaiProcessed: truecuando hay tags del inbox processor para evitar que F6 sobrescriba
- F1 · Cloud Function processInboxItem:
-
Fase 3.1 — Schema Enforcement ✅ Refactoring de las 2 Cloud Functions de AI para usar tool use de Anthropic (
tool_choice: { type: 'tool' }) con JSON Schema enforcement en vez de "Responde SOLO JSON" en el prompt. Elimina nulls en campos,stripJsonFence, fallbacks manuales, y ~120 lineas de codigo defensivo. Schemas compartidos enschemas.ts. Cero cambios en frontend — las CFs siguen escribiendo los mismos campos flat a Firestore. -
Fase 4 — Grafo + Resurfacing ✅ El conocimiento vuelve a aparecer. 5 features:
- F1 · Knowledge graph:
/notes/graphcon Reagraph (WebGL sobre Three.js). Nodos = notas, aristas = wikilinks. Filtros por tag/area, zoom, select para navegar al detalle - F2 · Embeddings (CF generateEmbedding):
onDocumentWrittenennotes/{noteId}genera vector 1536 dims con OpenAItext-embedding-3-small. Guard porcontentHashSHA-256 para evitar regeneraciones innecesarias. Persistidos enusers/{uid}/embeddings/{noteId} - F3 · Notas similares: panel lateral en el editor con cosine similarity sobre los embeddings cacheados en
useRef(embeddings NO van a TinyBase por tamaño) - F4 · FSRS spaced repetition: algoritmo
ts-fsrsclient-side para agendar revisiones de notas. Opt-in viaReviewBannercon 4 estados (activar/due/próxima/confirmación).fsrsDueen Firestore solo para notas activadas - F5 · Daily Digest: cards en el dashboard agrupando notas por hubs (tags con más incoming links) + orden determinístico del día via hash
noteId+date
- F1 · Knowledge graph:
-
Fase 5 — PWA + Chrome Extension ✅ Acceso desde donde sea. 2 features:
- F1 · PWA instalable:
vite-plugin-pwacongenerateSW+autoUpdate, manifest completo, navigateFallback para SPA routing offline, runtimeCaching de Google Fonts, install prompt en el Layout.useOnlineStatus(useSyncExternalStore) +OfflineBadge. Guards offline solo en features AI (procesar inbox, notas similares); el resto funciona via TinyBase - F2 · Chrome Extension MV3 (
extension/): CRXJS 2.4.0 + Vite 8, popup React con captura de selección del tab activo, auth Google viachrome.identity.getAuthToken+signInWithCredential, SDK lite (firebase/auth/web-extension+firebase/firestore/lite= 342KB / 105KB gzip),source: 'web-clip'consourceUrllimpiado de tracking params
- F1 · PWA instalable:
-
Fase 5.1 — Tauri Desktop ✅ Wrapper nativo Windows. 6 features:
- F1 · Scaffold: Tauri v2.10 integrado al proyecto existente (
src-tauri/). Consumedist/del build Vite. Scriptstauri:dev/tauri:build. Iconos generados desdepublic/pwa-512x512.png - F2 · System tray + close-to-tray: icono en la bandeja con menú (Abrir / Captura rápida / Iniciar con Windows / Salir). Click izq toggle main window. Botón X oculta en vez de terminar proceso
- F3 · Global shortcut
Ctrl+Shift+Space: desde cualquier app abre una ventana frameless/capture(480×220 frameless alwaysOnTop) con textarea enfocado. Enter escribe directo a Firestore consource: 'desktop-capture', Escape cierra. No colisiona conAlt+Nlocal - F4 · Autostart + window-state: toggle en el tray registra
HKCU\...\Run\SecondMind. Main window persiste pos/size; capture siempre centrada (denylist) - F5 · Single-instance + CSP Firebase: plugin previene procesos duplicados (crítico con autostart). CSP explícito en
tauri.conf.jsonpermite auth + firestore en release - F6 · OAuth Desktop flow (post-merge fix):
signInWithPopupno funciona en Tauri WebView2 (window.open va al browser del sistema, no puede postMessage back). Reemplazado por flow custom contauri-plugin-shell+ HTTP listener local en Rust (src-tauri/src/oauth.rs), PKCE S256, state CSRF, intercambio code→id_token,signInWithCredential. OAuth Client tipo "Desktop app" en Google Cloud Console.useAuthdetectaisTauri()y ramifica - Instaladores:
SecondMind_0.2.0_x64_en-US.msi+SecondMind_0.2.0_x64-setup.exe(NSIS, versión de entonces) ensrc-tauri/target/release/bundle/
- F1 · Scaffold: Tauri v2.10 integrado al proyecto existente (
-
Fase 5.2 — Capacitor Mobile (Android) ✅ Wrapper nativo Android. 5 features:
- F1 · Scaffold: Capacitor 8.3 integrado al proyecto (
android/Gradle project).appId com.secondmind.app, minSdk 24, compileSdk 36, targetSdk 36.server.androidScheme: 'https'obligatorio para Firebase Auth en WebView. Scriptscap:sync/cap:run/cap:build - F2 · Auth nativa Google Sign-In:
@capgo/capacitor-social-logincon bottom sheet nativo de Android. Patrón universalSocialLogin.login → idToken → GoogleAuthProvider.credential → signInWithCredential.MainActivity.java implements ModifiedMainActivityForSocialLoginPlugincononActivityResultforwarding.webClientId= Web Client ID de GCP (compartido con Tauri) - F3 · Share Intent:
@capgo/capacitor-share-targetrecibe texto/URL desde el menú "Compartir" de cualquier app Android.AndroidManifest.xmlcon intent-filterACTION_SEND text/*.useShareIntentextrae texto/URL del evento, detecta URLs con regex, llamaquickCapture.open(content, { source: 'share-intent', sourceUrl }). Reusa elQuickCaptureProviderya montado en el Layout (a diferencia de Tauri/captureque es ventana efímera) - F4 · Branding: ícono adaptive v26+ con VectorDrawable nativo extraído del
public/favicon.svg(21 paths + translate group para normalizar viewBox), fondo#171617matching el logo PWA. Splash screen drawable XML con color sólido#878bf9(el@capacitor/assets generateignora--splashBackgroundColory usa gris default). Edge-to-edge viaenv(safe-area-inset-*)enbody - F5 · APK debug:
./gradlew.bat assembleDebuggeneraapp-debug.apk(10.6MB) instalable en device físico viaadb install. SHA-1 del debug keystore registrado en Google Cloud Console para el Android OAuth Client
- F1 · Scaffold: Capacitor 8.3 integrado al proyecto (
-
Features 1-15 (marzo-abril 2026) ✅ Mejoras post-MVP sobre mobile, editor, búsqueda, infra y polish. 15 features completadas:
- F1 — Responsive & Mobile UX: shell con BottomNav + FAB + breakpoints mobile/tablet/desktop
- F2 — Editor Polish:
@para menciones, slash commands/(12 items en 5 categorías), templates Zettelkasten - F3 — Búsqueda Híbrida: keyword (Orama BM25) + semántica (embeddings cosine), CF callable
embedQuery - F4 — Progressive Summarization: 3 niveles de destilación L0/L1/L2/L3 de Tiago Forte sobre TipTap
- F5 — Bubble Menu: toolbar flotante con 6 acciones inline al seleccionar texto
- F6 — Theme System: claro / automático / oscuro, paleta violet oklch hue 285°, script inline anti-flash
- F7 — Capture Multi-Monitor: ventana
/capturecentrada en el monitor del cursor (lógica Rust-side entray.rs) - F8 — Tauri Auto-Updater: auto-update in-app con tag-based CI, firma ed25519, silent startup check
- F9 — Capacitor Auto-Update (Android): mismo flujo tag-based para APK vía Firebase App Distribution
- F10 — Capa de Repos (
src/infra/repos/): factory genérico, 6 repos, hooks −412 LoC, primeros tests Vitest - F11 — Store Isolation + Gating:
useStoreHydrationsignal real,delTablepre-init, cierra cross-user leak - F12 — Persister Diff-Based: consume
changesnativo de TinyBase v8, O(N) → O(cambios) en write amplification - F13 — GitHub Actions Node 24: migración
actions/*@v5+tauri-action@v0.6.2, prerelease guard RC/beta - F14 — Editor UX Polish: paste sanitization, slash menu con
@floating-ui/domflip dinámico,padding-bottom: 50vh - F15 — UI Polish Post-Dogfooding: scrollbar fantasma,
AuthLoadingSkeleton, imperativo neutro + tildes
-
Features 16-30 (abril 2026) ✅ Polish post-dogfooding, AI suggestions persistentes y retry queue end-to-end. 14 features completadas (F25 absorbida en F23):
- F16 — Code Block Scroll:
white-space: pre+max-width: 100%en<pre>para evitar que Tailwind v4 Preflight envuelva líneas largas; scroll horizontal preserva indentación en 375px - F17 — Editor Popup Hook Unificado:
useEditorPopup<TItem>encapsula slash + wikilink menus con Floating UI (flip,shift), close-on-scroll document capture deferred y keyboard nav - F18 — Notas Favoritas + Soft Delete:
isFavorite+deletedAtsentinel0(TinyBase no soporta null), cluster top-right enNoteCard+ConfirmDialog, favoritas anclan al tope sin query - F19 — Papelera con Auto-Purga: segmento 3 tabs en
/notes,trashAutoPurgeDaysconfigurable, primera CF scheduledautoPurgeTrashy cleanup cascada víaonNoteDeleted(embeddings + links bidireccionales) - F20 — Search en Papelera +
defaultNoteType: búsqueda por substring en los 3 tabs (Orama excluye borradas) y preferencia de tipo default (la preferencia se revertió en F21) - F21 —
aiSummaryFleeting Default: toda nota nace'fleeting'(Zettelkasten flow) y se surfaceaaiSummaryhuérfano como segunda línea enNoteCardcon itálica + Sparkles violet - F22 — Distill Levels Discoverability: badge L0 visible dashed violet, popover auto-abre primer mount (
distillIntroSeen), banner ascendente per-nivel 3s, copy L3 reformulado a "tu yo del futuro" - F23 — AI Suggestions: banner contextual en editor con accept/dismiss, AI server-side via
autoTagNoteextendida (prompt cachingephemeral) + heurística client-side,arrayUnioncon bypassupdateDoc. Absorbió F25 del roadmap - F24 — FSRS Widget Mejorado:
ReviewCardseparado de hubs con copy "Te toca/Te tocan N", botón "Ver todas las due" cuando >5, tab "Por revisar" en/notescon search local + deep-link?filter=review - F26 — Inbox Batch + Confidence: CF
processInboxItemdevuelveconfidence: 0..1, UI agrupa items en buckets "Alta confianza ≥0.85" / "Revisar", botónAceptar N itemscon batch-accept por tipo y badge % verde/ámbar por item - F27 — Cleanup Deuda QA: borra campo muerto
relatedNoteIds, separasetTimeoutdebatchStatusenuseEffectpropio (patrón canónico F22), guardexistingDoc.existsengenerateEmbeddingpara limpiar embeddings stale cuandocontentPlainqueda vacío - F28 —
saveContentRetry/Rollback: retry queue in-memory con backoff[1s, 2s, 4s]× 4 attempts,SaveStatus5 estados viauseSyncExternalStore, banner top-of-page con[Reintentar / Descartar / Copiar contenido], listenersbeforeunload+onlinepara flush + recovery, Tauri close-to-tray con timeout 2s - F29 — Retry Queue al Factory Entero:
RepoConfig<Row>parametrizado conqueue?: SaveQueue<Partial<Row>>, 7 singletons (saveContentQueue+ 6 metas por entidad),<PendingSyncIndicator />global en sidebar/header con popover per-entity counts, sign-out mid-retry guard,clear()separado dedispose()para test isolation - F30 — Retry Queue en los Creates: 4 singletons dedicados (
saveNotesCreatesQueue,saveTasksCreatesQueue,saveProjectsCreatesQueue,saveObjectivesCreatesQueue),RepoConfig.createsQueue?opcional,useNoteviauseSyncExternalStore+setDoc(merge:true)ensaveContent(D9) para tolerarnot-founddurante create-pending
- F16 — Code Block Scroll:
-
Features 31-37 (mayo-junio 2026) ✅ Hidden sidebar mode + sidebar reorg + flujo de update sin intervención manual + corpus de gotchas indexado. 7 features completadas:
- F31 — Hidden Sidebar Mode (desktop): preferencia
sidebarHiddencon<TopBar />alterno (logo +<PendingSyncIndicator compact />+ Buscar ⌘K + QuickCapture). ShortcutCmd+Blayout-independent víaevent.code === 'KeyB'con guards (foco editable / auth / breakpoint desktop).QUICK_ACTIONSdel CommandPalette pasa de 4 a 8 entries con iconos armonizados anavItems.ts - F32 — Hidden Sidebar Improvements: Cmd+K y Alt+N migrados a
event.code(paridad universal con F31). localStorage hint per-uid (secondmind:sidebarHidden:${uid}) enusePreferencespara hidratación síncrona pre-subscribe (anti-flash sin AND-gate). 9ª entry dinámica en CommandPalette ("Ocultar/Mostrar sidebar") conuseMemoreactivo. Animación entrada del componente swappeado solo en cambios subsecuentes —useLayoutEffectpre-paint para que el primer frame visible ya tenga la claseslide-in-from-X - F33 — Hidden Sidebar Polish: hook reutilizable
useMountedTransition(visible, durationMs): { shouldRender, isExiting }con patrónsetState durante render(skip-initial gratis sinuseRef).animate-out fill-mode-forwardsobligatorio para que el componente no revierta 1 frame pre-unmount. Botón "Mostrar menú" (PanelLeftOpen) a la izquierda del logo en TopBar - F34 — Sidebar reorg + dashboard cleanup: nav agrupado en 3 secciones (Ejecución / Captura / Conocimiento) en
navItems.tsconnavSections+navItemsderivado porflatMap. Buscar como input-shaped trigger embebido al tope abriendo CommandPalette. Capturar como botón primary full-width abriendo QuickCapture. Dashboard header simplificado al solo Greeting (eliminado botón redundante con la prop del sidebar). Gotcha drawer + modal nested resuelto cononClose() + requestAnimationFrame(open)handshake - F35 — Polish swap chrome (sidebar↔TopBar):
useMountedTransitionextendido conjustMounted: booleanstate-based +setTimeout(durationMs)— flags de animación deben sobrevivir re-renders mid-animación (nouseRef + 1-render-only). Sidebar always-floating overlay en desktop (absolute inset-y-0 left-0 z-30) contransition-[padding-left] duration-200en main column. Cierra los escenarios visible→hidden pop y hidden→visible shift - F36 — Cache stale + flujo de update sin intervención manual: ataque a 5 capas que se manifestaba como "no me permite crear ideas" tras update. F1 headers
no-cache+immutableenfirebase.json. F2-F4 PWAregisterType: 'prompt'+<UpdateBanner>+flushAll()antes del reload. F7.1 purga Rust-side ANTES del WebView load para SW residual (cohorte pre-F36 conskipWaiting: true). F8 schema versioning independiente —TINYBASE_SCHEMA_VERSIONyPREFERENCES_SCHEMA_VERSIONcon purge-on-mismatch asimétrico (TinyBase null=mismatch=purge zero data loss; preferences_schemaVersionausente=compat V1). Release v0.2.6 (hotfix sobre v0.2.5 que expuso bug latente CI conVITE_GOOGLE_OAUTH_*faltantes enrelease-tauriheredoc) - F37 — Split corpus de gotchas + skill BM25:
Spec/gotchas/<dominio>.md(15 archivos por dominio: editor, ui-componentes, tinybase-firestore, capacitor-mobile, tauri-desktop, etc.) extraídos del monolitoESTADO-ACTUAL.mdque cargaba 351 líneas para cualquier consulta de gotcha. Skill localgotchas-searchcon BM25 stdlib Python (k1=1.5, b=0.75, peso 2× título), tokenización Unicode-aware (\wmatchea ñ/á/é). Reindex automático via PostToolUse hook (matcher separado al editarSpec/gotchas/*.md). 197 gotchas indexados al cierre
Detalle técnico, decisiones y gotchas:
Spec/ESTADO-ACTUAL.mdySpec/features/SPEC-feature-*.md. - F31 — Hidden Sidebar Mode (desktop): preferencia
-
Features 38-50 (mayo 2026) ✅ Cleanup arquitectónico, fixes de plataforma y el bloque pre-beta. 13 features:
- F38-44 · Infra & polish: clean-arch cleanup (
linksRepo/inboxRepo), fixes CSP Tauri (grafo workers F39 + cloudfunctions F44), splash screens Android/Tauri (F40/F41), polish offline UX (F42), limpieza de nav mobile (F43). Detalle enSpec/ESTADO-ACTUAL.md - F45 · Code blocks: syntax highlighting con lowlight (25 lenguajes) + language picker; primer NodeView React del proyecto
- F46 · Split-pane multinota: dos notas lado a lado en
/notes/:noteId(?split=, atajoCmd/Ctrl+\), ratio persistido en preferences - F47 · Login redesign + email/password + capacity gate: LoginPage Linear-style con tabs email/pw + Google + reset password, verificación de email, y capacity gate ("Beta llena") sobre
config/app - F48 · BYOK API Keys: cada usuario aporta su propia API key de Anthropic (cifrada AES-256-GCM server-side, nunca vuelve al cliente); sin key, la IA de generación queda deshabilitada
- F49 · Onboarding:
WelcomeModalde 1 paso + checklist de 4 hitos reactivos en el dashboard (API key BYOK como hito central) - F50 · Security hardening + beta cerrada:
requireVerifieden los callables, allowlist enforced en rules + CFs + UX (beta cerrada), crypto AAD+keyVersion,maxInstancesbounded-cost, anti-enumeración en login
Detalle, decisiones y gotchas:
Spec/ESTADO-ACTUAL.mdySpec/features/SPEC-feature-*.md. - F38-44 · Infra & polish: clean-arch cleanup (
Ya se puede usar a diario: capturar ideas desde cualquier app con Ctrl+Shift+Space (desktop) o Alt+N (web/in-app), web clip desde Chrome via extensión, share intent desde cualquier app Android al Quick Capture, procesar inbox con sugerencias AI agrupadas por confianza (Aceptar N para los items ≥0.85), buscar globalmente con Ctrl+K, escribir notas con wikilinks + backlinks + auto-tags + resumen AI + sugerencias contextuales accept/dismiss en el editor, marcar favoritos y mandar a papelera con auto-purga configurable, explorar el grafo de conocimiento, ver notas similares por embeddings, agendar revisiones con FSRS, organizar tareas/proyectos/objetivos/hábitos, y todo offline gracias a TinyBase + PWA + retry queue end-to-end (creates + updates + saveContent) con <PendingSyncIndicator /> global cuando hay writes pendientes.
Cloud Functions: 11 desplegadas en us-central1 (9 v2 Node.js 22 — triggers con retry: false, callables con maxInstances — + 2 v1 Auth triggers):
processInboxItem—onDocumentCreateden inbox, Claude Haiku con tool use + schema enforcement, escribe 6 campos flataiSuggested*autoTagNote—onDocumentWrittenen notes, Claude Haiku con prompt cachingephemeral, escribeaiTags+aiSummarygenerateEmbedding—onDocumentWrittenen notes, OpenAItext-embedding-3-small(1536 dims), guard porcontentHashSHA-256embedQuery—onCallv2 callable para búsqueda híbrida client-side (input ≤300 chars; guards allowlist + rate-limit per-uid, SPEC-51)onNoteDeleted— cleanup cascada (embeddings + links bidireccionales) conWriteBatchchunkedautoPurgeTrash—onSchedule('0 3 * * *', UTC)hard-delete diario trastrashAutoPurgeDayssaveApiKey/deleteApiKey—onCallcallables BYOK: validan/cifran/borran la API key del usuario (F48)checkMyAccess—onCallautenticado: gate de allowlist post-auth (lee el email del token, no enumera terceros — reemplazó al públicocheckAllowlisten SPEC-51)submitAccessRequest/listAccessRequests/processAccessRequest— solicitud de acceso + cola admin (SPEC-52); elapproveenforce el capacity contando laallowlist/en transacción (SPEC-53)listAllowlistMembers/revokeAccess— gestión de miembros de la beta desde/admin, admin-only (SPEC-53)
Requisitos:
- Node.js 22 o superior (Capacitor Android lo requiere; Tauri funciona con 20)
- Un proyecto Firebase propio con Auth (Google sign-in) y Firestore habilitados
- OAuth Clients configurados en Google Cloud Console: Web (Vite), Android (SHA-1 del keystore para Capacitor) y Desktop (para el flow custom de Tauri)
- Opcional para el wrapper desktop: Rust 1.70+ (
rustup) y MSVC Build Tools con workload "Desktop development with C++" en Windows - Windows developers: ver
Docs/SETUP-WINDOWS.mdpara patches one-time de entorno (TS LSP, symlinksui-ux-pro-max, Firebase MCP, Capacitor Android, Cargo)
Pasos:
# Clonar e instalar
git clone https://github.com/sebasgc0399/SecondMind.git
cd SecondMind
npm install
# Configurar variables de entorno
cp .env.example .env.local
# Editar .env.local con las credenciales de tu proyecto Firebase
# Desplegar las security rules de Firestore (primera vez)
npx firebase login
npx firebase use --add # seleccionar tu proyecto
npm run deploy:rules
# Correr en desarrollo
npm run devNota — beta cerrada (allowlist). Las Firestore rules exigen que el email del usuario exista en
allowlist/{email}(gate de F50). Si levantás tu propio Firebase, trasdeploy:rulesquedás afuera de tu propia instancia hasta sembrar tu email: creá el docallowlist/<tu-email-en-minúsculas>en Firestore (Console o script) o todo read/write dapermission-denied(auto-lockout).
npm run dev # Servidor de desarrollo (Vite)
npm run build # Build de producción (tsc + vite build)
npm run lint # ESLint
npm test # Vitest (unit tests — repos, persister, etc.)
npm run preview # Preview del build local
npm run deploy # Build + deploy a Firebase Hosting
npm run deploy:rules # Deploy de Firestore security rules
npm run deploy:functions # Deploy de Cloud Functions
npm run logs:functions # Logs de Cloud Functions
npm run tauri:dev # Abre la app desktop nativa en modo dev (requiere Rust)
npm run tauri:build # Genera MSI + NSIS en src-tauri/target/release/bundle/
npm run cap:sync # Build web + sync al proyecto android/
npm run cap:run # cap run android (requiere Android Studio/adb en PATH)
npm run cap:build # Build web + sync + gradlew assembleDebug → APK debug- Web / PWA: https://app.getsecondmind.co — instalable desde Chrome/Edge
- Chrome Extension: código en
extension/(build separado vía CRXJS) - Desktop Windows: instaladores en
src-tauri/target/release/bundle/{msi,nsis}/víanpm run tauri:build. Auto-update tag-based (F8) - Android: APK debug en
android/app/build/outputs/apk/debug/víanpm run cap:build. El release firmado se distribuye por Firebase App Distribution (grupoowner) con el mismo flujo tag-based (F9). Es el canal del APK — distinto del gate de acceso por allowlist (auth, F50)
Documentación técnica y de diseño:
Docs/00-fundamentos-segundo-cerebro.md— principios teóricos (CODE de Tiago Forte, Zettelkasten, 10 principios de diseño)Docs/01-arquitectura-hibrida-progresiva.md— stack completo, modelo de datos Firestore, flujos clave, fases, decisionesDocs/02-flujos-ux-y-pantallas.md— 14 pantallas con wireframes, 5 flujos de usuario, shortcuts, responsiveDocs/03-convenciones-y-patrones.md— naming, componentes React, TinyBase, TypeScript, Tailwind, errores, GitDocs/04-clean-architecture-frontend.md— Clean Architecture en 4 capas, factory repos F10, excepciones documentadasDocs/SETUP-WINDOWS.md— patches one-time de entorno Windows.claude/design-principles.md— criterio de diseño (tokens factuales desrc/index.css+ jerarquía, densidad, color, motion, anti-patrones) que consume el agentedesign-review
Las SPECs viven en Spec/:
Spec/ESTADO-ACTUAL.md— snapshot consolidado (fuente primaria de estado y arquitectura vigente) + índice de gotchas por dominioSpec/SPEC-fase-*.md— canon histórico por fase (0 a 5.2)Spec/features/SPEC-feature-*.md— canon histórico por feature (1 a 50)Spec/gotchas/<dominio>.md— canon de gotchas técnicos por dominio (15 archivos: editor, ui-componentes, tinybase-firestore, capacitor-mobile, tauri-desktop, cloud-functions-*, etc.)Spec/drafts/DRAFT-*.md— discovery pre-SPEC temporal (se eliminan al convertirse en SPEC formal)