Metadata-Version: 2.5
Name: olenji
Version: 1.0.0
Summary: Agent-operated transcription, translation, and live browser captions
License-Expression: Apache-2.0
License-File: LICENSE
License-File: THIRD_PARTY_NOTICES.md
Keywords: agents,cli,mcp,speech-to-text,subtitles,transcription
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Requires-Python: >=3.11
Requires-Dist: anyio>=4
Requires-Dist: fastapi<1,>=0.115
Requires-Dist: httpx<1,>=0.27
Requires-Dist: huggingface-hub>=0.27
Requires-Dist: jsonschema<5,>=4.23
Requires-Dist: numpy>=1.26
Requires-Dist: python-multipart>=0.0.18
Requires-Dist: rich>=13
Requires-Dist: soundcard>=0.4.6; sys_platform == 'win32'
Requires-Dist: sounddevice>=0.5.6
Requires-Dist: soundfile>=0.12
Requires-Dist: uvicorn<1,>=0.30
Requires-Dist: websockets>=13
Provides-Extra: dev
Requires-Dist: build>=1; extra == 'dev'
Requires-Dist: httpx>=0.27; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Provides-Extra: diarization
Requires-Dist: scikit-learn>=1.4; extra == 'diarization'
Requires-Dist: sherpa-onnx==2.0.0; extra == 'diarization'
Provides-Extra: system-audio
Requires-Dist: soundcard>=0.4.6; extra == 'system-audio'
Provides-Extra: whisper
Requires-Dist: faster-whisper==1.2.1; extra == 'whisper'
Description-Content-Type: text/markdown

# olenji

**Speech, in a form your agent can work with.**

Olenji is a local transcription application with a CLI, durable background service, MCP tools, and an optional browser tab. Import an existing recording, transcribe live audio, label speakers, translate into Turkish or another language, and ask your agent to direct the presentation.

This working edition includes the **29 October 2026 Linux review**. See [current validation](docs/VALIDATION.md) for fresh tests, fixes, and remaining native-host checks. Earlier reports retain their original artifact scope; `1.0.0` is still an unpublished development version.

The CLI, browser and MCP server use the same session database and event stream. Closing an agent or viewer does not stop service-owned capture. A browser microphone remains owned by the tab supplying it.

## Install and start

Requires **Python 3.11+** and **FFmpeg/ffprobe** on your path. Use standard **CPython 3.12** for the widest reviewed model-runtime compatibility. Managed inference supports CPython 3.11–3.14 with model-specific restrictions; see the [platform matrix](docs/NATIVE_PORTABILITY.md). Native microphone recording also requires PortAudio; macOS and Windows sounddevice wheels supply it, while Linux may need the distribution's PortAudio package.

From this source bundle:

```sh
uv tool install .
# Alternatively, in a virtual environment:
python -m pip install .

olenji doctor
olenji models install faster-whisper.tiny
olenji transcribe interview.mp4 --retain-audio --open
```

If you received the built wheel:

```sh
uv tool install ./dist/olenji-1.0.0-py3-none-any.whl
```

### npm installation route

The coordinated release also contains an npm tarball with the **same Python wheel** and hashed default dependencies. With Node.js 22.14+ and uv installed:

```sh
npm install --global ./dist/olenji-1.0.0.tgz
olenji-bootstrap setup --python 3.12
olenji-bootstrap status --json
olenji doctor --json
```

There are no installation hooks. Explicit setup creates a persistent isolated runtime; ordinary commands launch it directly without dependency resolution or downloads. Setup does not install speech models. Application runtimes and transcript/model data have separate lifetimes, and upgrades retain environments that a detached service may still use. See the [npm package guide](packages/npm/README.md) for offline setup, runtime location and recovery.

These examples install local release artifacts. Registry names, the actual Git repository and trusted publishers still need to be configured before public npm/PyPI installation commands refer to this project; see [RELEASING.md](docs/RELEASING.md). If both distribution routes are installed on one machine, select the intended executable on your PATH before starting the service.

There is no account, subscription, mandatory hosted backend, or CDN dependency. Commands that need the workspace service start a private loopback listener automatically; help/version are local lightweight operations. Model installation downloads the requested artifacts and any required inference environment; normal local inference does not require Internet access.

`olenji ui open` opens or reuses a paired browser tab. On a machine without a browser launcher, `olenji ui open --print-url` prints a one-use pairing link. The link expires after five minutes. Pairing grants access to this local workspace; the durable API token stays in the protected data directory.

When replacing an earlier development build, stop its service first with `olenji service stop`, then reinstall the new wheel using `uv tool install --force ./dist/olenji-1.0.0-py3-none-any.whl` (or `python -m pip install --force-reinstall ./dist/olenji-1.0.0-py3-none-any.whl` in your virtual environment). Stop waits for service ownership and workers to finish; a timeout is an explicit error. Existing transcripts and downloaded models remain in the selected data directory. The schema-4 upgrade creates a consistent pre-upgrade database backup before changing an existing database; see [upgrade and recovery](docs/DEEP_HARDENING.md#upgrade-and-recovery) before reverting to an older build.

If the owned service reports a different application version, normal commands return `SERVICE_VERSION_MISMATCH`. `service status --json` still reports both versions and `service stop` remains available. Olenji never restarts an active recording automatically because a package changed. Published versions must be immutable; the explicit stop/reinstall procedure also applies to unpublished development archives sharing the same version string.

## A complete agent workflow

The [agent guide](docs/AGENT_GUIDE.md) covers MCP setup, source revision rules, live capture ownership, translation and view acknowledgments.

```sh
# Discover actual capabilities and model readiness.
olenji doctor --json
olenji models list --json
olenji models plan-install --profile fluidvoice-parity --compatible-only --json

# Download a specific model, or the compatible portion of the complete baseline.
olenji models install faster-whisper.tiny --json
olenji models install --profile fluidvoice-parity --compatible-only --no-wait --json
olenji jobs wait JOB_ID --json

# Transcribe a file; this returns stable session and job IDs.
olenji transcribe recording.mov --model faster-whisper.tiny --language en \
  --retain-audio --no-wait --json
olenji jobs get JOB_ID --json
olenji segments list SESSION_ID --limit 100 --json

# Direct a tab without generating arbitrary browser JavaScript.
olenji ui open SESSION_ID --layout bilingual --translation tr --json
olenji ui configure VIEW_ID --config '{"layout":"captions","target_language":"tr","font_scale":1.4}' --json
olenji ui status VIEW_ID --json

# Export durable, portable output.
olenji export SESSION_ID --format vtt --language bilingual --to tr --out transcript.vtt
```

All examples use returned IDs in place of `SESSION_ID`, `JOB_ID`, and `VIEW_ID`. They are commands for the installed application, not fake demo endpoints.

Machine output is explicit with `--json` or `--jsonl`; redirected stdout defaults to JSON. Logs and interactive progress go to stderr. `olenji schema --json` exposes the complete API schema. `--idempotency-key UNIQUE_KEY` protects supported session/job starts from ordinary duplicate retries with identical arguments. A different payload with the same key fails with a conflict. Job cancellation is explicit; Ctrl-C detaches a waiting CLI without cancelling the job.

Multi-file transcription derives a separate stable key for each path and position in the batch. Retrying the same batch returns the original sessions/jobs, even if preferences changed or the original files were subsequently moved. A completed idempotent result does not re-read the original file.

## Saved defaults and explicit choices

Omitting a model, recognition language, audio-retention option or translation target uses the saved preference across CLI, MCP, file uploads and live starts. New browser views use the saved layout, theme and translation language. Explicit choices always take precedence, including `--language auto` and `--no-retain-audio` when retention has been enabled in Settings.

```sh
olenji config set default_language en
olenji config set default_translation_language tr
olenji config set ui_layout bilingual
olenji transcribe recording.mp4 --no-retain-audio --no-wait --json
```

Recognition-language support depends on the selected model. A translation target is an explicit language code such as `tr`, `de`, or `pt-BR`. The `max_parallel_jobs` setting takes effect after restarting the background service; other preferences apply to subsequent operations. Use explicit options for reproducible agent workflows.

## Models: breadth with honest readiness

The registry includes all **17 selectable ASR identities in the FluidVoice reference audited on 25 October 2026**, including its newly enabled Qwen3 ASR 1.7B Q8_0, exact GGUF/Core ML identities and the two Apple speech backends. Olenji has 29 transcription identities plus one acoustic speaker model. Portable Faster Whisper, Moonshine, Qwen and Voxtral choices retain distinct IDs. The machine-readable catalog is in `olenji/catalog.py`; the readable matrix is in [docs/MODEL_SUPPORT.md](docs/MODEL_SUPPORT.md).

Each entry reports compatibility, artifact installation, inference runtime readiness, integrity verification, and whether inference has actually been validated on that installation. All seventeen reviewed FluidVoice selections have an installation and adapter path. **Fluid Speech Pico uses its verified public publisher archive**; its download no longer has the incorrect distribution gate. Its weight-license metadata remains unresolved, and Olenji does not bundle its weights. Exact Apple/Core ML selections require supported Apple hardware and operating-system APIs; native execution still needs Mac validation. Olenji will not report a complete parity installation when it skipped an incompatible entry. The current parity profiles follow this reviewed set; `fluidvoice-2026-10-22` preserves the original sixteen-model membership.

The installer reports OS, interpreter architecture, Python version and backend requirements before downloading. Faster Whisper on Intel macOS uses its compatible pinned ONNX Runtime; Fluid Mini ONNX is explicitly blocked there because the required graph operators have no reviewed Intel binary. Native Windows ARM64 Python can use the available ONNX routes; Faster Whisper needs x64 Python under emulation, while transcribe.cpp requires its explicit pinned source-build toolchain. These constraints do not remove or relabel catalog identities.

Downloads resume after interruption, resolve immutable publisher revisions where available, verify artifact digests, and promote a completed inventory atomically. Model leases prevent removal during inference. Optional backends install into managed environments rather than modifying the user's global Python installation. Interrupted or damaged Python runtimes are repaired in a fresh generation, activated only after import/version checks pass. Existing workers retain their previous environment; failed or cancelled repair leaves the selected runtime intact. Old successful generations are retained until an operator can safely reclaim them with all workspace processes stopped. The tiny defaults are convenient for a first run. Benchmark candidate models on your languages and hardware before choosing a quality/performance trade-off.

Inference checks artifact identity and integrity before reusing installed weights. An unchanged installation uses a bounded verification cache; replaced or modified files invalidate it and the warm engine cache. Worker protocol buffers and shutdown paths are bounded, so a stalled or noisy backend cannot accumulate unlimited transcript output or keep cancellation waiting on an inherited pipe.

```sh
olenji models inspect whisper.tiny.q8_0 --json
olenji models parity --json
olenji models verify faster-whisper.tiny --json
olenji models remove faster-whisper.tiny --json
```

Use `models list` for canonical IDs; aliases can vary by family. Apple locale assets can be requested explicitly with `models install MODEL_ID --language tr-TR` on supported systems.

### Choose inference settings through your agent

`models inspect` exposes the options accepted by each backend. File transcription, live capture and refinement share the same CLI flags and structured API/MCP `inference` object:

```sh
olenji models inspect faster-whisper.tiny --json
olenji transcribe meeting.mp4 --model faster-whisper.tiny \
  --device cpu --compute-type int8 --cpu-threads 2 --json
olenji live start --source microphone --model faster-whisper.small \
  --device cuda --compute-type float16 --open --json
olenji sessions refine SESSION_ID --inference '{}' --json
```

The CUDA example requires a working compatible GPU runtime. Unsupported fields, devices and precisions return an explicit error. Accepted settings are recorded with the session and each recognized turn. Omitted settings preserve existing adapter defaults; an explicit `{}` resets refinement settings, while omission inherits them when the backend is unchanged. Benchmark thread counts on the intended audio and hardware; more threads can be slower on small models. See [inference controls and reproducible measurements](docs/INFERENCE_OPTIONS.md) and the [dated competitor review](docs/COMPETITIVE_REVIEW.md).

## Live transcription and speakers

```sh
olenji live sources --json
olenji models install diarization.wespeaker.en
olenji live start --source microphone --model faster-whisper.tiny \
  --diarize --retain-audio --open --json
olenji tui SESSION_ID --translation tr
olenji live pause SESSION_ID
olenji live resume SESSION_ID
olenji live stop SESSION_ID
```

The live pipeline uses bounded queues, voice activity endpointing, partial previews, committed turns, pause/resume timing, capture gap reporting, and a final flush job. A model's native streaming capability and Olenji's buffered live mode are reported separately. With many file-oriented models, live text uses short buffered recognition windows; it is not falsely advertised as native incremental decoding.

`doctor` reports current job/source capacity. Ordinary jobs are limited to 16 times `max_parallel_jobs`; eight live sources may be owned at once. Finalization remains admissible when ordinary work is full. Browser worklet delivery is bounded, and discarded audio is recorded as an explicit measured gap. Audio accepted for retention is drained when capture is cancelled; cancellation does not replace queued recorded speech with silence.

Speaker attribution uses acoustic embeddings and clustering. Labels such as **Speaker 1** are anonymous acoustic clusters; Olenji does not know a person's identity. Short, noisy or overlapping speech may remain unknown. You or your agent can correct labels, colors and assignments, merge speakers, split or merge adjacent transcript turns, and inspect edit history. Source edits require a revision precondition.

Speaker merges remain effective while recognition continues: later turns follow the surviving speaker, including a chain of earlier merges. Existing source revisions and human translations retain their normal edit/staleness rules. Pause, resume and finalization publish recording state in control order, so an overlapping pause cannot leave a finished recording marked as paused.

Sources:

| Source | Behavior |
|---|---|
| Microphone | Service-owned capture through sounddevice/PortAudio, subject to OS permission |
| Browser microphone | AudioWorklet float32 PCM; user grants microphone permission in the paired tab |
| Linux system audio | PulseAudio/PipeWire monitor through FFmpeg when available |
| Windows system audio | WASAPI loopback through SoundCard, included in the default Windows install; capture runs in an owned, cancellable subprocess |
| macOS system audio | Bundled ScreenCaptureKit helper, compiled locally; requires screen/system-audio permission |

Run `live sources` to inspect actual prerequisites. Closing a browser supplying microphone audio ends that source and flushes committed text. Closing a browser that only views native capture does not stop it.

The terminal view fits the newest speech and translation to the available height, with speaker labels, visibly provisional drafts, audio level and capture/reconnection status. Multi-turn translations name their full source span and speakers. Closing the viewer leaves capture ownership unchanged. `olenji tui SESSION_ID --json` returns one bounded snapshot; redirected stdout defaults to the same machine output. Use `events --follow --jsonl` for a machine stream. See [terminal behavior](docs/TERMINAL.md).

Browser views open a bounded 200-turn window, with whole connected translation context and separate notes/speaker pages. Search covers the entire session, including the selected translation language. Earlier/later navigation and playback seeks replace the window; they do not accumulate the transcript in browser memory. Small complete windows retain incremental updates; filtered or partial windows reload consistently at their event cursor. See [bounded browser windows](docs/BROWSER_WINDOWS.md) for limits and [current verification](docs/VALIDATION.md) for measurements.

## Translation: your agent or a configured model

Your existing agent can read committed turns and write translations itself. No second LLM is required in Olenji for that workflow:

```json
{
  "translations": [{
    "source_refs": [{"segment_id": "SEGMENT_ID", "revision": 1}],
    "target_language": "tr",
    "text": "Merhaba, bugün ne üzerinde çalışıyoruz?",
    "producer": {"kind": "external_agent", "name": "your-agent"}
  }]
}
```

```sh
olenji translations put SESSION_ID --file translations.json --json
olenji sessions window SESSION_ID --query '{"limit":50,"target_language":"tr","committed_only":true}' --json
olenji events SESSION_ID --after 0 --follow --committed-only --jsonl
```

Translations are separate tracks with exact source revision references. If source text or attribution changes, affected translations become stale. Readable exports omit stale translations. Human-marked corrections are preserved against automatic overwrites.

An agent resuming work should read `sessions window` or the MCP tool `olenji_session_window` to obtain existing translations and their full source context. Only `window_ids` are selected display turns; other returned source rows preserve indivisible translation groups. Pin later pages with `expected_cursor` and restart on `SNAPSHOT_CHANGED`.

A translation covering several turns remains one sentence group. A replacement that overlaps that group supersedes it as a whole, and automatic output cannot bypass a human correction by changing the grouping. Bilingual subtitle cues span the complete source group and retain each original speaker's words. JSON and JSONL exports include all original tracks, speaker labels, notes, provenance and stale records for further processing; readable formats apply the requested language selection. Markdown exports preserve transcript text literally, including text that resembles HTML or Markdown links.

For automatic translation, connect an OpenAI-compatible **local** endpoint, for example a model already served by Ollama, LM Studio, or another local inference service:

```sh
olenji providers add local --base-url http://127.0.0.1:11434/v1 --model YOUR_LOCAL_MODEL
olenji translate SESSION_ID --to tr --provider local --json
olenji sessions configure SESSION_ID --metadata \
  '{"auto_translate":true,"translation_language":"tr","translation_provider":"local"}'
```

Automatic live translation coalesces new committed turns, skips current translations, and records provider failures without stopping recording. Configure provider API keys with `--api-key-env VARIABLE_NAME` or `--api-key-stdin`; keys are never returned by the public API. The current implementation stores provider credentials in a permission-restricted local file, not an OS keychain.

An agent can change the selected translation language while work is queued or running. Older automatic or manual work may complete its own source-linked track, but cannot overwrite a later explicit language selection. Automatic work observes the latest preference on its next coalesced pass. Source appended through MCP or the local API also starts enabled translation, and another source turn can arrive while translation is running.

Retryable automatic failures receive up to three delayed retries after 30, 60 and 120 seconds, without waiting for more speech. Pending work survives service restart; recording itself never restarts. Permanent errors or an exhausted retry budget remain blocked until the provider is repaired or translation is explicitly re-enabled/reconfigured. The browser, terminal and session metadata distinguish a scheduled retry from work that needs attention. A one-off `translate` command remains independent of the automatic retry budget. See [translation recovery](docs/TRANSLATION_RECOVERY.md) for cancellation, privacy, restart and capacity behavior.

Explicit API base paths are preserved, including Gemini's `/v1beta/openai` route; a bare origin uses `/v1/chat/completions`. Complete chat-completions URLs are also accepted. Olenji does not force a sampling temperature that a provider/model may reject. [Provider compatibility](docs/PROVIDER_COMPATIBILITY.md) maps the public FluidVoice provider choices, local services and supported protocol boundaries.

Sessions default to **local-only**. A remote provider requires HTTPS and an explicit session choice such as `transcribe ... --allow-cloud` or `sessions configure ... --metadata '{"local_only":false}'`. Redirects and endpoint overrides cannot silently move a configured credential to another host. An external agent's own processing policies are separate from Olenji's local process boundary.

## Browser presentation

The bundled UI has six layouts:

- **Conversation:** readable speaker turns, timestamps, live drafts and notes.
- **Bilingual:** source and target text together, with independent text scales.
- **Captions:** a quiet large-text view for following speech.
- **Review:** corrections, speaker assignment, revision history, split/merge and playback.
- **Timeline:** time-oriented navigation through the session.
- **Operations:** capture and job state, processing progress and errors.

Views can filter selected speakers or dynamically follow the most recent speakers, change typography, hide/show source or translations, seek playback, search text, and follow live or playback position. The API stores a desired revision. The browser acknowledges the revision it actually applied and its visibility state. An agent can tell “configuration requested” from “the tab rendered it.” No arbitrary HTML or JavaScript is accepted as a view instruction.

Browser playback uses retained normalized WAV audio for reliable codecs and HTTP byte ranges. Retention is opt-in through a command or a saved preference. Non-retained uploads and temporary decoding files are removed after work completes; original local files provided by path are never deleted. Refinement needs retained audio and preserves user-edited regions. If new recognition boundaries cross a protected edit, Olenji keeps the entire conflicting source region and reports `preserved_machine_segments`, so neighboring speech is not lost. Notes remain attached to temporally overlapping replacement turns.

## MCP configuration

Add this stdio server to an agent client that supports MCP:

```json
{
  "mcpServers": {
    "olenji": {
      "command": "olenji",
      "args": ["mcp", "serve"]
    }
  }
}
```

The adapter exposes **41 tools** for discovery, model planning/install/verification/removal, durable jobs, file/live transcription, bounded event/segment/translation-context reads, session configuration, source editing/history/split/merge, refinement, source-linked translations, provider configuration, speaker labels/merging, annotations, browser control and exports. Relative media paths resolve from the calling agent's working directory. It supports stateless **MCP 2026-07-28** requests and legacy initialization for 2025-11-25, 2025-06-18, 2025-03-26 and 2024-11-05 clients. Nested inputs are validated against their JSON Schema, and creation/job-start tools accept an optional per-call `idempotency_key`. Structured results occupy stdout. The adapter returns transcript content as data without embedded tool execution; an agent consuming it must preserve its own instruction hierarchy.

## Storage, service, and privacy

State defaults to the OS application-data directory. Override it with `--data-dir PATH` or `OLENJI_DATA_DIR`. SQLite WAL stores sessions, speakers, transcript revisions, translations, annotations, durable jobs, views and replayable events. Media and model artifacts live beside the database in separate directories.

```sh
olenji service status --json
olenji service logs
olenji service stop
olenji serve --port 8765
```

The service binds only to loopback. Requests validate Host and Origin; the CLI uses a protected local bearer token and the browser uses an HttpOnly SameSite cookie obtained from a short-lived one-use pairing link. Cookie names are scoped to the workspace so multiple local instances do not overwrite one another's login. Optional ONNX Runtime and Hugging Face telemetry is disabled before inference-library initialization. There is no public hosting mode in this version. Use explicit SSH tunnelling for an independently managed remote machine.

After a crash, already committed text remains available. Interrupted recordings and ordinary jobs are marked interrupted/failed; recording never restarts automatically. Previously owned, still-enabled automatic translation may continue through a new job under its persisted retry policy. Historical job outcomes remain available. Event cursors allow agents and browser views to replay committed changes. `sessions delete` removes a session's database rows, recorded event payloads, owned media and jobs. Deletion is a logical application deletion, not a guarantee of forensic erasure from database journals, backups or the storage device.

Agents can pin multi-page reads with `segments list --expected-cursor`. A changed source snapshot returns `SNAPSHOT_CHANGED` instead of skipping or duplicating turns. Event followers receive a `stream.reset` frame when their checkpoint is ahead of a restored database; they should refresh the snapshot and resume from its cursor. CLI, MCP, model workers and JSON imports preserve UTF-8 text independently of the terminal's codepage.

Job waits and event followers can establish the local service once before their observation timer starts. Subsequent polls verify the existing workspace and application version without starting a replacement daemon. A wait timeout stops observation and leaves the underlying job intact; resume it by job ID. Network budgets shrink with the remaining observation time, and expired responses are not accepted as successful completion. [Observer recovery](docs/OBSERVER_RECOVERY.md) covers checkpoints, response budgets and the synchronous timeout boundary.

Idempotency keys are reserved durably before side effects. If a service interruption prevents saving the response, retrying that key returns `IDEMPOTENCY_INCOMPLETE`; inspect existing sessions/jobs before deliberately starting new work. This avoids silently duplicating a recording or download whose outcome is uncertain.

Definite capacity rejections (`JOB_QUEUE_FULL` and `CAPTURE_CAPACITY`) admit no work and release their request reservation, so an agent can retry the same key after capacity returns. Temporary uploads and newly created unstarted sessions are removed on those paths.

Exports use a consistent database read and incremental encoding for all seven formats. Downloads are prepared on private disk storage, then streamed without holding the database snapshot open for a slow client. CLI/MCP destination writes are atomic; an interrupted transfer preserves an existing file. Browser downloads use native download links with the paired cookie. Temporary exports expire, are revoked when their session is deleted, and are removed after use. See [sustained-use improvements](docs/RESILIENCE.md) for the measured memory reduction and exact limits.

## Development and verification

```sh
uv sync --frozen --extra dev
uv run --frozen --extra dev --group quality python scripts/check_quality.py
uv run --frozen --extra dev pytest
uv run --frozen --extra dev --group release python scripts/build_release.py
npm --prefix packages/npm test
# Frontend DOM verification:
npm --prefix tests/browser ci --ignore-scripts
npm --prefix tests/browser test
```

Start with [product acceptance](docs/PRODUCT_ACCEPTANCE.md) for the original requirements and their evidence, [docs/HANDOFF.md](docs/HANDOFF.md) for continuing development, [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for language/process decisions and [docs/RELEASING.md](docs/RELEASING.md) for packaging and future publication. The builder verifies wheel contents, rebuilds the same wheel from the source archive, stages the npm package and writes checksummed artifacts; it does not publish.

See [docs/VALIDATION.md](docs/VALIDATION.md) for executed checks and [docs/NATIVE_HANDOFF.md](docs/NATIVE_HANDOFF.md) for hardware validation. Earlier reports remain in [docs/RESILIENCE.md](docs/RESILIENCE.md), [docs/DEEP_HARDENING.md](docs/DEEP_HARDENING.md), [docs/HOLISTIC_AUDIT.md](docs/HOLISTIC_AUDIT.md) and [docs/AUDIT.md](docs/AUDIT.md). The source includes frozen dependencies, a reviewed Swift dependency lock, Python/native installed-wheel CI and browser, Swift and distribution jobs. Remote CI is configured but has not been executed in this workspace. Tests distinguish controlled fixtures from genuine downloaded-model inference. Native capture permissions, Apple APIs and Windows WASAPI need the corresponding hardware and OS to validate. Model availability and rights are not changed by a registry entry.

## Contributing and maintenance

Start with [CONTRIBUTING.md](CONTRIBUTING.md) for setup, focused checks and review expectations. The source includes issue/PR templates, a pinned read-only quality command and dependency-update configuration. [CHANGELOG.md](CHANGELOG.md) records notable changes; `1.0.0` remains an unreleased development build until a public release is actually published.

Use [SECURITY.md](SECURITY.md) for suspected vulnerabilities and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for community behavior. [The security model](docs/SECURITY_MODEL.md) explains actual trust and data boundaries. The repository owner still needs to configure real monitored reporting contacts and hosted repository protections; [MAINTAINING.md](docs/MAINTAINING.md) is the operational handoff.

## Project structure

| Area | Files |
|---|---|
| CLI, agent transport, background service | `olenji/cli.py`, `client.py`, `mcp.py`, `service.py` |
| Versioned API and persistent state | `olenji/app.py`, `schemas.py`, `store.py`, `runtime.py`, `config.py` |
| Models and runtimes | `olenji/catalog.py`, `models.py`, `engines.py`, `engine_worker.py`, `native/apple/` |
| Audio and language pipeline | `olenji/audio.py`, `pipeline.py`, `diarization.py`, `translations.py` |
| Browser and exports | `olenji/web/`, `olenji/exports.py` |
| npm launcher and explicit runtime setup | `packages/npm/` |
| Canonical packaging, artifact verification and release handoff | `scripts/build_release.py`, `pyproject.toml`, `docs/RELEASING.md` |

Olenji's original application code is licensed under Apache-2.0. Downloaded model weights, optional backends and operating-system APIs keep their own licenses and terms. See [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).

## Read the built-in handbook

Use `olenji docs --open` to read the installed offline handbook. Use
`olenji docs --list` to find topic IDs, or add `--section ID` to open one topic.
Without `--open`, the command only prints a local link. `--json` returns the link
and section list for agents. These commands do not create a workspace, start the
service, download a model, or contact a website. In a running browser workspace,
select **Help and handbook** to open the same document in a separate tab.

Contributors maintain the handbook in `docs/handbook/chapters/`. See
[the integrated-help handoff](docs/OFFLINE_HELP_UPDATE.md) for this source branch,
its validation scope, and the exact base from which it was built.
