Metadata-Version: 2.5
Name: latris
Version: 0.3.2
Summary: Latris — an AI-assisted, evidence-native causal-modelling workbench (Python CLI + server backend).
Project-URL: Homepage, https://latris.app
Project-URL: Repository, https://github.com/Shannon-Bengtson/latris
Author: Shannon Bengtson
License: Apache-2.0
License-File: LICENSE
Keywords: bayesian,causal,cld,evidence,git,latris,modelling,provenance,systems-thinking
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: OS Independent
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Visualization
Requires-Python: >=3.11
Requires-Dist: bibtexparser<2,>=1.4
Requires-Dist: click>=8.2
Requires-Dist: httpx>=0.28
Requires-Dist: instructor>=1.3
Requires-Dist: jinja2>=3.1
Requires-Dist: keyring>=25
Requires-Dist: litellm>=1.40
Requires-Dist: pydantic>=2.6
Requires-Dist: python-docx>=1.1
Requires-Dist: python-ulid>=2.2
Requires-Dist: rich>=13.7
Requires-Dist: ruamel-yaml>=0.18
Requires-Dist: typer>=0.26
Provides-Extra: data
Requires-Dist: pandas>=2.0; extra == 'data'
Requires-Dist: scipy>=1.11; extra == 'data'
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest-rerunfailures>=14; extra == 'dev'
Requires-Dist: pytest-xdist>=3.5; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Provides-Extra: quant
Requires-Dist: pgmpy>=1.1; extra == 'quant'
Provides-Extra: server
Requires-Dist: fastapi>=0.115; extra == 'server'
Requires-Dist: pandas>=2.0; extra == 'server'
Requires-Dist: pgmpy>=1.1; extra == 'server'
Requires-Dist: python-multipart>=0.0.7; extra == 'server'
Requires-Dist: scipy>=1.11; extra == 'server'
Requires-Dist: uvicorn[standard]>=0.34; extra == 'server'
Requires-Dist: watchfiles>=1.0; extra == 'server'
Description-Content-Type: text/markdown

# Latris

**Structure for defensible reasoning.**

Latris is an evidence-native modelling workbench for building defensible
causal and systems models — structured provenance, challenge workflows,
git-native versioning, AI-assisted drafting under human approval, and
report generation.

This repository is the open-source core: the Python package (`latris`),
its CLI, and the FastAPI + WebSocket server backend. The Latris desktop
app (React + Electron) is built on top of this package from a separate
private repository.

**New here?** The Latris product — a desktop app for modellers and for
the people who must weigh in on their models — lives at
[latris.app](https://latris.app) (invite-only early access). This
repository is the open backend that powers it.

- Every modelling project is a **git repo** — every change is an
  inspectable, reversible commit.
- Evidence and provenance are **first-class data**, not annotations:
  citations, assumptions, decisions, challenges, sign-offs.
- AI assistance returns **structured proposals**, never free-form
  mutations; a human approves before anything commits.
- One substrate, many formalisms: qualitative CLD/DAG views today, a
  built-in discrete **Bayesian Network engine** (state spaces, CPTs with
  per-cell provenance, exact inference, parameter learning), and more
  views on the architecture's path.

Status: **alpha** (0.3.1). Apache-2.0 licensed.

## Prerequisites

- **Python 3.11+** on PATH
- **git 2.40+** on PATH, with `user.name` and `user.email` configured
  globally (Latris commits as you, and enforces that identity)

## Install

From PyPI:

```bash
pip install "latris[server,data]"
latris --version
latris doctor          # verify git + identity
```

From source:

```bash
git clone https://github.com/Shannon-Bengtson/latris.git
cd latris
python -m venv .venv
# Windows: .venv\Scripts\activate   —   mac/linux: source .venv/bin/activate
pip install -e ".[server,data,dev]"
latris doctor
```

Optional extras:

| Extra | Brings in | For |
|-------|-----------|-----|
| `server` | FastAPI, uvicorn, pandas, scipy, pgmpy | The API server (`python -m latris.server`) |
| `data` | pandas, scipy | Dataset wrangling and statistics |
| `quant` | pgmpy | Quantitative inference (also in `server`) |
| `dev` | pytest, xdist, ruff, build | Running the test suite |

## Quickstart

```bash
# 1. Create a project (a git repo with the full model structure)
latris init air-quality --question "What drives urban air quality?"

cd air-quality

# 2. Build a model: nodes, then edges
latris node add "Traffic volume" --kind variable
latris node add "NO2 concentration" --kind variable
latris edge add <traffic-id> <no2-id> --kind causal

# 3. Inspect — every step above was a git commit
latris status
latris log

# 4. Export
latris export md --output reports/report.md
latris export dot --view cld --output reports/model.dot
```

The full command catalogue is in
[`docs/engineering/CLI_REFERENCE.md`](docs/engineering/CLI_REFERENCE.md).

## Run the API server

```bash
python -m latris.server --project-root ./air-quality
```

Serves the full CRUD/AI/export API on **http://127.0.0.1:8741** (the
same backend the Latris desktop app embeds). `--help` lists flags.

## AI layer (bring your own key — or your own agent)

AI calls go through a vendor-agnostic adapter (litellm + instructor);
secrets live in your OS keyring, never on disk:

```bash
latris ai key set anthropic      # or openai / gemini / groq / ...
latris ai config show            # default model lives in .graph-tooling/ai_config.yaml
```

Set `LATRIS_AI_MOCK=1` to stub all AI calls (used by the test suite and
CI; the pre-rename `GRAPH_TOOLING_AI_MOCK` is still honoured for one
release).

Working from an agent (Claude Code, Kimi, …) with no API key?
`latris ai task emit <prompt> --inputs '<json>'` produces a self-contained
task package your agent can answer; `latris ai task apply --task task.json
--from response.json` ingests the answer through the same human-approval
pipeline (recorded as `external-agent`). See
[docs/engineering/AI_LAYER.md](docs/engineering/AI_LAYER.md).

## Tests

```bash
python -m pytest              # full suite, parallel via pytest-xdist
python -m pytest -n0          # serial, for clean tracebacks
python -m pytest tests/test_worked_example.py --slow   # acceptance test (regenerates the transcript)
```

## Documentation

- [`docs/README.md`](docs/README.md) — documentation index
- [`docs/engineering/ARCHITECTURE.md`](docs/engineering/ARCHITECTURE.md) — how it's built
- [`docs/engineering/CLI_REFERENCE.md`](docs/engineering/CLI_REFERENCE.md) — command catalogue
- [`worked_example/worked_example_output.md`](worked_example/worked_example_output.md) — a full end-to-end session transcript
- [`llms.txt`](llms.txt) — machine-readable doc map for AI agents

## License

[Apache-2.0](LICENSE) — Copyright (c) 2026 Shannon Bengtson.

---

## For AI agents

You are working with **Latris**, an evidence-native causal-modelling
CLI + API server. Treat the engineering docs as the source of truth:
start from [`llms.txt`](llms.txt) and
[`docs/README.md`](docs/README.md).

**You can be the model.** If no API key is configured, don't stop — any
of the 46 AI prompts can be delegated to you:
`latris ai task emit <PromptName> --inputs '<json>'` writes a task
package (prompt + project context + response schema); answer it as
JSON, then the human runs
`latris ai task apply --task task.json --from response.json`. Same
approval gates; the interaction is recorded as `external-agent`. See
[AI_LAYER.md](docs/engineering/AI_LAYER.md) § "Delegated calls".

**Check what's actually available before recommending a specific model
type.** `latris capabilities` (or `latris capabilities --json`) lists
every registered model type with `can_use_today: true/false`. Only
`cld`, `dag`, `bn`, and `fcm` are stable/switchable today; the rest
(`theory_of_change`, `sd`, `gsn`, and 13 others) are registered but not
yet switchable — `latris view project <kind>` raises a `ValueError` if
`kind` isn't stable. A few categories (black-box ML) are excluded by
design, not "not yet." Run this before telling a user Latris can build
them a specific kind of model.

**Moving a project online so a human can see it in a browser.** If it'd
help the person you're working with to view or share the model at
`https://app.latris.app` instead of just reading your terminal output,
walk them through `latris sync login --email <their email>` (sends a
one-time code — ask them what it was, then run it again with `--code`),
then `latris sync share "<project name>"`. That prints the exact link to
open. No desktop install needed on their end.

Setup (one shot):

```bash
pip install "latris[server,data]"
```

Minimal working session (init → node → edge → export → history):

```bash
latris init demo --question "Does X cause Y in context Z?"
cd demo
latris node add "X" --kind variable
latris node add "Y" --kind variable
latris edge add <x-id> <y-id> --kind causal   # IDs from the node add output
latris export md --output reports/report.md
latris log                                     # every mutation is a git commit
```

The complete, always-current demonstration of every command is the
worked example:
[`worked_example/worked_example_output.md`](worked_example/worked_example_output.md)
(generated by `worked_example/worked_example.py`; the generator is the
repo's acceptance test). Read it before asking the user how the tool
behaves — and after changing CLI behaviour, regenerate it
(`pytest tests/test_worked_example.py --slow`) and commit the updated
transcript.

Hard rules when modifying this repo: no business logic in `cli/` (one
parse + one call into `operations/` + one print); respect the five
chokepoints (`repo/git.py`, `repo/yaml_io.py`, `repo/layout.py`,
`operations/commit.py`, `schema/ids.py`); no AI-authored commits; no
secrets on disk. See [`CLAUDE.md`](CLAUDE.md) and
[`src/latris/CLAUDE.md`](src/latris/CLAUDE.md).
