Skip to content

What shipped per release. Mirror of CHANGELOG.md (release-please canonical).

Auto-generated from CHANGELOG.md at the repo root. Edits to this file will be overwritten on the next docs build.

All notable changes to ARCIVE. Versions track the phases in docs/00_MASTER_PLAN.md §3.

The format follows Keep a Changelog. Versioning matches the master plan’s phase ladder (V0, V0.1, V0.2, …) — so 0.1.0 is the V0.1 release, 0.2.0 is V0.2, and so on.

Unreleased — V0.3 in progress

Added

  • Mobile Universe — Skia renderer + Obsidian-style layout (feature/mobile-universe, 2026-05-06). Migrated the mobile graph from react-native-svg to @shopify/react-native-skia (GPU-backed, Expo-Go bundled). Continuous d3-force with ambient drift; long-press-and-drag a node pins it via fx/fy so connected nodes follow via the link force; tap-to-focus dim- everything-else; forceRadial pushes orphan nodes onto an outer ring (Obsidian’s globe silhouette); pinned “You” anchor at canvas centre. Filter persists via AsyncStorage. Auto-fit-to-viewport on first paint, double-tap to re-fit.

Pending:

  • Voice talk-back client on mobile (port web Pipecat client to RN).
  • MCP wiring on the voice service for in-call retrieval.
  • Real end-to-end pipeline test on a deployed Supabase.
  • Group conversation mode (LiveKit transport, interject()).
  • DoA fusion with Pyannote re-ID.
  • App Store / Play Store submissions (deferred with the Apple Developer account decision until release prep).

0.2.0 — 2026-05-04 — V0.2 (mobile slice + cross-platform polish)

V0.2 closes out with the Expo mobile app, the audio transcode worker, and a cross-platform polish pass that makes the recording → transcript flow continuous and offline-tolerant on every device.

Added

  • Expo mobile app (apps/mobile/, SDK 54 + Expo Router 6) — magic- link sign-in (with the same dev-skip path the web has), Today feed grouped by date bucket, full-text search across transcript + summary, Memory detail with audio playback + drag-to-seek progress bar, share-to-space, delete, sign-out. Press-to-record dictation via expo-audio. Routes to the same hosted Supabase as the web app — no LAN trickery.
  • Audio transcode worker (Modal, backend/workers/audio-transcode/) — every uploaded recording is always re-encoded to m4a/AAC for cross-device playback (iOS AVPlayer can’t decode Opus, Android can’t decode some Apple-MIME containers). ingest-audio fires the worker per upload; a 10-minute cron sweeper catches anything missed. Single source of truth for “what plays everywhere”: recordings.playback_storage_path. Both web and mobile audio readers prefer it when set.
  • Offline upload queue (apps/mobile/lib/upload-queue.ts) backed by expo-sqlite. Recorder always enqueues first then triggers a flush — so the row appears in Today the moment recording stops, whether online or off. Flush retries on app foreground + every 30s while there are pending rows. Each recording is persisted to a unique path under documentDirectory/arcive/pending/ immediately after stop, so consecutive recordings can’t overwrite each other’s bytes.
  • Flow continuity for recordings. Pending row stays visible through the entire upload → transcribe → memory pipeline, transitioning “Uploading…” → “Transcribing…” → real memory row. When the matching memories INSERT arrives via Realtime, the pending row is dismissed in the same frame the real one appears. No more “row vanishes for 5 seconds, comes back” gap.
  • Per-recording resume position via AsyncStorage. Player resumes mid-clip after navigating away or relaunching. Saves on pause/stop and every 5s while playing.
  • Single global audio player (apps/mobile/lib/audio-context.tsx) — one useAudioPlayer instance shared across Today inline rows and the Memory detail screen. Fixes the iOS bug where two per-row players step on each other and one never reaches isLoaded: true. Cross-screen continuation works for the same memory; tapping into a different memory’s detail stops the previous audio.
  • Resend SMTP for magic-link delivery (sender noreply@send.arcive.io, verified via SPF + DKIM + MX). Replaces Supabase’s built-in 4-emails-per-hour shared sender.
  • Subtle animations on the mobile feed (built-in RN LayoutAnimation + Animated; no Reanimated/worklets dep): rows fade/slide on update, dot pulses on Uploading→Transcribing, record button breathes while capturing.
  • Offline browse + on-device search. Last unfiltered fetch is cached in memory; on network failure the feed falls back to filtering that cache locally with the same ILIKE behaviour. Subtle red banner indicates locally-cached results.
  • MCP wiring on /api/chat — when MCP_SERVER_URL is set, retrieval routes through the internal MCP server instead of running inline. Falls back to the existing inline path when unset or unreachable.
  • Consent gate on agent retrievalsearch_memories_semantic and match_memories accept a new respect_consent parameter. MCP server tool and /api/chat’s inline-fallback path always pass true; user-facing search keeps the default false. See ADR-0007.
  • Per-role system prompt lookup in voice service. Resolves the prompt from the roles table by role_id query param (RLS scopes to built-in + own roles), appends the shared VOICE_MODE_ADDENDUM, falls back to the Reviewer default. Voice channel can now run any built-in or user-authored role without code changes.

Changed

  • Hosted-Supabase only. Dropped Path A (local Supabase / Docker) from setup. Removed db:start, db:stop, db:reset, functions:serve from root scripts; kept db:push, db:diff --linked, functions:deploy. README, env templates, mobile setup, and 01_SOFTWARE_PLAN §1.7 updated.
  • Realtime client wiring. Both web and mobile now call realtime.setAuth(jwt) before .subscribe() so the channel join payload carries the user JWT — required by the new sb_publishable_* key model. Without this, the WS connected anonymously and RLS-scoped postgres_changes silently never arrived.
  • Audio playback identity moved from URL to memoryId in inline
    • detail players, so a 5-minute signed-URL refresh doesn’t mis- identify the active row.

Fixed

  • Empty-string sentinel for playback_storage_path swapped for playback_content_type = 'missing' so consumers’ || fallback to storage_path works cleanly.
  • Periodic position-save interval in the audio context was being torn down and re-installed on every position tick (deps included currentTime); now reads live status from a ref and gates the effect on playing only — the 5s callback actually fires now.
  • flushPendingUploads has a top-level flushing guard so concurrent foreground + pull-to-refresh + AppState-active triggers can’t all walk the queue in parallel and mint duplicate recordings rows.
  • Recorder no longer reuses a single temp file path. Persists each take to a unique URI immediately after stop; the queue uploads what was actually recorded, not whatever’s in the slot when the network came back.

Production hardening (landed in this release)

  • pgmq DLQ + max-retry policy. Sibling pipeline_jobs_dlq queue + pipeline_dead_letters diagnostics table + pipeline_stuck_jobs view. pipeline-tick enforces the retry ceiling at the dispatch boundary (PIPELINE_MAX_RETRIES, default 5). 30-day TTL on diagnostics (pruning job is a follow-up). See ADR-0008.
  • Rate limits on Stripe + ingest routes. New consume_rate_limit(p_uid, p_bucket, p_cap, p_window_seconds) RPC. Stripe checkout/portal: 10/hour/user. Ingest-audio: 15/min/user. Stripe webhook unchanged (signature-gated).
  • Explicit Sentry captures. Hand-rolled Deno envelope helper for Edge Functions (no @sentry/deno dep); used by pipeline-tick (on dead-letter promotion), all 6 step functions, ingest-audio, delete-memory. Web app captures wired into /api/chat driver errors and the three Stripe routes via @sentry/nextjs.
  • dev_pass production prep. Default flipped to false; existing rows bulk-updated. <DevPassSection /> hidden when NODE_ENV === "production"; the server action refuses there too (defense-in-depth). Vault placeholder service_role_key removed by migration with a RAISE WARNING pointing at the SQL to set the real value.
  • MCP server in CI. Standalone pnpm install --ignore-workspace
    • pnpm typecheck step on backend/mcp/arcive-memory-mcp/.
  • Universe pagination. Keyset on recorded_at desc via ?before=<iso>. Edges restricted server-side to those with both endpoints in the visible window — closes the silent 2000-edge cap.

Deferred to release prep

  • Apple Developer account + EAS development build → gates background- audio capture (always-on listening), BLE pairing, TestFlight, and store submission. Punted on 2026-05-04 to keep the iteration loop in Expo Go.
  • App Store / Play Store submissions.
  • Mobile background capture + Universe view + voice talk-back client
    • role conversations + BLE pairing UX.

0.2.0-rc.1 — 2026-05-03 — V0.2 (web slice + voice scaffold)

V0.2 web-only scope. Mobile app and store submissions are not in this RC.

Added

  • Claude Agent SDK driver (packages/agents/src/drivers/claude-agent-sdk.ts) — tool use + streaming + prompt caching. The model invokes search_memories only when it needs context. Drop-in swap behind the AgentDriver interface.
  • Tutor, Brainstorm Partner, Caregiver built-in roles.
  • Spaces UX (Family tier) — list, create, member view, token-based invite links, share-to-space toggle on memory detail. RLS lets members read shared memories.
  • Family Stripe price — checkout accepts {tier: "pro" | "family"}, webhook reads arcive_tier from subscription metadata to flip the right tier.
  • Tool-call indicator in chat UI (“Searching memories for X…”).
  • Internal MCP server scaffold (backend/mcp/arcive-memory-mcp/) — search_memories, get_person, timeline_window tools, Streamable HTTP transport, Supabase JWT auth.
  • Voice talk-back service (backend/workers/voice-talkback/) — Pipecat orchestrator: Deepgram Nova-3 → Claude Haiku 4.5 → Cartesia Sonic. WebSocket transport with Silero VAD. /talkback web client uses the Pipecat JS client SDK.
  • Spoken-register system prompt + composeVoiceSystemPrompt(role) helper so any role’s prompt can be composed with phone-call register rules.
  • Dev passuser_profiles.dev_pass short-circuits all tier gates and usage caps. Settings has an On/Off toggle. <ProBadge /> still shows on premium features so you can see what would be gated in production.
  • /about page — version, build SHA, phase status, changelog link.

Changed

  • /api/chat switched from stateless RAG to the Claude Agent SDK driver.
  • Settings shows three checkout CTAs (Upgrade Pro · Family · Switch to Family) based on current tier.
  • Universe and Spaces stop blocking free users; instead they render content with a Pro / Family badge in the header.

Fixed

  • Server-side billed duration in ingest-audio (floors to byte-size estimate, caps at 30s/chunk per the contract). Client can no longer under-report duration to dodge the cap.
  • Conversations persist to role_sessions and rehydrate from ?session=<id> in the URL.
  • Per-tier /api/chat rate limit (50 free / 500 pro per day).
  • Storage cleanup on memory delete via delete-memory Edge Function.

0.1.0 — 2026-05-03 — V0.1 (pipeline + retrieval + first AI features)

Added

  • pgmq queue + pg_cron drain replacing the synchronous transcribe chain. Step workers: transcribe, diarize, reid, summarize, embed, compute_edges. Each idempotent and retryable.
  • Diarization — Deepgram Nova-3 batch fills memory_participants rows.
  • Speaker re-ID — Pyannote.audio worker scaffold on Modal (backend/workers/pyannote-reid/). Cosine match against people.voice_embedding; auto-creates “Unknown speaker” when no match.
  • Voyage-3-lite embeddings + HNSW index on memories.embedding.
  • Semantic search on the Today search box (merges with FTS).
  • Markdown export — single memory + full archive.
  • Universe viewreact-force-graph-2d over memory_edges.
  • Reviewer role — first AI feature, stateless RAG driver, streaming chat UI with “memories used” drawer.
  • Stripe Pro tier — checkout, billing portal, webhook handling.
  • Tier gates + consume_recording_seconds RPC for monthly cap.
  • PostHog feature flags — server-side isEnabled() helper.

Changed

  • Hardened the pgmq migration with extension-/vault-fallback DO blocks so a missing extension can’t abort the migration suite.

0.0.1 — 2026-05-03 — V0 (web PWA dictaphone)

Added

  • Next.js 15 PWA — Tailwind, magic-link auth, consent screen, Today feed with FTS search, memory detail, settings.
  • RecordergetUserMedia + MediaRecorder, posts to /functions/v1/ingest-audio. Pulsing “Recording” badge for the consent contract.
  • Edge Functionsingest-audio (accepts phone and hardware uploads on the same endpoint per master plan §6.1) and transcribe-step (Groq Whisper-large-v3-turbo).
  • V0 schema — people, devices (with full variant enum), recordings, memories, edges, roles, sessions, spaces. Auto-create user_profile and “Self” person on signup.
  • Realtime — Today feed live-refreshes on insert/update, no polling.
  • PWA layer — manifest, service worker (offline shell), placeholder icons (192/512/maskable + apple-touch).
  • CI — GitHub Actions runs pnpm -r typecheck + pnpm --filter web build on push and PR.
  • Observability + billing scaffolds — PostHog, Sentry, Stripe customer pre-create. All no-op without env keys.
  • Shared contracts — Zod API contracts + BLE UUID placeholders for the firmware track.