Commit Graph

16 Commits

Author SHA1 Message Date
NilsBriggen 108ac59cb1 Mobile UI: bottom tab navigation + auto-build APK on push
CI / test (push) Successful in 20s
CI / deploy-web (push) Successful in 27s
CI / build-apk (push) Successful in 42m14s
The Library crammed five text nav-links into a non-wrapping row with no
bottom navigation — unusable on phones. Restructure the primary screens
into a bottom tab bar:

- Add src/app/(tabs)/_layout.tsx: <Tabs> with 5 tabs (Library, Search,
  Study, Ask, Settings) with emoji icons and the accent active tint.
- Move index/search/study/ask/settings into the (tabs) route group; the
  parens keep URLs unchanged (/, /search, /study, /ask, /settings).
- Root _layout becomes a Stack hosting (tabs) (headerless) plus the
  secondary pushed screens (record, transcript/[id], courses, quiz,
  bibliography), each with a back-button header.
- Drop the per-screen <Stack.Screen> headers from the moved tabs (titles
  now come from Tabs); relocate Study's "Export Anki" action into the body.
- Library: remove the cramped header link-row and duplicate title; add a
  "nothing uploaded" subheader and a Courses link.

Verified at 375px: tab bar pinned to the bottom, 5 even tabs, navigation
between tabs works. tsc clean, web export OK, 279 tests pass.

CI: build-apk now runs automatically on every push to master (after
deploy-web), so the APK at /wisp.apk tracks master instead of being
frozen at a stale tag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 20:40:32 +02:00
NilsBriggen 7611ada001 feat(phase5): optional generative RAG — ask your lectures, with citations
CI / test (push) Successful in 20s
CI / build-apk (push) Has been skipped
CI / deploy-web (push) Successful in 33s
Strictly opt-in, gated, with the deterministic features as the always-present floor:
- GenerationEngine: WebLLM (Qwen2.5-1.5B, WebGPU, CDN-loaded) + BYO-key cloud
  (OpenAI-compatible); native stub. Pure grounding prompt builder (4 tests).
- rag.askLectures: retrieve Phase-1 hits -> grounded prompt -> answer with
  citations; refuses when nothing relevant; falls back to search-only when no
  engine is available. Never sends raw audio/transcripts — only question + snippets.
- aiStore (BYO key persisted in localStorage on web), Ask screen (answer +
  tappable citation chips that jump to the audio + honest "verify" disclaimer),
  Settings AI section (engine status + bring-your-own-key form).

279 tests green, 0 tsc errors, web export builds. ROADMAP phases 0-5 complete.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 15:56:57 +02:00
NilsBriggen 97aee3e4b3 feat(phase4): enrichment — dates->calendar, citations->references, book/paper links
CI / test (push) Successful in 16s
CI / build-apk (push) Has been skipped
CI / deploy-web (push) Successful in 29s
All detection pure/on-device; lookups send only the id/topic (never transcript):
- src/lib/enrich pure modules: dates (absolute + relative, anchored to lectureDate),
  citations (DOI/arXiv/ISBN/author-year), ics (RFC5545), bib (BibTeX/RIS), links
  (legit + Anna's Archive/LibGen search URLs) — 60 tests.
- lookup.ts: CORS-friendly metadata clients (Crossref/OpenAlex/Open Library) +
  Wikipedia summary; AbortController timeouts, session cache, never throws.
- UI: transcript "Dates & references" (add to calendar .ics, look up references +
  open DOI/OpenLibrary/Google Books/Wikipedia/Anna's Archive/LibGen); per-course
  Bibliography screen with BibTeX/RIS export.

Not going to app stores, so Anna's Archive/LibGen links are included per request
(search URLs only — never fetched/proxied). 275 tests green, 0 tsc errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 15:48:13 +02:00
NilsBriggen 40858e0025 feat(phase3): learning helpers — summary, glossary, flashcards (SM-2), quizzes
CI / test (push) Successful in 16s
CI / build-apk (push) Has been skipped
CI / deploy-web (push) Successful in 30s
Deterministic, on-device, no model:
- src/lib/learn pure modules (tokenize, summary [TextRank-ish], glossary
  [definition-pattern + frequency], flashcards [cloze/Q-A], srs [SM-2], quiz
  [MCQ with distractors]) — 37 unit tests.
- Flashcard persistence: Dexie v4 + native v4 `flashcards` table; create/list/
  listDue/updateSrs/delete/counts; cascades (transcript delete, course->Unsorted).
- UI: transcript "Study aids" (generate summary+glossary, click-to-seek; create
  flashcards), Study screen (SM-2 review + Anki CSV export), per-lecture Quiz,
  library Study link with due-count badge.

215 tests green, 0 tsc errors, web export builds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 15:37:42 +02:00
NilsBriggen 6d2f583136 feat(phase2): in-app live recording into courses (web)
CI / test (push) Successful in 17s
CI / build-apk (push) Has been skipped
CI / deploy-web (push) Successful in 28s
- useRecorder: MediaRecorder mic capture with elapsed timer, live input-level
  meter (AnalyserNode), pause/resume, and a screen Wake Lock; returns the
  recording as an ArrayBuffer that flows into the existing transcribe pipeline.
- Record screen: big timer + level meter + start/pause/resume/stop; on stop the
  pre-capture sheet collects title/course/date, then it transcribes + saves +
  indexes (reusing Phase 0/1). Home gets Record + Import buttons.
- Web-only for now; native realtime (whisper.rn), OPFS crash-recovery,
  tab-audio capture, and the per-course dashboard are follow-ups.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 14:53:15 +02:00
NilsBriggen fc24c0875d feat(phase1): on-device semantic recall — embeddings, vector search, hybrid ranking
CI / test (push) Successful in 17s
CI / build-apk (push) Has been skipped
CI / deploy-web (push) Successful in 27s
Exam-time search over your own lectures, 100% on-device (vectors never leave it):
- EmbeddingEngine (transformers.js feature-extraction via the CDN loader,
  multilingual-e5-small 384-dim, e5 query/passage prefixes); native stub.
- Vector store in StorageRepo (Dexie v3 + native v3 segvecs): upsertVectors,
  brute-force cosine searchVectors (course-scoped), clearVectors, unembeddedIds.
  Cascades: re-embed on segment edit, reassign updates vector courseId, deletes cascade.
- Hybrid search: semantic candidates + lexical rank fused via reciprocal-rank-fusion
  (pure, tested); searchLectures() returns segment hits tagged semantic/lexical/both.
- embeddingStore: build-index/backfill with progress + embed-on-save (fire-and-forget).
- Search screen: query -> segment hits (snippet · course · time) -> tap jumps the
  transcript to that timestamp (seek + scroll-into-view). Per-course stats on Courses.

25 repo tests (incl. cosine ranking + course scoping), 13 search tests, 170 total green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 14:48:03 +02:00
NilsBriggen 8db59d4bbe feat(phase0): courses, migrations, persisted audio, stable segment IDs, course-aware UI
CI / test (push) Successful in 16s
CI / build-apk (push) Has been skipped
CI / deploy-web (push) Successful in 29s
Data layer (Zod-gated, behind StorageRepo; web Dexie v2 + native expo-sqlite
user_version migrations, both with no-data-loss segment-id backfill):
- Course entity + courseId/lectureDate/instructor/location/tags/lectureNumber on
  transcripts; listCourses/createCourse/updateCourse/deleteCourse, listByCourse,
  reassign. Stable per-segment ids assigned on create/update + backfilled.
- Persisted source audio (Dexie blob / expo-file-system) via putMedia/getMediaUrl;
  the editor replays it after reload.

UI/stores:
- Pre-capture sheet (title + course + lecture date + language) before transcribing.
- Course-aware library home (All/Unsorted/per-course filter) + Courses screen.
- coursesStore; transcriptsStore course filter + reassign; transcribeStore threads
  course/date and persists media.

16 web-repo tests incl. v1->v2 migration no-data-loss; 148 total green; web export OK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 13:54:38 +02:00
NilsBriggen 30dd2d5b75 ci(apk): arm64-only, tag-triggered, persistent /wisp.apk via host mount
- android.Dockerfile: build arm64-v8a only (--max-workers=2) → ~48MB APK, ~4x
  less compile (the 4-ABI build timed out on the shared prod runner).
- ci.yml: build-apk runs only on version tags (v*), timeout 120m — normal pushes
  no longer peg the box; web still auto-deploys on every master push.
- wisp.compose.yml: mount /srv/wisp/wisp.apk read-only so the download survives
  web container rebuilds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 13:54:38 +02:00
NilsBriggen 7a1e6b06c1 fix(android): working signed release APK
CI / test (push) Successful in 22s
CI / deploy-web (push) Successful in 34s
CI / build-apk (push) Failing after 3h1m42s
- docker/android.Dockerfile: install nodejs (image ships Bun; ci-android-sign.sh
  patches build.gradle with a Node script).
- buffer polyfill: whisper.rn -> safe-buffer requires Node's `buffer`, absent in
  Metro/RN. Add `buffer` dep, alias it in metro.config.js, set the global in
  _layout. Web export unaffected (verified).

Validated locally end-to-end: assembleRelease BUILD SUCCESSFUL, 117MB APK across
all 4 ABIs with librnwhisper.so, signed (CN=Wisp, O=briggen.dev).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 23:59:08 +02:00
NilsBriggen 74a436b5ee docs: study-system roadmap (courses, on-device semantic recall, learning helpers, enrichment, optional RAG)
CI / test (push) Successful in 23s
CI / deploy-web (push) Successful in 7s
CI / build-apk (push) Failing after 6s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 21:10:36 +02:00
NilsBriggen ec90c1588c ci: build + serve signed Android APK on push to master
CI / test (push) Successful in 22s
CI / build-apk (push) Failing after 1m2s
CI / deploy-web (push) Successful in 29s
- docker/android.Dockerfile: full socket-safe build (JDK17 + SDK + NDK 27 +
  CMake + Bun) -> expo prebuild -> sign (BuildKit --secret) -> assembleRelease.
- ci.yml build-apk job: buildx build, extract APK via docker create/cp, copy
  into the running wisp container so it serves at /wisp.apk; artifact upload.
- app.json: set android.package = dev.briggen.wisp (required by prebuild).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 19:25:24 +02:00
NilsBriggen 1ec6f14f20 ci: trigger run after runner socket-mount fix
CI / test (push) Successful in 27s
CI / deploy-web (push) Successful in 30s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 18:44:20 +02:00
NilsBriggen 1ba172bdeb ci: run test on default image + install Bun (Node-less bun container broke checkout)
CI / test (push) Failing after 13s
CI / deploy-web (push) Has been skipped
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 18:39:10 +02:00
NilsBriggen 84e7a56b13 CI: Gitea Actions web auto-deploy (runner-on-server) + signing prep
CI / test (push) Failing after 3s
CI / deploy-web (push) Has been skipped
- .gitea/workflows/ci.yml rewritten for a self-hosted runner co-located with
  the host Docker daemon + Traefik: push to master -> test -> deploy-web
  (docker compose up --build in place; no SSH, no registry). APK job documented
  as the next iteration (socket-safe build+extract; signing secrets already set).
- .gitignore: never commit the release keystore (*.keystore + wisp-release.keystore).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 18:27:26 +02:00
NilsBriggen 9f42ee2460 Build Wisp: on-device transcription studio (web + native, one codebase)
CI / test (push) Has been cancelled
CI / deploy-web (push) Has been cancelled
CI / build-apk (push) Has been cancelled
Private, offline speech-to-text that runs Whisper on the user's own device —
free, no account, no per-minute fees. Replaces Otter.ai / Rev.

- Pure, tested engine: chunking, overlap timestamp-stitching, exports
  (SRT/VTT/TXT/MD/JSON), WAV codec, resampler, job queue, model catalog (142 tests).
- Platform-abstracted TranscriptionEngine: transformers.js on web (loaded from
  CDN at runtime to dodge Metro's onnxruntime-web bundling limits), whisper.rn
  on native. Shared pipeline orchestrates decode -> chunk -> transcribe -> stitch.
- Cross-platform StorageRepo (Dexie web / expo-sqlite native), Zod-validated.
- UI: library + search, import, live-progress transcription, synced click-to-seek
  editor, multi-format export; model picker + privacy in settings.
- Web ships as a single-page PWA with COOP/COEP isolation for threaded WASM;
  Docker (nginx) image + Traefik compose for wisp.briggen.dev.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 17:54:21 +02:00
NilsBriggen 97996c9846 Initial commit
Generated by create-expo-app 4.0.0.
2026-06-13 17:05:52 +02:00