Commit Graph

625 Commits

Author SHA1 Message Date
Jeff Emmett 9266a6155f feat(rnotes): debounce suggestion panel + drag-drop notes between notebooks
Batch consecutive keystrokes into single suggestions via session tracker,
debounce panel sync (400ms) to prevent letter-by-letter flicker, and add
HTML5 drag-and-drop to move notes between notebooks in the sidebar.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 12:43:40 -07:00
Jeff Emmett abc855f34e fix(rnotes): position sidebar collapse button at right edge, vertically centered
Move < button from inside search header to absolute-positioned on the
sidebar border at vertical midpoint. Matches the > reopen tab style.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 16:43:21 -07:00
Jeff Emmett e8d88cd10e fix(rnotes): resolve anonymous identity in comments, suggestions, and cursors
Session was stored as { claims: { username, sub } } but getSessionInfo()
read sess.username (top-level) instead of sess.claims.username — always
falling back to "Anonymous". Fixed in all 3 locations: folk-notes-app,
comment-panel, collab-presence.

Also fixed awareness race: Yjs provider broadcast initial awareness before
user field was set, creating a ghost "anonymous" peer. Now identity is set
on awareness before provider connects, and the duplicate set is removed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 16:34:08 -07:00
Jeff Emmett 99fa59c8df feat(rnotes): suggestions in sidebar panel with per-item accept/reject
- Suggestions now appear as cards in the right-hand comment sidebar
  with author, type (Added/Deleted), text preview, and Accept/Reject
- Clicking a suggestion card scrolls the editor to the marked text
- Removed "Accept All" and "Reject All" from the review bar — too blunt
- Review bar now directs users to the sidebar for granular review
- Sidebar auto-opens when suggestions exist
- Inline popover accept/reject still works for quick actions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 16:28:42 -07:00
Jeff Emmett 0ec5edd1ee feat(rnotes): collapsible document sidebar with < / > toggle
Add collapse button (<) in sidebar header top-right and reopen tab (>)
on left edge when collapsed. CSS grid transition for smooth animation.
Hidden on mobile where slide navigation handles sidebar state.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 16:28:01 -07:00
Jeff Emmett 9084de7adb feat(rsocials): wire social shapes into all cross-rApp systems
- Add GET /api/threads, /api/threads/:id, /api/campaigns, /api/campaigns/:id
  REST endpoints so other rApps can fetch rsocials data
- Register folk-social-thread/campaign/newsletter in MI triage panel,
  tool schema, system prompt, and KNOWN_TRIAGE_SHAPES
- Add rsocials MODULE_PORTS (threads-out, campaigns-out, post-published,
  campaign-data) and WIDGET_API to folk-rapp for embed/widget mode
- Add rsocials to folk-feed FEED_ENDPOINTS (threads, campaigns, newsletter)
  and normalize response arrays (threads, campaigns, drafts)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 16:25:26 -07:00
Jeff Emmett 63a3f9b6c3 fix(rcart): add missing getTransakEnv import
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 16:08:23 -07:00
Jeff Emmett 9edb6cccde fix(rcart): Transak staging payment — popup instead of blocked iframe
Transak staging sets X-Frame-Options: sameorigin, blocking iframe embedding.
Server now uses x-forwarded-host header for correct referrerDomain behind
Traefik, and returns env (STAGING/PRODUCTION) in transak-session response.
Client opens a popup window for staging instead of iframe.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 16:01:57 -07:00
Jeff Emmett bbbe14246c feat(rinbox): space agent mailbox system — per-space MI email identity
Each space gets {space}-agent@rspace.online as a real Mailcow mailbox
(auto-provisioned with generated password). Inbound emails are IMAP-polled
and processed by MI (Gemini Flash) for auto-reply. All outbound emails
(approvals, notifications) set reply-to to the agent address so replies
route back through MI.

- mailcow.ts: createMailbox/deleteMailbox/mailboxExists API
- schema.sql + db.ts: agent_mailboxes table for per-space IMAP creds
- space-alias-service.ts: provisionAgentMailbox/deprovisionAgentMailbox
- server.ts: internal routes for agent mailbox CRUD + member-emails
- rinbox/mod.ts: initAgentMailbox, per-space IMAP sync, processAgentMI
- rinbox/agent-notify.ts: sendSpaceNotification (BCC members)
- rcal/rtasks/rvote: notification hooks on create

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 08:59:52 -07:00
Jeff Emmett e31c905d7c feat(rnotes): add tiptap-markdown for inline markdown shortcuts + paste
Type **bold**, _italic_, ~~strike~~, `code`, etc. and they auto-convert
to rich text. Pasting markdown also converts to formatted content.
Added to all 4 editor instances (Yjs, legacy, bookmark, image, audio).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 20:56:22 -07:00
Jeff Emmett 219a5f434b fix(rnotes): mobile collab UX — bottom-sheet comments, toolbar reorder
- Comment sidebar → full-width bottom sheet at ≤768px (was ≤480px)
- Toolbar: collab tools (comment, suggest) reordered first on mobile
  via CSS order so they're visible without scrolling
- Suggestion review bar wraps at mobile widths
- Toolbar scroll + larger touch targets promoted to ≤768px breakpoint

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 20:26:30 -07:00
Jeff Emmett 8f9d507440 fix(rinbox): clean up sub-tab header — mailboxes + approvals only, info icon, space mailbox primary
Remove Personal, Agents, Tour from nav header. Move Guide/About behind
info icon (ⓘ). Space mailbox ({space}@rspace.online) shown first with
highlighted card spanning full width. Add demo threads for space mailbox.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 20:21:50 -07:00
Jeff Emmett 25abb0266b feat(rsocials): newsletter drafts tab + remove Listmonk setup wall
Drafts tab shown by default with Automerge-backed CRUD. Listmonk tabs
conditionally appear when configured. Info banner for unconfigured state.
Draft editor with HTML preview, status dropdown, subscriber management.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 20:15:46 -07:00
Jeff Emmett db25d65c43 chore(rnotes): bump JS cache version to v=9
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 20:14:22 -07:00
Jeff Emmett 77ac0c1e32 feat(rsocials): newsletter drafts, subscribers + MI route updates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 20:11:31 -07:00
Jeff Emmett 2eac542e19 feat(rnotes): mobile stack navigation — Notion-style two-screen slide
Replace overlay sidebar with horizontal flex stack: full-width doc list
slides to full-width editor with back bar on note tap. Resize-aware.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 20:11:26 -07:00
Jeff Emmett 3add66b5ef chore(rsocials): add NewsletterDraft and NewsletterSubscriber types
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 20:04:15 -07:00
Jeff Emmett f966f02909 feat(spaces,rsocials): invite-based member adds + clickable campaign content
Space invites: Convert both username-add and email-invite (existing user)
paths from direct-add to invite flow — creates space_invite via EncryptID,
sends invite email with Accept button, dispatches space_invite notification
with Accept/Decline buttons in the notification bell. No one gets forcefully
added to a space anymore.

rSocials content linking: All generated campaign content now links through
to actual editable content. Draft post cards in thread gallery are clickable
(thread editor or campaign view). Campaign manager post cards expand on click
and thread badges link to thread editor. Wizard success screen shows
individual thread links. CampaignPost schema gains threadId field, stored on
commit so posts maintain their thread association.

Also includes canvas social media tools, social shape components
(folk-social-thread, folk-social-campaign, folk-social-newsletter),
and MI context-aware suggestion registry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 20:03:52 -07:00
Jeff Emmett 358965cb61 fix(rmaps): join form overlay + authenticated user auto-join
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 18:04:24 -07:00
Jeff Emmett c4972079dd fix(cad): CSS containment + Scribus image gen for all CAD shapes
- KiCad, FreeCAD, Blender, Scribus: add .wrapper flex container with
  height:100% + min-height:0 so content stays within element bounds
- KiCad assembler: regex fallback for non-JSON tool results (SVG, Gerber, PDF)
- Scribus image gen: actually write downloaded fal.ai images to disk
  (was creating imagePath but never saving bytes)
- Mount rspace-files volume in scribus-novnc so generated images are
  accessible from both containers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:53:42 -07:00
Jeff Emmett 8ea537525a fix(rwallet): align timeline inflows/outflows with balance changes
- Use curveStepAfter for the balance river so step transitions happen
  exactly at transaction dates (curveBasis didn't pass through data points,
  causing waterfall shapes to disconnect from the river edges)
- Update hardcoded USD estimates to current CoinGecko prices (2026-03-25)
- Add SAFE, COW, ENS, LDO, BAL to the price estimate table
- Fix BigInt→Number precision for large token balances (>2^53 wei) in
  both price-feed enrichment and transfer value parsing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:36:10 -07:00
Jeff Emmett f3094f5f88 fix(rwallet): chain filter now updates all displayed data + chain proportion bar
- Stats, balance table, and DeFi positions all filter by selected chain
- Added proportional color bar showing each chain's share of total value
- Chain buttons show USD value + percentage on hover
- Bumped JS cache version to v=21

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:32:02 -07:00
Jeff Emmett ba56697e23 fix(rcal): show calendar event locations on map in all spaces, not just demo
REST API events use location_lat/location_lng while the map panel
filters on latitude/longitude. Demo events set both, but non-demo
events only had location_lat/location_lng — so the map was always
empty outside demo.

Normalize both REST and Automerge event data to include latitude/
longitude aliases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:10:44 -07:00
Jeff Emmett 44a69e665e perf(rmaps): preload MapLibre GL, switch CDN from unpkg to jsDelivr
Add <link rel="preload"> hints for MapLibre JS+CSS in the module HTML
so the browser starts fetching them in parallel with the main bundle,
instead of waiting until joinRoom() calls loadMapLibre().

Switch from unpkg (slow, no HTTP/2) to jsDelivr (faster edge caching).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:03:21 -07:00
Jeff Emmett 355d33768a fix(mobile): responsive parity — touch targets, iOS zoom, viewport clamping
rNotes: always-visible add button on touch, 36px toolbar buttons with horizontal
scroll, URL popover as bottom sheet on mobile, improved comment sidebar bottom
panel with drag handle, larger footer buttons, slash menu viewport clamping and
mobile-friendly item sizes, reduced code-textarea/image-preview heights.

rTasks/rFiles: font-size 16px on inputs to prevent iOS Safari auto-zoom.

Shell: .hover-reveal touch utility, 36px min-height on rapp-nav buttons.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:59:04 -07:00
Jeff Emmett 4a75c64a18 feat(rdesign): rich landing page, Scribus canvas tool, icon update
- Replace minimal rDesign landing with full rl-* pattern (hero, features,
  how-it-works, capabilities, open source, data protection, CTA)
- Add Scribus button to Create toolbar group in canvas (folk-design-agent)
- Export FolkDesignAgent from lib/index.ts, register in canvas.html
- Update module icon from 🎯 to 🎨 (matches favicon + MODULE_META)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:51:31 -07:00
Jeff Emmett 6d20a275ff fix(rwallet): show all chains with activity, fix chain filter stats
- Backend: detect chains where Safe has transaction history even if
  current balance is zero (queries all-transactions?limit=1)
- Frontend: stats (Total Value, Tokens) now update when clicking
  chain filter buttons instead of always showing all-chain totals

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:50:20 -07:00
Jeff Emmett d7c1501d4f feat(rnotes): Google Docs-style suggestion mode + comment panel fixes
Rewrite suggestion plugin to use ProseMirror props (handleTextInput,
handleKeyDown, handlePaste) instead of broken filterTransaction approach.
Typed text gets suggestionInsert mark (green underline), deleted text gets
suggestionDelete mark (red strikethrough). Add per-suggestion accept/reject
popover and review bar with Accept All / Reject All.

Fix comment panel text overflow with box-sizing: border-box, add
collapse/minimize toggle button.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:48:16 -07:00
Jeff Emmett 0db5addc17 fix(rdesign): switch to StreamableHTTP transport, fix KiCad Python path
SSE transport crashes on concurrent connections (supergateway
single-session limit). StreamableHTTP supports multiple sessions.
Also set KICAD_PYTHON=/usr/bin/python3 for existsSync validation
and install missing requests package.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:48:11 -07:00
Jeff Emmett e0e9802bd7 feat(rwallet): use CoinGecko Demo API key for batch token pricing
Reads COINGECKO_API_KEY from env (injected via Infisical) and appends
x_cg_demo_api_key param. Enables batch lookups + spam filtering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:45:45 -07:00
Jeff Emmett 76a846cc36 fix(rwallet): handle CoinGecko free tier 1-address limit gracefully
Single-token wallets get CoinGecko verification + spam filtering.
Multi-token wallets attempt batch (works with Pro/Demo keys), degrade
gracefully on free tier — Safe API trusted+exclude_spam handles most spam.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:31:44 -07:00
Jeff Emmett 110b733f94 fix(rnotes): Google Docs-like comment sidebar, fix suggestions + duplicate extensions
- Fix duplicate tiptap extension warnings by disabling link/underline in
  StarterKit v3 (which now includes them by default)
- Move comment panel from metaZone (destroyed by renderMeta) to dedicated
  comment sidebar next to the editor, Google Docs style
- Add click-on-highlight to open comment thread in sidebar
- New comment creation shows inline textarea with auto-focus
- Fix suggestion plugin: pass view getter instead of broken state.view access
- Improve comment panel styling: avatars, Google Docs yellow active border,
  cleaner thread layout, Ctrl+Enter to submit, Escape to cancel
- Bump folk-notes-app cache version to v=7

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:29:21 -07:00
Jeff Emmett 8ba14a0e15 fix(rwallet): skip spam filter when CoinGecko data unavailable
Revert per-address batching (rate limit cascade). Track cgAvailable flag
in cache — only apply spam filter when CoinGecko successfully returned data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:25:48 -07:00
Jeff Emmett 95246743c3 fix(rwallet): batch CoinGecko requests to 1 address each (free tier limit)
CoinGecko free tier now limits to 1 contract address per request.
Process in batches of 3 concurrent single-address requests with 1.5s delay.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:17:03 -07:00
Jeff Emmett 5f853322b0 fix(rwallet): filter spam tokens via CoinGecko verification
ERC-20 tokens not recognized by CoinGecko and valued < $1 by Safe API
are now stripped from balance responses, removing fake ETH and airdrop spam.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:08:52 -07:00
Jeff Emmett 4d7d2c0108 fix(rsocials): campaign wizard auth — read correct session storage key
Was reading `encryptid-token` (doesn't exist), now reads `encryptid_session`
and extracts `.accessToken` matching the pattern used by all other modules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:01:10 -07:00
Jeff Emmett 4a43ecdee0 fix(rcal): replace event dots with thin colored bars on mobile
Dots were overlapping in small day cells. Now renders full-width 2px
color-coded stripes (solid for confirmed, dashed for tentative). Multi-day
spans also thinner (10px) with hidden text on mobile.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:21:15 -07:00
Jeff Emmett 28f11242f7 fix(rwallet): consolidate dual tab bars into single shell subnav
Remove internal view-tabs from folk-wallet-viewer — navigation now handled
entirely by shell subnav outputPaths: Budget (default), Token Balances, Flows.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 14:40:14 -07:00
Jeff Emmett a10f8e9507 fix(rwallet): capture ETHEREUM_TRANSACTION inflows, filter airdrop spam tokens
Transfers: handle ETHEREUM_TRANSACTION txType as inflows (was only scanning
tx.transfers), exclude self-transfers from embedded transfers loop.
Balances: hide unpriced ERC-20s (airdrop spam) while keeping native tokens,
CRDT tokens, and CoinGecko-priced tokens. Filter zero balances on single-chain
Safe endpoint. Bump JS cache to v=20.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 14:37:35 -07:00
Jeff Emmett c7c6b6a13b chore(rwallet): bump JS cache version to v=19
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 14:04:00 -07:00
Jeff Emmett 2bfd674d0e refactor(rwallet): consolidate tabs — remove Yield, merge viz into Budget + Flows
Simplify rWallet from 5 internal tabs to 3: Token Balances, Budget Visualization
(default), and Flows (Sankey + timeline scrubber with play/pause). Remove Yield
shell-level outputPath and route. Budget view auto-loads transfer data on entry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 14:03:35 -07:00
Jeff Emmett 8071b620e1 fix(auth): throttle session validation, typed auth-change events, misc fixes
- rstack-identity.ts: throttle server session validation to every 5min,
  add reason detail to all auth-change events (signin/signout/revoked/
  refresh/persona-switch), remove redundant location.reload on signout
- shell.ts: skip UI side-effects on token refresh, only redirect home
  on genuine signout/revocation
- server.ts: add PUT to CORS allowMethods
- folk-inbox-client.ts: pass auth token on mailbox API fetch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 12:21:26 -07:00
Jeff Emmett 06a58f1bba fix(ui): theme-adaptive rSocials buttons + device link textbox
- campaign-wizard.css: fix undefined --rs-surface-hover → --rs-bg-hover
- campaign-workflow.css: replace hardcoded blue colors with theme vars
  (--rs-primary-hover, --rs-bg-active, --rs-border, --rs-primary)
- rstack-identity.ts: device link URL input --rs-bg-inset → --rs-input-bg
  (--rs-bg-inset was never defined in theme.css, dark fallback always won)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 11:39:14 -07:00
Jeff Emmett dd46905e12 feat(mi): agentic upgrade — multi-turn loop, LiteLLM, media gen, live data
Transform MI from single-shot chat into an agentic system:

- LiteLLM provider with Claude Sonnet/Haiku models via proxy
- Agentic loop (max 5 turns): stream → parse actions → execute server-side → feed results back
- Server-side media generation (fal.ai + Gemini) as first-class MI actions
- Module data queries (rnotes, rtasks, rcal) read directly from Automerge
- System prompt enriched with recent notes, open tasks, and calendar events
- Client handles new NDJSON types (turn, action-start, action-result)
- Extracted shared media helpers, refactored image/video endpoints

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 19:26:56 -07:00
Jeff Emmett 5915daf8a0 feat(rtrips): interactive AI workspace with maps, flights & route planning
Transform the AI planner right panel into an interactive workspace:
- Persistent MapLibre GL map (40% height) with pin accumulation and route lines
- Flight search results with prices, airlines, and Kiwi.com booking links
- Route cards with distance/duration from OSRM
- Nearby POI discovery via Overpass API (restaurants, hotels, attractions)
- Server-side trip tool execution via new /api/trips/ai-prompt endpoint
- Conversational system prompt that progressively builds understanding
- New lib/trip-ai-tools.ts with 4 executable tools (search_flights, get_route,
  geocode_place, find_nearby)
- Enhanced demo mode with realistic mock flights, routes, and geocode data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 18:56:49 -07:00
Jeff Emmett 193588443e fix(routing): eliminate /{space} from paths on subdomain routing
On subdomain routing (e.g. demo.rspace.online), the space slug belongs
only in the subdomain — never in the URL path. This fixes all server
and client code that was generating /{space}/module paths on subdomains.

Server fixes:
- index.ts: notification actionUrls, template/disabled-module redirects,
  subdomain passthrough (now redirects HTML, rewrites API), WS notifications
- output-list.ts: subdomain-aware path prefix for hrefs and fetch URLs
- shell.ts: dashboard pushState URL

Client fixes (basePath getter pattern):
- folk-book-shelf.ts, folk-splat-viewer.ts: _basePath getter
- folk-campaign-wizard.ts: basePath subdomain check
- folk-trips-planner.ts: use __rspaceNavUrl for canvas export
- rschedule/landing.ts: onclick handlers use __rspaceNavUrl
- rsplat/mod.ts: legacy view redirect subdomain check

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 18:45:16 -07:00
Jeff Emmett 75ad3f8194 feat(rinbox): per-space email forwarding via Mailcow aliases
Provision {space}@rspace.online forwarding aliases that route to
opted-in members' personal emails. Admins/mods opted in by default;
regular members can opt in via PUT /api/spaces/:slug/email-forwarding/me.

New: space-alias-service.ts, schema tables, 8 DB functions, 6 API routes.
Hooks: rinbox onSpaceCreate/Delete, spaces.ts member lifecycle, startup migration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 18:40:29 -07:00
Jeff Emmett 348f86c179 fix(rtrips): fit all views on one screen without page scrolling
Pin nav bar and tabs at top, make tab content scroll within the remaining
viewport height. Uses flex layout with overflow-y: auto on the content
area. Applies to list, detail, and AI planner views.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 18:28:50 -07:00
Jeff Emmett 1eb4e1cb66 feat(rmaps): UX parity with rmaps-online — route overlay, ping cooldown, session persistence
Phase 1: Route double-layer outline, ScaleControl, route instruction summary,
Enter key in meeting search, select-all toggle in import preview, fitToParticipants FAB.
Phase 2: Ping All sidebar button, push vibrate+requireInteraction, 30s ping cooldown,
bundled QR code (qrcode package with external API fallback), ping toast with vibration.
Phase 3: Location persistence across sessions (<30min restore), auto-start sharing preference.
Also fix pre-existing TS error in community-sync.ts (bulkForget changes array typing).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 18:25:46 -07:00
Jeff Emmett 496dff3c7f feat(rtrips): add in-module AI planner with split-view chat + canvas export
"Plan with AI" now opens a split-view within rTrips instead of redirecting
to the canvas. Left panel: chat with model selector. Right panel: generated
trip cards (destinations, itineraries, budgets, packing lists) with
accept/discard flow. Demo mode provides realistic mock responses for Japan,
Europe, and beach queries. Accepted items export to canvas via sessionStorage
+ #trip-import hash handler.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 18:21:40 -07:00
Jeff Emmett 3f496d9fc6 feat(rnotes,canvas): comments in demo mode, emoji reactions, reminders + inline picker modal
- rNotes comments now work in demo mode via in-memory thread storage
- Added emoji reactions (7-emoji palette) and date reminders on comment threads
- Reminders integrate with rSchedule API for persistent notifications
- Canvas toolbar: split Note into "Blank Note" (always available) and "From rNotes" (picker)
- Replaced browser prompt()-based pickFromList with showPickerModal (dark-themed, searchable, keyboard nav)
- Updated pickTrip, destination, and booking handlers to use the new modal

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 17:53:06 -07:00
Jeff Emmett 41051715b9 feat(rtasks): ClickUp two-way sync integration
Add bidirectional sync between rTasks and ClickUp:
- API client with 100 req/min rate limiter
- OAuth2 + personal API token connection flows
- Import wizard (workspace → space → list picker)
- Outbound push queue (5s intervals, 10-item batches)
- Inbound webhook with HMAC-SHA256 validation
- Field-level conflict detection (rTasks wins)
- Source badges (purple CU) with sync status dots on task cards
- Sync status indicator in board header for connected boards

Also fix 6 pre-existing TS errors across crowdsurf, rcal, rnotes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 17:37:01 -07:00
Jeff Emmett 3a222e2ddc fix(rnotes): register comment and suggestion marks in legacy editor
The CommentMark, SuggestionInsertMark, and SuggestionDeleteMark extensions
were only registered in the collab (Yjs) editor, causing "no mark type
named 'comment'" crash when adding comments in demo/legacy mode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 17:24:56 -07:00
Jeff Emmett e8379541cc fix(tabs): strip duplicate shell elements from canvas tab injection
The canvas.html body contained <rstack-tab-bar>, <rstack-space-settings>,
and <rstack-history-panel> elements that weren't being stripped by
extractCanvasContent (the tab-row regex failed due to extra children).
When injected via TabCache, these duplicate elements interfered with the
shell's tab management, causing tabs to appear wiped.

Fixes:
- Server: robust div-counting strip for rstack-tab-row + explicit strips
  for space-settings and history-panel
- Client: DOM-based safety strip in TabCache.extractContent()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 17:21:52 -07:00
Jeff Emmett df8631360e feat(collab): unified presence system across all 27 rApps
Harmonize the two disconnected presence systems into one:
- New shared/collab-presence.ts utility (broadcastPresence, startPresenceHeartbeat)
- Collab overlay now listens to custom presence messages, shows module context in people panel
- Fixed Shadow DOM focus tracking using composedPath() for focus rings through shadow boundaries
- Replaced rNotes custom presence with shared utility (kept sidebar dots)
- Added presence heartbeat to all 27 rApp components with dynamic context strings
- Bumped cache versions in all modified mod.ts files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 16:56:06 -07:00
Jeff Emmett 32524fdf00 feat(rnotes): add collab status bar, sidebar indicator, mobile UX polish
Adds a visible collab status bar between toolbar and editor showing
connection state (live editing with peer count, sync enabled, or offline).
Sidebar footer now shows a live collab indicator dot. Mobile sidebar
auto-closes when selecting a note. Mobile FAB button now shows "Docs"
label. Bumps cache version to v=5.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 16:11:49 -07:00
Jeff Emmett c35f39380e feat(rflows): replace drain valve bar with rotary knob, move allocations to panel
- Add renderDrainKnob() with rotating handle matching source valve style
- Remove rectangular ◁ $/mo ▷ drag bar and split control overlays from canvas
- Add editable range sliders in inline config Allocations tab
- Rewire drag handler for live knob rotation during drain rate adjustment
- Clean up dead split-divider CSS and event listeners

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:38:59 -07:00
Jeff Emmett 8635b54800 fix(rflows): eliminate SVG NaN errors via comprehensive data sanitization
Added safeNum() + migrateNodeData() to sanitize all numeric fields (including
positions and allocation percentages) at every data loading boundary. The nullish
coalescing operator (??) doesn't catch NaN, so corrupted Automerge/localStorage
data cascaded NaN through pipe positions, port coordinates, and edge paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:14:26 -07:00
Jeff Emmett 2d28252f1a feat(rwallet): replace S-curve flows with L-curve right-angle flows in timeline
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:03:23 -07:00
Jeff Emmett ef65ec49ff chore(rnotes): bump JS/CSS cache version to v=4
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 14:45:26 -07:00
Jeff Emmett 0e9ca3ec30 feat(rnotes): convert to Docmost-style persistent sidebar layout
Replace 3-step drill-down navigation (notebook grid → note list → editor)
with a persistent sidebar showing collapsible notebook tree alongside the
editor. Sidebar supports search, per-notebook note lists, hover add buttons,
and active note highlighting. Mobile collapses to slide-in overlay <768px.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 14:43:21 -07:00
Jeff Emmett 5f25ae02e1 fix(rsocials): use checkboxes for campaign wizard platform selectors
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 14:22:49 -07:00
Jeff Emmett 4e6d0b885b fix(rdesign): chat messages top-to-bottom, input at bottom, no page scroll
Move chat input below messages container so conversation flows naturally
top-to-bottom. Add overflow:hidden on html/body to prevent page scrolling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 14:16:07 -07:00
Jeff Emmett bf0661fab2 feat(cad): LLM-orchestrated MCP tool-calling for KiCad and FreeCAD
Add Gemini Flash agentic loop that converts natural language prompts
into real MCP tool call sequences for PCB design (KiCad) and parametric
CAD (FreeCAD). Dynamic schema conversion from MCP tools to Gemini
function declarations, 8-turn/60s loop with real execution and result
feedback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 14:07:19 -07:00
Jeff Emmett d8736ba341 fix(rcal): add post-load migration for tags field on existing events
Automerge docs created before the tags schema don't have the field.
The migration runs 5s after startup (after loadAllDocs completes),
patches missing tags onto events, and assigns known demo event tags.
Also removes debug endpoint and tracing logs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 14:01:01 -07:00
Jeff Emmett 9ae88e14b7 debug: add tags tracing logs 2026-03-24 13:56:22 -07:00
Jeff Emmett d7e195c0b3 debug: temporary tags debug endpoint 2026-03-24 13:48:21 -07:00
Jeff Emmett a3b6d7f425 fix(rcal): convert Automerge proxy arrays to plain arrays for tags serialization
Automerge proxy lists don't serialize to JSON properly via ?? null.
Use Array.from() to materialize them before returning in API responses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 13:41:32 -07:00
Jeff Emmett 2dd5e764cd feat(rcal): MI calendar awareness, tags, saved views, MCP server
Phase 1: MI now knows the current date/time and upcoming events (14-day
lookahead, 5 events max) via direct Automerge read — no HTTP overhead.

Phase 2: Tags (string[] | null) on CalendarEvent for first-class filtering.
Saved views (named filter presets) with full CRUD API. Tag filter on
GET /api/events via comma-separated AND logic. Demo events seeded with tags.

Phase 3: Calendar MCP server (5 tools: cal_list_events, cal_get_event,
cal_list_sources, cal_list_views, cal_create_event) registered in .mcp.json.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 13:28:02 -07:00
Jeff Emmett 90d511077c fix: campaign wizard using wrong localStorage key for auth token
Was reading `auth_token`, should be `encryptid-token`. Also removes
the premature client-side auth guard that blocked signed-in users.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 13:04:57 -07:00
Jeff Emmett 7f327eb07a fix: whitelist rvote GET API as public + guard campaign wizard auth client-side
1. Add GET /rvote/api/* to public endpoint whitelist so proposal
   listings work on private/permissioned spaces without auth.
2. Campaign wizard now checks for auth token before POSTing,
   showing "Please sign in" instead of a cryptic 401.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 12:58:21 -07:00
Jeff Emmett 50c003e8e3 fix(rdesign): catch SSE stream close errors (Cloudflare QUIC reset)
Add .catch() to the ReadableStream reader loop so Cloudflare QUIC
protocol resets on stream close don't surface as uncaught errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 12:13:44 -07:00
Jeff Emmett 4ed940d75c fix(rdesign): run Scribus runner as standalone supervisor process
The Scribus --python-script flag requires GUI initialization which
blocks in headless environments. Instead, run the runner as a separate
supervisor-managed Python process (always-on socket server). The bridge
server now simply verifies the socket exists rather than launching
Scribus.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 12:05:51 -07:00
Jeff Emmett e5466491c7 fix(rdesign): auto-restart Scribus when runner socket is missing
The bridge's /start endpoint was returning "already running" even when
the runner script had crashed (socket gone). Now kills zombie Scribus
and restarts. Agent route also verifies runner connectivity after start.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 11:41:58 -07:00
Jeff Emmett fdf4db2050 fix(rdesign): move prompt input above replies in chat panel
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 11:37:08 -07:00
Jeff Emmett 3cb2298569 feat(rdesign): split-pane chat + visual editor UI, SSE keepalive
Rewrite rDesign UI from cramped textarea+step-log to proper split-screen:
left = chat conversation with bubbles, right = interactive SVG editor
with click-to-select, drag-to-move, and corner-handle resize.

SSE keepalive pings every 15s prevent Cloudflare QUIC stream drops.
Tool calls now show human-readable descriptions in collapsible details.
Gemini reasoning text included in thinking events.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 11:28:28 -07:00
Jeff Emmett 68edfaae66 feat(rflows): rewrite flow engine — conservation-enforcing simulation + Sankey renderer
Simplify FunnelNodeData from 4-tier thresholds to 2 fields (overflowThreshold + capacity),
replace 3-tier spending multiplier with flat drainRate. Rewrite folk-flow-river.ts as clean
Sankey-style SVG renderer (~580 lines, was ~1043). Add migrateFunnelNodeData() for backward
compat with saved flows. Net -616 lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:58:53 -07:00
Jeff Emmett c2b5820f8a fix(rdesign): use relative path for API fetch to avoid mixed content
The bare-domain router redirects /demo/... paths to demo.rspace.online
with http:// protocol, causing mixed content errors. Use the current
page path as the base URL instead of constructing an absolute path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:41:13 -07:00
Jeff Emmett aec42ef976 fix(rdesign): add publicWrite flag to unblock POST requests
The write-method middleware was returning 403 for POST /api/design-agent
because the module lacked publicWrite: true.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:36:14 -07:00
Jeff Emmett ddb5b0b2e4 fix(rdesign): fix 401 auth error and theme-aware CSS for light mode
Pass encryptid auth token in design-agent API requests. Replace
non-existent --rs-bg-elevated with real theme variables and remove
hardcoded dark fallbacks so the UI works in both light and dark mode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:22:16 -07:00
Jeff Emmett 77b7aba893 feat(rdesign): Scribus noVNC + AI design agent + CRDT sync
Replace Affine wrapper with full Scribus DTP stack:
- Docker container: Scribus 1.5 + Xvfb + x11vnc + noVNC + Python bridge
- Bridge API: Flask server (port 8765) proxying to Scribus Python API via Unix socket
- Design agent: Gemini tool-calling loop drives Scribus headlessly from text briefs
- CRDT sync: Automerge schema v2 with pages/frames, bidirectional SLA bridge
- Canvas tool: folk-design-agent shape + create_design_agent in canvas-tools registry
- Module UI: inline text prompt + step log + SVG layout preview (no iframe)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:06:04 -07:00
Jeff Emmett d74512ddcd chore(rflows): bump folk-flow-river.js cache version to v=2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 19:33:56 -07:00
Jeff Emmett 8b43df5ce9 fix(rflows): Sankey-style constant-width L-shaped ribbons for waterfalls
Three fixes for S-curve appearance:
- Constant width throughout each waterfall (no taper between source/river)
- Stack inflow waterfalls side-by-side at funnel top proportionally
- Widen spending drain to 80% of vessel bottom width

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 19:23:46 -07:00
Jeff Emmett aa4a200f32 feat(history): add "Revert to this point" button in Time Machine panel
Forward Automerge change that overwrites content fields with snapshot data,
preserving meta and full history. Also fixes pre-existing TS errors in
folk-flow-river (undefined exitX) and test-full-loop (StepResult type).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 19:08:15 -07:00
Jeff Emmett 47a3fe32fb fix(rflows,rwallet): unstaged fixes from previous session
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 18:42:11 -07:00
Jeff Emmett 8aa2e9773a feat(rmaps): ZIP import, chat, route requests, indoor maps
- ZIP import: Google Takeout + generic FeatureCollection ZIP via JSZip
- Route requests: "Ask to navigate" sends WebSocket route_request, toast notification with Navigate/Dismiss in other tab
- Chat: Automerge-backed persistent messages with MapChatMessage schema (v2), sidebar tab toggle, unread badge
- Indoor maps: <map-indoor-view> with c3nav raster tile proxy, level selector, Easter egg on Level 0 triple-click
- Indoor/outdoor toggle in controls bar and mobile FAB
- Cache bust v2→v3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 18:42:02 -07:00
Jeff Emmett aa520d41a2 chore(rwallet): bump JS cache version to v=15
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 18:23:07 -07:00
Jeff Emmett 51be476694 feat(rwallet): timeline-first UX overhaul with proportional rivers
- Fix USD estimation: add NATIVE_APPROX_USD price table for ETH, MATIC,
  BNB, AVAX, xDAI, CELO, GNO; unknown tokens fall back to $0 instead of
  raw token amounts (fixes wildly wrong river widths)
- Fix scroll hijacking: only intercept Ctrl+wheel (pinch-to-zoom) on
  timeline, flow chart, and sankey; normal two-finger scroll passes through
- Collapse address bar to compact chip after wallet loads with Save/Change
- Promote watchlist as horizontal chip selector above dashboard; merge
  example wallets as dashed "suggested" chips when watchlist is empty
- Default to timeline view after wallet detection (auto-loads transfers)
- Move balance/transaction tables to Details modal (pill button, overlay
  with backdrop blur) — stats cards hidden in viz views since D3 shows them

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 18:16:06 -07:00
Jeff Emmett bfdb320b3e fix(rcal): prevent multi-day event spans from displacing day cells
Multi-day event span bars used grid-row/grid-column inside the same
CSS grid as auto-placed day cells. The grid auto-placement algorithm
skipped cells occupied by explicitly-placed spans, pushing day numbers
to wrong positions.

Fix: make .ev-span position:absolute with .grid position:relative.
Absolutely-positioned grid children still use grid-row/column for
their containing block but don't participate in layout flow. Also
account for expanded day-detail rows when calculating span grid rows.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 17:37:35 -07:00
Jeff Emmett 245d2ec3b4 feat(rwallet): HyperSwitch full-loop fiat↔CRDT payment integration
- /api/internal/mint-crdt: on-ramp webhook → cUSDC mint (idempotent)
- /api/internal/escrow-burn: off-ramp escrow with two-step confirm/reverse
- $MYCO bonding curve (server/bonding-curve.ts): quadratic price curve,
  buy/sell/quote/settlement-state endpoints in rwallet
- BFT token renamed to $MYCO (6 decimals) in seed data
- LedgerEntry schema extended with offRampId, status for escrow tracking
- burnTokens, burnTokensEscrow, confirmBurn, reverseBurn in token-service
- Wallet UI: Buy cUSDC, $MYCO Swap, Withdraw sections with live quotes
- scripts/test-full-loop.ts for end-to-end verification

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 17:34:48 -07:00
Jeff Emmett 6ab9790373 fix(rflows): match overflow pipe widths to edge width formula
Compute overflow/spending pipe widths as proportional shares of
outflowWidthPx (matching edge formula: outflowWidthPx * flow/total)
instead of independent globalMaxFlow scaling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 17:26:05 -07:00
Jeff Emmett 3def8f73fe fix(rflows): cache-bust folk-flows-app.js for CDN
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 17:11:24 -07:00
Jeff Emmett db1c0ec490 feat(rflows): proportional flow pipes on all node types
Scale source stream, funnel inflow/overflow/spending, and outcome
inflow/overflow pipes using the same 8-80px global Sankey scale as
edges, replacing fixed-width cosmetic pipes with flow-consistent ones.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 17:06:45 -07:00
Jeff Emmett 68adc7ad17 feat(rwallet): add yield sandbox simulator with compound interest engine
Client-side sandbox for "what-if" yield projections — enter any amount,
pick asset/chain, scrub a time slider, and compare all protocol APYs
instantly. Uses live DeFi Llama rates when available, mock fallbacks offline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 16:50:06 -07:00
Jeff Emmett 3cfec226a4 fix(rflows): proportional node sizing + remove organic visualization
Nodes now scale with dollar values (sources by flowRate, funnels by
maxCapacity, outcomes by fundingTarget). Removed unused organic/
mycorrhizal render mode including renderer, CSS, and all toggle logic.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 15:08:08 -07:00
Jeff Emmett cb92a7f6d8 feat(rtrips): AI trip planner — canvas tools + "Plan with AI" button
Register 5 trip-specific tools (destination, itinerary, booking, budget,
packing list) in canvas-tools.ts so Gemini can create trip shapes.
Add public toolsEnabled/systemPrompt properties to folk-prompt with
persistence. Add #trip-planner hash handler to canvas.html that auto-
creates a pre-configured AI prompt. Add "Plan with AI" gradient button
to rTrips list and detail views.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 14:32:28 -07:00
Jeff Emmett 0c04d6bee1 fix(rmeets): use Jitsi External API by default, clean up toolbar buttons
Switch default room view to External API (cleaner toolbar, no stray
close buttons). Slim toolbar to essentials, disable participant pane
overlay. Fall back to iframe embed with ?iframe=1.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 12:11:00 -07:00
Jeff Emmett 460c68ddbf fix(rcal): only show dots/labels for events starting on that day
Multi-day events on intermediate days are shown via span bars,
not duplicated as dots/labels in each day cell.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 10:48:30 -07:00
Jeff Emmett 7234a8db38 feat(rspace): add rich landing page for the canvas module
Replace the generic "🎨 rSpace — Real-time collaborative canvas" fallback
with a full landing page following the rl-* CSS system used by other rApps.

Sections: hero, principles (local-first/interoperable/AI-native/multiplayer),
canvas features, 16-shape library grid, AI capabilities, how it works steps,
ecosystem integrations, open source stack, data protection, and final CTA.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 20:41:00 -07:00
Jeff Emmett 2e3007b1df fix(flipbook): ensure 2-page spread display in StPageFlip
Add flex-shrink:0 to flipbook containers to prevent flex layout from
squishing them below pageW*2, which would trigger StPageFlip's
portrait (single-page) mode. Update rpubs page counter to show
spread page range (Pages X–Y of N) for middle pages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 18:35:25 -07:00