# Project export: Zipity

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: OpenAI Build Week
- Tagline: A fast, personal AI learning companion that remembers what matters and wakes with a double clap.
- Devpost: https://devpost.com/software/zipity
- GitHub: https://github.com/Subhradeep246/Fastlearner
- Video: https://www.youtube.com/embed/IEumKkxdNJQ?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 2 GitHub contributor(s) — Subhradeep246 (7 commits), Tanmay Sahu (6 commits)

## Devpost submission (written by the team)

### Inspiration

Students are expected to manage classes, assignments, goals, notes, and AI chats across disconnected tools. Most assistants also forget who the learner is between sessions. Zipity is built around a simpler idea: one personal learning companion that grows with a student from the beginning of school through graduation.

### What it does

Zipity is a local-first desktop learning companion that: creates a personalized learner profile during first-run onboarding organizes multiple subjects, assignments, and learning goals in one place remembers relevant learner context while keeping it scoped to the device owner streams clear, structured answers with headings, lists, tables, quotes, and code blocks supports fast voice conversations with ElevenLabs wakes hands-free when the student double-claps, then listens for a request uses the name Zipity throughout the product for a consistent companion experience The current demo profile is prefilled with realistic Grade 10 subjects and tasks so judges can explore the full workflow immediately.

### How we built it

The desktop client uses Tauri 2, Rust, React 19, TypeScript, and Vite. A Rust/CPAL audio pipeline performs continuous low-overhead microphone analysis with an adaptive noise floor and double-clap detection. The backend uses FastAPI, PostgreSQL, and Redis, with typed contracts shared across the workspace. For the live assistant, Zipity uses Baseten to serve the GPT-OSS 120B model and ElevenLabs for speech. Responses stream into a safe structured renderer, while speech output receives a clean text-only version for natural delivery. How Codex and GPT-5.6 accelerated the build Codex with GPT-5.6 acted as the engineering partner across the build: it mapped the monorepo, traced the desktop-to-API request path, implemented the personalized onboarding and owner-scoped memory flow, hardened the Rust wake detector, redesigned the companion interface, generated the Zipity icon pipeline, and repeatedly ran the application to diagnose real microphone and desktop-runtime failures. The most important architectural decisions were made through those Codex sessions: keep identity and learning context explicitly owner-scoped instead of relying on one global chat history run clap detection natively in Rust for lower latency and more reliable Windows audio access separate display formatting from speech formatting so rich answers remain readable without making TTS sound robotic use frame-batched streaming updates to keep long answers smooth validate changes with API, UI, Rust, and production-build checks instead of stopping at generated code Codex also shortened the debug loop by inspecting logs, reproducing failures, editing across Rust/Python/TypeScript boundaries, and verifying each fix in the running desktop app.

### Challenges we ran into

Reliable hands-free wake-up was the hardest problem. Real microphones have changing ambient noise, device contention, and very different clap signatures. We built adaptive thresholds, timing windows, diagnostics, and recovery paths rather than treating a clap as a fixed-volume spike. We also had to balance rich, structured assistant responses with low-latency streaming and natural speech. That led to a two-path renderer: safe Markdown-like presentation for the screen and stripped, speakable text for voice.

### Accomplishments we're proud of

a working native desktop companion rather than a chat mockup personalized, owner-scoped context across many school subjects adaptive double-clap wake detection responsive streaming with structured, safely escaped answers an end-to-end voice loop using ElevenLabs broad automated coverage across the FastAPI service, React interface, and Rust desktop layer a cohesive, minimal visual identity built around Zipity's brain-and-lightning mark

### What we learned

A believable AI companion is not only a model call. It needs identity boundaries, reliable input, useful long-term context, graceful failure states, and an interface that makes complex answers easy to scan. Native audio and streaming UI work also benefit enormously from tight observe-edit-test loops—the kind of workflow Codex enabled throughout this project.

### What's next

Next we plan to add opt-in encrypted sync, a longitudinal learning graph, curriculum and calendar integrations, richer teacher/guardian controls, packaged installers, and a hosted backend so students can carry their context safely across devices.

## README (from the GitHub repository)

# Zipity

> A fast, personal AI learning companion that remembers what matters and wakes with a double clap.

Zipity is a native desktop companion designed to grow with a learner from their first school years through graduation. It brings subjects, assignments, goals, context, voice, and an AI tutor into one focused workspace—without treating every conversation as a blank slate.

![Zipity icon](apps/desktop/app-icon.png)

## What Zipity can do

- **Know the learner** — first-run onboarding creates a personal profile; relevant context stays scoped to that device owner.
- **Keep school organized** — manage many subjects, assignments, and learning goals in one desktop app.
- **Explain clearly** — the assistant streams structured answers with headings, lists, tables, quotes, and code blocks.
- **Talk naturally** — optional ElevenLabs speech provides a fast voice loop.
- **Wake hands-free** — double-clap to activate Zipity, then speak a request.
- **Stay responsive** — native Rust audio handling and frame-batched answer rendering keep the experience smooth.

## How it is built

| Layer         | Technology                                 |
| ------------- | ------------------------------------------ |
| Desktop app   | Tauri 2, Rust, React 19, TypeScript, Vite  |
| Voice wake-up | Rust, CPAL, adaptive double-clap detector  |
| API           | FastAPI, Python 3.12                       |
| Data          | PostgreSQL + pgvector, Neo4j, Valkey/Redis |
| AI            | Baseten-hosted GPT-OSS 120B                |
| Speech        | ElevenLabs (optional)                      |

## Quick start

These instructions run Zipity locally on a developer machine. The desktop app is currently **Windows-first**; macOS and Linux contributors also need the normal Tauri system dependencies for their platform.

### 1. Install prerequisites

Install the following before cloning the repository:

- [Node.js 22.13.1](https://nodejs.org/) and npm 10
- [Python 3.12.9](https://www.python.org/downloads/)
- [uv](https://docs.astral.sh/uv/)
- [Rust 1.88](https://rustup.rs/)
- [Docker Desktop](https://www.docker.com/products/docker-desktop/) and start it
- On Windows: Microsoft C++ Build Tools / Windows SDK, as required by Tauri

Confirm the versions used by this project:

```powershell
node --version
python --version
uv --version
cargo --version
docker --version
```

> The repository pins its expected versions in `.nvmrc`, `.python-version`, and `rust-toolchain.toml`.

### 2. Clone and install

```powershell
git clone https://github.com/Subhradeep246/Fastlearner.git
cd Fastlearner
npm ci
uv sync --project services/api --locked
```

### 3. Configure local environment variables

Create your private environment file:

```powershell
Copy-Item .env.example .env
```

Open `.env` and replace every value written as `<...>`. At minimum, set:

| Variable                 | What to provide                                             |
| ------------------------ | ----------------------------------------------------------- |
| `POSTGRES_PASSWORD`      | Any strong local database password                          |
| `DATABASE_URL`           | Use the same PostgreSQL password in this URL                |
| `NEO4J_PASSWORD`         | Any strong local Neo4j password                             |
| `AI_API_KEY`             | Your Baseten API key                                        |
| `APP_ENCRYPTION_KEY`     | A long random secret used to protect local application data |
| `SESSION_SIGNING_SECRET` | A separate long random secret                               |

For voice features, also set:

| Variable              | What to provide                                         |
| --------------------- | ------------------------------------------------------- |
| `ELEVENLABS_API_KEY`  | Your ElevenLabs API key                                 |
| `ELEVENLABS_VOICE_ID` | An ElevenLabs voice ID (a sensible default is included) |

`ELEVENLABS_API_KEY` is optional: the app still runs without speech synthesis. Keep all keys in `.env`; never commit that file or put secrets in a `VITE_*` variable.

### 4. Check the machine, then start Zipity

```powershell
npm run local:check
npm run dev:local
```

The supervisor starts PostgreSQL/pgvector, Neo4j, and Valkey in Docker; applies migrations; seeds the demo data; starts the worker and FastAPI service; then opens the Tauri desktop app.

On first launch, complete onboarding or use the included demo learner profile to explore the full experience.

## Using the companion

1. Create or choose a learner profile during onboarding.
2. Add subjects, assignments, and goals.
3. Ask Zipity for explanations, plans, revision help, or a breakdown of an assignment.
4. For hands-free mode, make two clear claps in sequence, wait for the wake confirmation, then speak your request.

### Double-clap troubleshooting

The detector adapts to background noise, but physical audio devices vary. If it does not wake:

- grant microphone permission to the desktop app;
- select the intended microphone as the default Windows input;
- make two sharp claps about half a second apart;
- close other apps that may be holding the microphone exclusively;
- reopen Zipity after changing an audio device.

The app remains fully usable with keyboard input if the microphone is unavailable.

## Useful commands

| Command                                            | Purpose                                                                     |
| -------------------------------------------------- | --------------------------------------------------------------------------- |
| `npm run dev:local`                                | Start databases, services, migrations, seed data, and the Tauri desktop app |
| `npm run dev:services`                             | Start only the backend services for headless development                    |
| `npm run local:check`                              | Validate configuration and local tooling without starting services          |
| `npm run api:dev`                                  | Run the FastAPI service directly for API debugging                          |
| `npm run db:migrate`                               | Apply database migrations                                                   |
| `npm run db:seed`                                  | Seed the local demo data                                                    |
| `npm run ci`                                       | Run formatting, contracts, linting, types, tests, builds, and Rust checks   |
| `npm run dev:reset -- --confirm delete-local-data` | Delete all local Zipity Docker data and start fresh                         |

> `dev:reset` is destructive: it removes the local PostgreSQL, Neo4j, and Valkey volumes. Only use it when you intentionally want to erase local development data.

## Project layout

```text
apps/
  desktop/             Tauri + React desktop experience
  web-dashboard/       Browser dashboard surface
crates/
  wake-detector/       Native Rust audio capture and double-clap detection
services/
  api/                 FastAPI API, persistence, AI and speech integrations
packages/
  contracts/           Generated API contracts
  ui/                  Shared UI components and onboarding flow
  content/             Shared learning content utilities
infra/
  docker-compose.yml   Local PostgreSQL, Neo4j, and Valkey services
docs/
  local-development.md Detailed local development notes
```

## Privacy and local data

Zipity is designed around personal context. Profile and learning context are owner-scoped, and API keys remain server-side in the local environment. Running locally still sends prompts to the AI and speech providers you configure (Baseten and optionally ElevenLabs), so use only credentials and data you are comfortable sharing with those providers.

## Contributing

Before opening a pull request, run:

```powershell
npm run ci
```

For focused work, each workspace package also exposes its own `b

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 153 recognized source files, 1046 KB.
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- HTML (language) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Rust (language) — detected in the code
- TypeScript (language) — detected in the code
- Docker (technology) — claimed on Devpost, not found in the code
- PostgreSQL (technology) — claimed on Devpost, not found in the code
- Redis (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (120 of 189)

```
.env.example
.github/workflows/ci.yml
.gitignore
.nvmrc
.prettierignore
.prettierrc.json
.python-version
.vscode/settings.json
adaptive-learning-app-spec.md
apps/desktop/index.html
apps/desktop/package.json
apps/desktop/src-tauri/build.rs
apps/desktop/src-tauri/Cargo.toml
apps/desktop/src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml
apps/desktop/src-tauri/icons/android/values/ic_launcher_background.xml
apps/desktop/src-tauri/icons/icon.icns
apps/desktop/src-tauri/src/commands.rs
apps/desktop/src-tauri/src/controller.rs
apps/desktop/src-tauri/src/lib.rs
apps/desktop/src-tauri/src/main.rs
apps/desktop/src-tauri/src/os/adapters.rs
apps/desktop/src-tauri/src/os/mod.rs
apps/desktop/src-tauri/src/os/platform.rs
apps/desktop/src-tauri/src/wake_runtime.rs
apps/desktop/src-tauri/tauri.conf.json
apps/desktop/src/App.test.tsx
apps/desktop/src/App.tsx
apps/desktop/src/clap.css
apps/desktop/src/companion.css
apps/desktop/src/features/companion/index.ts
apps/desktop/src/features/companion/useCompanion.ts
apps/desktop/src/features/companion/wakeController.test.ts
apps/desktop/src/features/companion/wakeController.ts
apps/desktop/src/main.tsx
apps/desktop/src/platform/tauri.test.ts
apps/desktop/src/platform/tauri.ts
apps/desktop/tsconfig.json
apps/desktop/vite.config.ts
apps/web-dashboard/index.html
apps/web-dashboard/package.json
apps/web-dashboard/src/App.test.tsx
apps/web-dashboard/src/App.tsx
apps/web-dashboard/src/main.tsx
apps/web-dashboard/tsconfig.json
apps/web-dashboard/vite.config.ts
Cargo.lock
Cargo.toml
crates/wake-detector/Cargo.toml
crates/wake-detector/src/capture.rs
crates/wake-detector/src/detector.rs
crates/wake-detector/src/diagnostics.rs
crates/wake-detector/src/lib.rs
docs/local-development.md
eslint.config.mjs
infra/docker-compose.yml
package.json
packages/content/package.json
packages/content/src/index.test.ts
packages/content/src/index.ts
packages/content/tsconfig.json
packages/contracts/openapi.json
packages/contracts/package.json
packages/contracts/src/generated/.gitkeep
packages/contracts/src/generated/schema.ts
packages/contracts/src/index.ts
packages/contracts/tsconfig.json
packages/ui/package.json
packages/ui/src/index.test.tsx
packages/ui/src/index.tsx
packages/ui/src/onboarding.css
packages/ui/src/Onboarding.test.tsx
packages/ui/src/Onboarding.tsx
packages/ui/src/styles.css
packages/ui/tsconfig.json
PROGRESS.md
README.md
rust-toolchain.toml
scripts/assert-clean-generated.mjs
scripts/export_openapi.py
services/api/alembic.ini
services/api/alembic/env.py
services/api/alembic/helpers.py
services/api/alembic/script.py.mako
services/api/alembic/versions/__init__.py
services/api/alembic/versions/0001_identity.py
services/api/alembic/versions/0002_curriculum.py
services/api/alembic/versions/0003_work.py
services/api/alembic/versions/0004_learning.py
services/api/alembic/versions/0005_memory_vector.py
services/api/alembic/versions/0006_actions.py
services/api/alembic/versions/0007_outbox.py
services/api/alembic/versions/0008_lifecycle.py
services/api/alembic/versions/0009_operations.py
services/api/alembic/versions/0010_constraints.py
services/api/alembic/versions/0011_owner_indexes.py
services/api/app/__init__.py
services/api/app/adapters/__init__.py
services/api/app/adapters/ai.py
services/api/app/adapters/files.py
services/api/app/adapters/graph.py
services/api/app/api/__init__.py
services/api/app/api/dependencies.py
services/api/app/api/errors.py
services/api/app/api/middleware.py
services/api/app/api/routers/__init__.py
services/api/app/api/routers/assistant.py
services/api/app/api/routers/health.py
services/api/app/api/routers/identity.py
services/api/app/api/routers/learning.py
services/api/app/api/routers/local_auth.py
services/api/app/api/routers/memory.py
services/api/app/api/routers/work.py
services/api/app/api/schemas.py
services/api/app/api/serialization.py
services/api/app/auth/__init__.py
services/api/app/auth/identity.py
services/api/app/auth/policy.py
services/api/app/auth/sessions.py
services/api/app/clock.py
services/api/app/commands/__init__.py
[69 more files omitted for size]
```

### Dependencies

- apps/desktop/package.json: @fastlearner/ui@0.1.0, @tauri-apps/api@2.11.1, @tauri-apps/cli@2.11.4, @types/react@19.1.0, @types/react-dom@19.1.1, @vitejs/plugin-react@4.4.1, react@19.1.0, react-dom@19.1.0, vite@6.4.3
- apps/desktop/src-tauri/Cargo.toml: serde@1, serde_json@1, tauri@=2.11.5, tauri-build@=2.6.3, wake-detector
- apps/web-dashboard/package.json: @fastlearner/contracts@0.1.0, @fastlearner/ui@0.1.0, @types/react@19.1.0, @types/react-dom@19.1.1, @vitejs/plugin-react@4.4.1, react@19.1.0, react-dom@19.1.0, vite@6.4.3
- crates/wake-detector/Cargo.toml: cpal@=0.15.3
- package.json: @eslint/js@9.39.5, eslint@9.39.5, globals@16.0.0, prettier@3.5.3, typescript@5.8.2, typescript-eslint@8.26.0, vitest@3.2.7
- packages/contracts/package.json: openapi-typescript@7.6.1
- packages/ui/package.json: @types/react@19.1.0, react@19.1.0, react@19.1.0, react-dom@19.1.0
- services/api/pyproject.toml: alembic@==1.15.1, fastapi@==0.115.12, httpx@==0.28.1, pgvector@==0.3.6, psycopg[binary]@==3.2.6, pydantic-settings@==2.8.1, sqlalchemy@==2.0.39, uvicorn[standard]@==0.34.0
- tests/conformance/package.json: @types/node@22.13.10

### Recent commits (newest first)

- Complete Zipity desktop companion
- Improve Zipity README
- Add local study APIs and desktop app shell
- Merge branch 'main' of https://github.com/Subhradeep246/Fastlearner
- update
- clean
- initial
- Restore FastLearner build specification
- Merge branch 'main' of https://github.com/Subhradeep246/Fastlearner
- del
- Revert "Expand FastLearner build specification"
- Expand FastLearner build specification
- plan

## Key source files (fetched from GitHub, selected and truncated for size)

### PROGRESS.md

```markdown
# Zipity Adaptive Learning App — Implementation Progress

> **Last updated:** 2026-07-20  
> **Spec location:** `.kiro/specs/adaptive-learning-app/`  
> **Task DAG:** `tasks.md` (13 waves, 62 total tasks, 38 required + 12 optional test tasks + 12 parent/checkpoint tasks)

---

## Summary

**15 of 62 tasks completed** (all required leaf tasks through Wave 3, plus partial Wave 4).  
**5 tasks currently in-progress** (were dispatched but session ended before completion).  
**47 tasks remaining** (including optional test tasks, checkpoints, and later waves).

---

## What Is Done (Completed Tasks)

### Wave 0 — Infrastructure Foundation
| Task | Status | What was built |
|------|--------|----------------|
| **1.1** Runtime settings, Docker Compose, startup guards | ✅ Done | `app/config.py` with typed `StartupConfigurationError`, production guards (local-auth, insecure origins, default credentials, missing secrets). `infra/docker-compose.yml` with pinned pgvector/PG16, Neo4j 5.26, Valkey 8.0.1, health checks, localhost-only ports, named volumes. `.env.example` extended. |

### Wave 1 — Migrations, Scripts, Wake Detector
| Task | Status | What was built |
|------|--------|----------------|
| **1.2** Alembic migrations + SQLAlchemy models + seeds | ✅ Done | 11-revision linear chain (identity → curriculum → work → learning → memory/vector → actions → outbox → lifecycle → operations → constraints → owner-indexes). `app/persistence/models.py`, `app/persistence/migrations.py`, `app/persistence/seeds.py`, `app/persistence/checks.py`. Schema/revision consistency checks. Idempotent local persona + curriculum seed. |
| **1.4** Cross-platform local startup scripts | ✅ Done | `app/devtools/local.py` supervisor with ordered readiness, `--services-only`, coordinated shutdown, destructive reset. Root `package.json` scripts: `dev:local`, `dev:services`, `dev:reset`, `db:migrate`, `db:seed`, `worker`, `local:check`, `test:services`. CI `service-backed` job. |
| **5.2** Pure Rust double-clap wake detector | ✅ Done | `crates/wake-detector/src/detector.rs`: adaptive noise-floor, 10-30ms frames, transient shape checks, 120-900ms pairing, cooldown 1.5-3s, monotonic time, pause/unavailable states, in-memory downmix, no network/AI/raw-audio persistence. 12 unit tests passing. |

### Wave 2 — Persistence Primitives, Identity, Tauri Shell
| Task | Status | What was built |
|------|--------|----------------|
| **1.3** Unit-of-work, idempotency, audit, outbox, worker | ✅ Done | `app/repositories/` (ports.py, unit_of_work.py, idempotency.py, audit.py, outbox.py, errors.py). `app/workers/` (policy.py, queue.py, relay.py, worker.py, main.py). `app/clock.py`. 12 tests. |
| **2.1** Identity, profile, device, session, relationships | ✅ Done | `app/domain/identity.py`, `app/auth/sessions.py` (HMAC-SHA256 signed tokens), `app/auth/identity.py` (LocalIdentityProvider), `app/repositories/identity.py`, `app/services/identity.py`. Server-side owner-scope resolution. 16 tests. |
| **5.1** Ta
[truncated — 8167 more characters]
```

### docs/local-development.md

```markdown
# Local development

Copy `.env.example` to `.env` and replace every `<...>` placeholder. The supervisor reports setting names but never prints configured values.

## Commands

- `npm run dev:local` starts or connects PostgreSQL/pgvector, Neo4j, and Valkey; waits for health; migrates; seeds; starts the worker and API; waits for API readiness; then starts Tauri.
- `npm run dev:services` runs the same ordered startup without Tauri for headless development.
- `npm run db:migrate` applies the migration chain.
- `npm run db:seed` applies idempotent local persona and versioned data seeds.
- `npm run api:dev` and `npm run worker` run an individual long-lived process for diagnosis.
- `npm run local:check` validates local configuration names, tools, and startup artifacts without starting services.
- `npm run test:services` migrates, seeds, and runs Python tests against already-running local services.

Press Ctrl+C once to stop supervised processes. Services started by the supervisor are stopped in reverse lifecycle order; services that were already running are left running. Named volumes and local data are preserved.

## Destructive reset

Reset is intentionally separate and requires an exact confirmation phrase:

```text
npm run dev:reset -- --confirm delete-local-data
```

This removes the Zipity Compose containers and named PostgreSQL, Neo4j, and Valkey volumes. Omitting or changing the phrase exits without modifying data.

## Safe remediation

Startup failures identify the unavailable component, affected feature, and a remediation command. For container diagnostics, inspect the named service locally with `docker compose --env-file .env -f infra/docker-compose.yml logs <service>`; do not paste logs containing secrets into issues.

```

### Cargo.toml

```
[workspace]
members = ["apps/desktop/src-tauri", "crates/wake-detector"]
resolver = "2"

[workspace.package]
version = "0.1.0"
edition = "2021"
license = "UNLICENSED"
rust-version = "1.88"

[workspace.lints.rust]
unsafe_code = "forbid"

[workspace.lints.clippy]
all = "deny"
pedantic = "warn"

```

### package.json

```
{
  "name": "fastlearner",
  "version": "0.1.0",
  "private": true,
  "packageManager": "npm@10.9.2",
  "engines": {
    "node": ">=22.13.0 <23"
  },
  "workspaces": [
    "apps/*",
    "packages/*",
    "tests/*"
  ],
  "scripts": {
    "build": "npm run build --workspaces --if-present",
    "typecheck": "npm run typecheck --workspaces --if-present",
    "test:js": "npm run test --workspaces --if-present",
    "test:python": "uv run --project services/api pytest",
    "test:rust": "cargo test --workspace --locked",
    "dev:local": "uv run --project services/api python -m app.devtools.local start",
    "dev:services": "uv run --project services/api python -m app.devtools.local start --services-only",
    "dev:reset": "uv run --project services/api python -m app.devtools.local reset",
    "local:check": "uv run --project services/api python -m app.devtools.local check --desktop",
    "db:migrate": "uv run --project services/api python -m app.devtools.local migrate",
    "db:seed": "uv run --project services/api python -m app.devtools.local seed",
    "api:dev": "uv run --project services/api uvicorn app.main:app --host 127.0.0.1 --port 8000 --reload",
    "worker": "uv run --project services/api python -m app.devtools.local worker",
    "test:services": "npm run db:migrate && npm run db:seed && npm run test:python",
    "lint:rust": "cargo fmt --all --check && cargo clippy --workspace --all-targets --locked -- -D warnings",
    "lint:js": "eslint . --max-warnings 0",
    "lint:python": "uv run --project services/api ruff check services/api",
    "format:check": "prettier --check .",
    "contracts:generate": "uv run --project services/api python scripts/export_openapi.py && npm run generate --workspace @fastlearner/contracts",
    "contracts:check": "npm run contracts:generate && node scripts/assert-clean-generated.mjs",
    "conformance": "npm run test --workspace @fastlearner/conformance",
    "ci:js": "npm run lint:js && npm run typecheck && npm run test:js && npm run build",
    "ci:python": "npm run lint:python && uv run --project services/api mypy services/api/app && npm run test:python",
    "ci:rust": "npm run lint:rust && npm run test:rust",
    "ci": "npm run contracts:check && npm run format:check && npm run ci:js && npm run ci:python && npm run ci:rust"
  },
  "devDependencies": {
    "@eslint/js": "9.39.5",
    "eslint": "9.39.5",
    "globals": "16.0.0",
    "prettier": "3.5.3",
    "typescript": "5.8.2",
    "typescript-eslint": "8.26.0",
    "vitest": "3.2.7"
  }
}

```

### infra/docker-compose.yml

```yaml
name: fastlearner

services:
  postgres:
    image: pgvector/pgvector:0.8.0-pg16
    environment:
      POSTGRES_DB: ${POSTGRES_DB:-fastlearner}
      POSTGRES_USER: ${POSTGRES_USER:-fastlearner}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env}
    ports:
      - "127.0.0.1:${POSTGRES_PORT:-5432}:5432"
    volumes:
      - fastlearner-postgres:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
      interval: 5s
      timeout: 5s
      retries: 12
      start_period: 10s
    networks: [fastlearner-private]

  neo4j:
    image: neo4j:5.26.0-community
    environment:
      NEO4J_AUTH: ${NEO4J_USER:-neo4j}/${NEO4J_PASSWORD:?Set NEO4J_PASSWORD in .env}
      FASTLEARNER_NEO4J_USER: ${NEO4J_USER:-neo4j}
      FASTLEARNER_NEO4J_PASSWORD: ${NEO4J_PASSWORD:?Set NEO4J_PASSWORD in .env}
      NEO4J_server_memory_heap_initial__size: 256m
      NEO4J_server_memory_heap_max__size: 512m
    ports:
      - "127.0.0.1:${NEO4J_HTTP_PORT:-7474}:7474"
      - "127.0.0.1:${NEO4J_BOLT_PORT:-7687}:7687"
    volumes:
      - fastlearner-neo4j-data:/data
      - fastlearner-neo4j-logs:/logs
    healthcheck:
      test:
        - CMD-SHELL
        - >-
          cypher-shell -a neo4j://localhost:7687 -u "$${FASTLEARNER_NEO4J_USER}"
          -p "$${FASTLEARNER_NEO4J_PASSWORD}" "RETURN 1;" >/dev/null 2>&1
      interval: 10s
      timeout: 10s
      retries: 12
      start_period: 30s
    networks: [fastlearner-private]

  redis:
    image: valkey/valkey:8.0.1-alpine
    command: ["valkey-server", "--appendonly", "yes"]
    ports:
      - "127.0.0.1:${REDIS_PORT:-6379}:6379"
    volumes:
      - fastlearner-valkey:/data
    healthcheck:
      test: ["CMD", "valkey-cli", "ping"]
      interval: 5s
      timeout: 5s
      retries: 12
      start_period: 5s
    networks: [fastlearner-private]

networks:
  fastlearner-private:
    name: fastlearner-private

volumes:
  fastlearner-postgres:
    name: fastlearner-postgres
  fastlearner-neo4j-data:
    name: fastlearner-neo4j-data
  fastlearner-neo4j-logs:
    name: fastlearner-neo4j-logs
  fastlearner-valkey:
    name: fastlearner-valkey

```

### tests/conformance/package.json

```
{
  "name": "@fastlearner/conformance",
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "scripts": {
    "typecheck": "tsc --noEmit",
    "test": "vitest run"
  },
  "devDependencies": {
    "@types/node": "22.13.10"
  }
}

```

### packages/content/package.json

```
{
  "name": "@fastlearner/content",
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "exports": {
    ".": "./src/index.ts"
  },
  "scripts": {
    "build": "tsc --noEmit",
    "typecheck": "tsc --noEmit",
    "test": "vitest run"
  }
}

```

### crates/wake-detector/Cargo.toml

```
[package]
name = "wake-detector"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true

[features]
default = []
native-capture = ["dep:cpal"]

[dependencies]
cpal = { version = "=0.15.3", optional = true }

[lints]
workspace = true

```

### packages/contracts/package.json

```
{
  "name": "@fastlearner/contracts",
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "exports": {
    ".": "./src/index.ts"
  },
  "scripts": {
    "generate": "openapi-typescript openapi.json -o src/generated/schema.ts",
    "build": "tsc --noEmit",
    "typecheck": "tsc --noEmit"
  },
  "devDependencies": {
    "openapi-typescript": "7.6.1"
  }
}

```

### packages/ui/package.json

```
{
  "name": "@fastlearner/ui",
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "exports": {
    ".": "./src/index.tsx"
  },
  "scripts": {
    "build": "tsc --noEmit",
    "typecheck": "tsc --noEmit",
    "test": "vitest run"
  },
  "peerDependencies": {
    "react": "19.1.0"
  },
  "devDependencies": {
    "@types/react": "19.1.0",
    "react": "19.1.0",
    "react-dom": "19.1.0"
  }
}

```

[153 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]