Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: CI

on:
push:
branches: [ main, development ]
pull_request:
branches: [ main, development ]

jobs:
test:
name: test (${{ matrix.os }}, py${{ matrix.python-version }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest ]
python-version: [ "3.11", "3.12" ]

steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
cache-dependency-path: "pyproject.toml"

- name: Install Linux dependencies
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y libportaudio2 libasound2-dev

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .[dev,nlp,whisper]

- name: Run Ruff Linter
run: ruff check src/

- name: Run Mypy Type Checker
run: mypy src/

- name: Run Safety Check
run: safety check

- name: Run Pytest with Coverage
# GUI tests might require mock display on Ubuntu. Let's use xvfb on Ubuntu runner.
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get install -y xvfb
xvfb-run --server-args="-screen 0 1024x768x24" pytest tests/ -v --cov=src --cov-fail-under=80 --cov-report=xml

- name: Run Pytest with Coverage (Windows)
if: matrix.os == 'windows-latest'
run: pytest tests/ -v --cov=src --cov-fail-under=80 --cov-report=xml
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,8 @@ models/
logs/
*.log
.gemini/
.coverage
htmlcov/
.pytest_cache/
.mypy_cache/
.ruff_cache/
18 changes: 18 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Taskify Makefile target shortcuts

.PHONY: dist clean test lint typecheck

dist:
python packaging/build.py

clean:
python -c "import shutil; [shutil.rmtree(p, ignore_errors=True) for p in ('build', 'dist')]"

test:
pytest tests/ -v

lint:
ruff check src/ --fix

typecheck:
mypy src/
140 changes: 140 additions & 0 deletions docs/developer_guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# Taskify Developer Guide

This guide describes the architecture, codebase organization, database schema, and test suites for developers contributing to Taskify.

---

## 1. Directory Structure & Architecture

Taskify's architecture is modular, separating audio capture, speech recognition, database storage, extraction scheduling, and the user interface.

```
src/taskify/
├── __init__.py
├── __main__.py # Program execution launcher
├── cli/ # Click command-line interface
├── audio/ # PyAudio / sounddevice capture streams
├── stt/ # Vosk & Whisper speech transcription backends
├── storage/ # SQLite migrations and CRUD data access
├── llm/ # Ollama and rule-based NLP extraction engines
├── pipeline/ # Background extraction worker scheduler
└── ui/ # customtkinter graphical widgets
```

### Core Architecture Flowchart

```mermaid
graph TD
A[Microphone Stream] --> B[Audio Capture Queue]
B --> C[STT Engine: Vosk/Whisper]
C --> D[Transcript Database & Rotated Logs]
D --> E[Extraction Scheduler]
E --> F[LLM / NLP Extraction Engine]
F --> G[Tasks & Matrix Database Tables]
G --> H[Eisenhower Matrix GUI Dashboard]
```

---

## 2. Codebase Components

### 1. Configuration (`src/taskify/config/`)
- Uses `Settings` dataclasses mapped from default settings TOML and user-customizable overrides.

### 2. Audio Capture (`src/taskify/audio/`)
- Uses `sounddevice` to stream raw float32 array samples to a thread-safe Queue.
- Implements energy-based silence detection algorithms to pause downstream transcribing during quiet periods.

### 3. Speech-to-Text (`src/taskify/stt/`)
- Implements the `STTEngine` interface:
- `VoskEngine`: Primary offline, light model.
- `WhisperEngine`: Heavy model wrapper utilizing `faster-whisper`.
- Models are lazy loaded and resolved via the `get_stt_engine` factory.

### 4. Storage Engine (`src/taskify/storage/`)
- `DatabaseManager`: Exposes thread-safe connections using SQLite stdlib. Run database migration scripts sequentially from `storage/migrations/`.
- `TranscriptWriter`: Background worker flushing transcripts to SQLite and rotating logs at midnight.

### 5. Extraction Pipeline (`src/taskify/pipeline/`)
- `ExtractionScheduler`: Periodically triggers an extraction cycle in a daemon thread.
- `EventBus`: Decoupled publisher-subscriber hub matching pipeline updates to frontend dashboard refreshes.

---

## 3. SQLite Database Schema

Taskify uses four relational tables tracking capture sessions, segments, task lists, and categorization entries:

```sql
-- Schema version tracking
CREATE TABLE schema_migrations (
version INTEGER PRIMARY KEY,
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Voice capture sessions
CREATE TABLE sessions (
id TEXT PRIMARY KEY,
start_time REAL NOT NULL,
end_time REAL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Transcribed audio segment lines
CREATE TABLE transcripts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT REFERENCES sessions(id) ON DELETE CASCADE,
text TEXT NOT NULL,
confidence REAL NOT NULL,
start_time REAL NOT NULL,
end_time REAL NOT NULL,
processed INTEGER DEFAULT 0 CHECK(processed IN (0, 1)),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Extracted tasks
CREATE TABLE tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
notes TEXT,
due_date TEXT,
completed INTEGER DEFAULT 0 CHECK(completed IN (0, 1)),
user_override INTEGER DEFAULT 0 CHECK(user_override IN (0, 1)),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Eisenhower matrix quadrant entries
CREATE TABLE matrix_entries (
task_id INTEGER PRIMARY KEY REFERENCES tasks(id) ON DELETE CASCADE,
quadrant TEXT CHECK(quadrant IN ('urgent_important', 'important_not_urgent', 'urgent_not_important', 'neither')),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```

---

## 4. Development Setup & Tests

### Installation
1. Clone the repository and establish a Python virtual environment:
```bash
python -m venv .venv
.venv\Scripts\activate # Windows
source .venv/bin/activate # macOS/Linux
```
2. Install with all development extras:
```bash
pip install -e .[dev,nlp,whisper]
```

### Makefile Shortcuts
Taskify includes automated quality checks and builders.

| Action | Makefile Target | CLI Alternative |
|---|---|---|
| Run Complete Test Suite | `make test` | `pytest tests/ -v` |
| Code Lint Check | `make lint` | `ruff check src/` |
| Type-Checking | `make typecheck` | `mypy src/` |
| Package Executable | `make dist` | `python packaging/build.py` |
59 changes: 59 additions & 0 deletions docs/model_download.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Offline STT Model Download Guide

Taskify is a **privacy-first application** that runs all speech-to-text (STT) models locally on your system. No audio data or transcriptions are ever sent online.

---

## 1. Storage Directories

Local model files are stored in the following platform-specific application directories:

| OS | Default Download Directory |
|---|---|
| **Windows** | `C:\Users\<Username>\.local\share\taskify\models\` |
| **macOS** | `/Users/<Username>/.local/share/taskify/models/` |
| **Linux** | `/home/<Username>/.local/share/taskify/models/` |

---

## 2. Vosk Models Setup

### Automatic Download
If you are connected to the internet, run the CLI utility to download and extract automatically:
```bash
# Download the default small english model
taskify download-model vosk en-small
```

### Manual Offline Setup (Air-gapped)
If you are setting up Taskify on an offline machine, follow these steps:
1. **Download the model ZIP** from the official Vosk repository:
- **en-small** (Lightweight, default): [vosk-model-small-en-us-0.15.zip](https://alphacephei.com/vosk/models/vosk-model-small-en-us-0.15.zip) (Approx. 40 MB)
- **en-large** (High accuracy): [vosk-model-en-us-0.22-lgraph.zip](https://alphacephei.com/vosk/models/vosk-model-en-us-0.22-lgraph.zip) (Approx. 120 MB)
2. **Extract the ZIP file** into your local Taskify model directory:
- Path for `en-small`: `.../taskify/models/vosk/vosk-model-small-en-us-0.15/`
3. **Verify directory structure**:
- Ensure the directory contains database folders like `am/`, `graph/`, and description files such as `README`.

---

## 3. Whisper Models Setup

### Automatic Download
To automatically download standard HuggingFace quantized model parameters via `faster-whisper`:
```bash
# Downloads and registers the "base" model
taskify download-model whisper base
```
Supported configurations: `tiny`, `base`, `small`.

### Manual Offline Setup (Air-gapped)
Huggingface Whisper weights are resolved via the `huggingface_hub` caching mechanism:
1. On an online machine, download the model files using python:
```python
from faster_whisper import WhisperModel
model = WhisperModel("base", device="cpu", compute_type="int8")
```
2. Copy the cached Hugging Face hub folders from your online machine to the offline machine:
- Cache Directory (default): `~/.cache/huggingface/hub/`
3. Ensure the target directory layout is replicated exactly. Taskify will automatically detect the cache on start.
47 changes: 47 additions & 0 deletions docs/privacy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Taskify Privacy Statement & Network Inventory

Taskify is built from the ground up as a **fully offline, privacy-first task manager**. We believe your private spoken conversations, thoughts, plans, and task details belong entirely to you and should never leave your physical device.

---

## 1. Zero Network Interactions

Taskify compiles a strict **Network Interaction Inventory** containing exactly zero runtime remote operations:

- **No Remote Speech Recognition**: All audio captured via your microphone is transcribed locally using `vosk` or `faster-whisper`.
- **No Cloud LLM Processing**: Task extractions and Eisenhower classifications are performed locally via Ollama (using models running on your system like `phi4` or `gemma`) or via our rule-based `NLPBackend` regex system.
- **No Telemetry or Tracking**: The application does not collect usage stats, metrics, crash dumps, or run analytics trackers.
- **Zero Remote Dependencies**: The application does not download runtime assets. (The only remote network requests are initiated explicitly by the user when running `taskify download-model` to fetch voice packs).

---

## 2. Local File & Data Storage Inventory

All data generated by Taskify is stored in plain sight, locally on your machine. You can inspect, modify, back up, or delete it at any time.

### Database
- **Path**: `~/.local/share/taskify/taskify.db` (SQLite format)
- **Contents**: Stores capture sessions, transcribed speech text segments, task lists, and Eisenhower Matrix categories.

### Rotation Logs & Transcripts
- **Path**: `~/.local/share/taskify/logs/`
- **Markdown Logs (`YYYY-MM-DD.md`)**: A daily human-readable record of all conversations transcribed during that day.
- **JSON Lines Logs (`YYYY-MM-DD.json`)**: Machine-readable logs of session transcripts for debugging.
- **Application Diagnostics Log (`app.log`)**: Unified application operation logs (rotated automatically at 10 MB).

### Configuration Files
- **Default Package Configuration**: `src/taskify/config/config.default.toml`
- **User Preference Configuration overrides**: `~/.config/taskify/config.toml` (TOML format)
- **Contents**: Local audio rate, silence detection threshold, selected STT model parameters, and Ollama host server configurations.

### Local Machine Models
- **Path**: `~/.local/share/taskify/models/`
- **Contents**: Extracted local speech recognition models (`vosk` directories).

---

## 3. Transparency & Verification

Developers can inspect the codebase to verify our privacy assertions:
1. Check [ollama_backend.py](file:///c:/Users/nihal/Desktop/Taskify/src/taskify/llm/ollama_backend.py): Outgoing requests are sent exclusively to the user's custom configured `ollama_host` (defaulting to local port `http://localhost:11434`).
2. Check [capture.py](file:///c:/Users/nihal/Desktop/Taskify/src/taskify/audio/capture.py) and [transcript_writer.py](file:///c:/Users/nihal/Desktop/Taskify/src/taskify/storage/transcript_writer.py): Audio bytes and transcripts are directed exclusively to the local database and rotation log writers.
Loading
Loading