Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
b30d9c0
Shortened some ARD titles.
sid-ak Jul 2, 2026
c34bbcf
Some more title shortening.
sid-ak Jul 2, 2026
1f9f057
Added useful dev commands.
sid-ak Jul 2, 2026
3dc8b88
#2 Deps for rag_core modules.
sid-ak Jul 2, 2026
fc5fb2f
#2 SQL schema for documents and chunks. Also adds new indexes (HNSW a…
sid-ak Jul 2, 2026
ee64b04
#2 DB config and client impl: CRUD documents/chunks.
sid-ak Jul 2, 2026
467e0b7
#2 Store tests against a test DB, also included in CI.
sid-ak Jul 2, 2026
3f4e066
#2 Store documentation update.
sid-ak Jul 2, 2026
081f8fe
#2 Reflected architectural changes in docs: interfaces, embedder flex…
sid-ak Jul 3, 2026
d54200a
Added TDD as a rule to root AGENTS.md to enforce moving forward.
sid-ak Jul 4, 2026
c1c35f5
Trimmed rag_core AGENTS.md file and recorded the three pass process i…
sid-ak Jul 4, 2026
5c3f016
#2 Defined a StoreProtocol to ADR 0006, backed by pg DB store and an …
sid-ak Jul 4, 2026
544b180
#2 Added parameterized tests for StoreProtocol and an implementation …
sid-ak Jul 4, 2026
a325e8f
#2 Enforced linting rule for docstring presence and made respective c…
sid-ak Jul 4, 2026
cf1bdd2
#2 Documentation updates in accordance with progress made for Phase 1.
sid-ak Jul 4, 2026
a626708
Fix pre commit to run uv workspace so libraries resolve.
sid-ak Jul 7, 2026
c1d6ba8
Updated PR template to add instructions as comments for agents drafti…
sid-ak Jul 7, 2026
a1410ac
Update CodeRabbit configuration and add PR Agent workflow for automat…
sid-ak Jul 7, 2026
f6ebe96
Update CodeRabbit configuration to skip draft reviews and prevent re-…
sid-ak Jul 7, 2026
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
16 changes: 3 additions & 13 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,10 @@ language: en-US

reviews:
profile: chill # fewer, higher-signal comments (the alternative is "assertive")
high_level_summary: true
high_level_summary: false
poem: false
auto_review:
enabled: true
drafts: false
drafts: false # skip drafts; only review once the PR is published/marked ready
auto_incremental_review: false # don't re-review on every new commit
base_branches: [".*"]
path_instructions:
- path: "**/*.py"
instructions: >-
Python 3.12, typed under `mypy --strict` and linted by ruff (rules E,F,I,UP,B,
line length 100). Enforce the project conventions in AGENTS.md and docs/decisions:
retrieval logic lives only in `rag_core`; no top-level `torch` import outside
`embed/` and `rerank/`; relevant tables carry the defaulted `user_id` column.

tools:
ruff:
enabled: true
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
POSTGRES_USER=study
POSTGRES_PASSWORD=change-me
POSTGRES_DB=study_assistant
POSTGRES_TEST_DB=study_assistant_test
POSTGRES_HOST=localhost
POSTGRES_PORT=5432

# Connection string used by the app/services (host networking from the host machine).
DATABASE_URL=postgresql://study:change-me@localhost:5432/study_assistant
TEST_DATABASE_URL=postgresql://study:change-me@localhost:5432/study_assistant_test

# ---- Generation (used in later phases) ----
# Claude is the one hosted dependency; ingestion + retrieval stay on-machine.
Expand Down
39 changes: 37 additions & 2 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,52 @@
# [PR Title]

## Summary

<!-- Two parts, in order:
1. Lead: a high-level 2-3 line overview in plain English — what this branch delivers and why the
pieces hang together. Make it self-contained: a reader shouldn't need to already know the
architecture or internal package/module names (e.g. a bare `rag_core`) to follow it. Don't lean
on an internal identifier to carry the meaning — say what it is in plain terms (name it "the
shared retrieval library" rather than assuming the reader knows `rag_core`). Favor understandable
over exhaustive; don't pad with definitions. No commit hashes here; this is the altitude read.
2. Walkthrough: a bulleted list one level deeper that elaborates the lead. Each bullet names a facet
of the change and cites the commit(s) it traces to by short-hash in parens, e.g. (fc5fb2f) — pull
hashes from the actual commit log, don't invent them. Name the unique or non-obvious parts (a new
protocol, an architectural decision, an automation), not obvious scaffolding (don't give "added
tests" a bullet if tests are just expected). Commits are titled `#<issue> <subject>`; those
without a leading #<issue> (chore/doc housekeeping) usually don't earn their own bullet.
Don't add a separate Changes section — the walkthrough lives here under Summary. Don't mention ADRs
or decision records here; they have their own dedicated section at the end. -->

## Motivation

<!-- Why this change, in a sentence or two — the issue or ADR driving it, not a restatement of the
Summary. -->

## Type

<!-- Check exactly the boxes that fit, based on what the commits actually do. -->

- [ ] Bug
- [ ] Feature
- [ ] Improvement

## Related issues

<!-- Closes #<N> if this branch finishes the issue; Relates to #<N> if it's partial. -->

## Verification

<!-- Numbered, command-first: each item leads with the exact command, then what it confirms.
Items 1 and 2 are the standard CI gate as two umbrellas — don't split the individual
lint/format/typecheck checks into their own points:
1. `pre-commit run --all-files` (hygiene hooks + ruff lint/format + mypy) and the docs build
`uv run sphinx-build -b html docs site -W`.
2. the full test suite `uv run pytest` (with `docker compose up -d` for the DB-backed tests).
Every item after 2 is specific to THIS PR: the exact commands or behaviors that exercise what this
branch actually changed (a new test module, a schema round-trip, a manual repro) — not generic
checks already covered by items 1-2. If you ran them, report pass/fail; if not, present them as the
commands to run before merging. -->

## Decision records / ADRs

<!-- Link any docs/decisions/*.md files this branch touches. If none apply, keep this heading and
leave the section empty. -->
17 changes: 17 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,21 @@ jobs:
checks:
name: Lint, typecheck, test
runs-on: ubuntu-latest
# Integration tests (rag_core/store) run against a real pgvector instance.
services:
postgres:
image: pgvector/pgvector:pg16
env:
POSTGRES_USER: study
POSTGRES_PASSWORD: change-me
POSTGRES_DB: study_assistant_test
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U study -d study_assistant_test"
--health-interval 5s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v5

Expand All @@ -33,6 +48,8 @@ jobs:

- name: Pytest
run: uv run pytest
env:
TEST_DATABASE_URL: postgresql://study:change-me@localhost:5432/study_assistant_test

docs:
name: Docs build
Expand Down
30 changes: 30 additions & 0 deletions .github/workflows/pr_agent.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: PR Agent (Gemini)

on:
pull_request:
types: [opened, reopened, ready_for_review]
Comment thread
coderabbitai[bot] marked this conversation as resolved.
issue_comment:

jobs:
pr_agent_job:
if: ${{ github.event.sender.type != 'Bot' && !github.event.pull_request.draft }}
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
contents: write
checks: write
Comment on lines +12 to +16

@coderabbitai coderabbitai Bot Jul 7, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- .github/workflows/pr_agent.yaml ---'
sed -n '1,220p' .github/workflows/pr_agent.yaml

echo
echo '--- PR Agent references in repo ---'
rg -n "pr-agent|pr_agent|permiss|checks: write|contents: write|pull-requests: write|issues: write" .github README* docs* . || true

echo
echo '--- workflow file list ---'
git ls-files '.github/workflows/*'

Repository: sid-ak/study_assistant

Length of output: 1819


🌐 Web query:

PR Agent GitHub Action required permissions contents write checks write documentation

💡 Result:

To successfully run PR-Agent as a GitHub Action, the standard recommended configuration requires specific permissions to interact with your repository effectively [1][2][3]. The official documentation specifies that your workflow file should include the following permissions block [1][3]: permissions: issues: write pull-requests: write contents: write These permissions are necessary for the bot to perform actions such as posting review comments, updating pull request descriptions, and applying labels [2][4][3]. Important Considerations: 1. Permission Denied Errors: If you encounter a "Permission denied" error during execution, ensure that this permissions block is explicitly defined in your workflow file [1][2][3]. 2. Restricted Mode: If you cannot or do not wish to grant contents: write access, you can enable "restricted mode" in your PR-Agent configuration (setting config.restricted_mode = true) [1]. In this mode, the required permissions are reduced to: permissions: issues: write pull-requests: write 3. Security Context: While these permissions are required for full functionality, be aware that granting write access to the GITHUB_TOKEN allows the action to modify repository components [5][6]. Always follow the principle of least privilege appropriate for your organization's security policies [6]. 4. GitHub App Installation: If you are setting up PR-Agent as a GitHub App (rather than a simple GitHub Action workflow), the required permissions are configured directly in the GitHub App settings, which generally include: - Pull requests: Read & write - Issue comment: Read & write - Metadata: Read-only - Contents: Read-only [2][3]

Citations:


🌐 Web query:

site:github.com qodo-ai pr-agent checks write GitHub Action permissions

💡 Result:

To run Qodo AI PR-Agent as a GitHub Action, your workflow must have specific permissions to interact with your repository, such as posting comments and managing PR information [1][2]. The recommended permissions for the job are as follows [1][2]: permissions: issues: write pull-requests: write contents: write Explanation of Permissions: - issues: write: Required for the agent to post comments on pull requests or issues [1][2]. - pull-requests: write: Necessary for the agent to perform actions on pull requests, such as adding labels, describing the PR, or requesting reviews [1][2]. - contents: write: Often required for actions that involve modifying code or repository contents, though some configurations may work with read-only access depending on the specific features enabled [1][3]. It is important to note that these permissions are applied to the GITHUB_TOKEN provided to the action [1]. If you encounter a "Permission denied" error during execution, verify that these scopes are explicitly defined in your .github/workflows/ YAML file [1]. If you require a more restricted setup, you can experiment with reducing these permissions, but the write-level access listed above is the standard configuration recommended in the official PR-Agent documentation [1][3][2].

Citations:


🌐 Web query:

PR-Agent "checks: write" GitHub Action docs

💡 Result:

When using PR-Agent as a GitHub Action, the "checks: write" permission is required specifically if you want the tool to publish its results—such as reviews, descriptions, or code improvements—as a GitHub Check Run rather than as a standard PR comment [1][2]. To configure this, you must explicitly grant the necessary permission in your GitHub Actions workflow YAML file [3][2]. Example configuration for your workflow file: jobs: pr_agent_job: runs-on: ubuntu-latest permissions: issues: write pull-requests: write contents: write checks: write # Required for publishing results to the Checks tab steps: - name: PR Agent action step uses: the-pr-agent/pr-agent@main env: OPENAI_KEY: ${{ secrets.OPENAI_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} Additionally, you must set the configuration parameter github.publish_as_check_run to true, as the default behavior is to post results as comments [2]. You can set this via environment variables in your workflow or in your.pr_agent.toml configuration file [2][4]. Note: The "checks: write" permission allows the GitHub Action to manage check runs via the GitHub REST API, which is a requirement for integrating with the Checks tab [5][2]. If this permission is missing while the feature is enabled, the action will likely fail due to insufficient privileges [3][6].

Citations:


Drop the unused checks: write scope.

PR Agent’s default GitHub Action setup uses issues: write, pull-requests: write, and contents: write; checks: write is only needed when github.publish_as_check_run is enabled. This workflow doesn’t set that option, so the checks permission can be removed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pr_agent.yaml around lines 12 - 16, The GitHub Actions
permissions block includes an unused checks: write scope, which should be
removed unless github.publish_as_check_run is enabled. Update the permissions in
pr_agent.yaml to keep only the required scopes used by the workflow, and leave
the existing issues, pull-requests, and contents permissions intact.

name: Run PR Agent (Gemini free tier) on pull requests and comments
steps:
- name: PR Agent action step
uses: the-pr-agent/pr-agent@main

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect available immutable refs for PR Agent before choosing a pinned version.
git ls-remote --tags https://github.com/the-pr-agent/pr-agent.git | tail -n 20
git ls-remote https://github.com/the-pr-agent/pr-agent.git refs/heads/main

Repository: sid-ak/study_assistant

Length of output: 1372


🏁 Script executed:

sed -n '1,80p' .github/workflows/pr_agent.yaml | cat -n

Repository: sid-ak/study_assistant

Length of output: 1373


Pin the-pr-agent/pr-agent to an immutable ref. @main is mutable for a third-party action; use a release tag or commit SHA instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pr_agent.yaml at line 20, The workflow currently uses the
third-party action the-pr-agent/pr-agent via a mutable ref, which should be
pinned to an immutable version. Update the uses entry in the pr_agent workflow
to reference a specific release tag or commit SHA instead of main so the action
version cannot change unexpectedly. Keep the change limited to the existing
action reference and ensure the chosen ref is stable and reproducible.

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Free-tier Gemini models via Google AI Studio — no OpenAI cost.
config.model: "gemini/gemini-2.5-flash"
config.fallback_models: '["gemini/gemini-2.5-flash-lite"]'
GOOGLE_AI_STUDIO.GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
# Auto-run on new/updated PRs.
github_action_config.auto_review: "true"
github_action_config.auto_describe: "true"
github_action_config.auto_improve: "true"
12 changes: 8 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ repos:
args: [--fix]
- id: ruff-format

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.14.1
- repo: local
hooks:
- id: mypy
# Match the workspace config; no third-party deps to install yet.
args: [--config-file=pyproject.toml]
name: mypy
# Run the workspace mypy from the uv venv (same as CI's `uv run mypy`) so it resolves
# psycopg / numpy / pytest / pydantic-settings. An isolated mirrors-mypy env can't see those
# third-party deps and fails on import-not-found even when the code typechecks clean.
entry: uv run mypy
language: system
types: [python]
pass_filenames: false
48 changes: 37 additions & 11 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,42 @@ Anthropic API.

- Read [`docs/architecture.md`](docs/architecture.md), it is the full design.
- Read ADRs under [`docs/decisions/`](docs/decisions/), locked decisions live there.
- Read the [GitHub issues](https://github.com/sid-ak/study_assistant/issues), work is tracked as phases there.
- Read the [GitHub issues](https://github.com/sid-ak/study_assistant/issues), work is tracked as
phases there.
- Read [`README.md`](README.md), Status blurb states intent.
- Compare against repo, which is the ground truth.
- Scan with `ls` and compare with directory structure in `architecture.md` to gauge progress.
- Use `git log` to reveal further current progress whether in between phases or mid-phase.
- Fetch the current issue being worked on from the GitHub repo, read its full content.
- Also read the full content of the current issue's sub issues (if any).

## Governance model
## Governance

Canonical context lives in `AGENTS.md` files (tool-neutral). Each `CLAUDE.md` is a one-line
`@AGENTS.md` import stub so Claude Code's directory-walk loading picks up the same content. Edit
`AGENTS.md`, never the stub. Each package/service carries its own scoped `AGENTS.md` describing its
surface; agents read the nearest file in the tree, so the closest one wins. This file is the root
entry point — keep package-specific detail in the package's own `AGENTS.md`.

## Dev environment tips
## Development

- Strict TDD, in three passes (binding, not a preference). For any new feature or issue: pass one
writes tests only — fully describing the expected behavior — with no interface or implementation
code, run and expect red. Pass two defines the interface(s) the code will satisfy — the `Protocol`
types and signatures, per the interface-first architecture
([ADR 0006](docs/decisions/0006-interface-first-architecture.md)) — with no implementation logic.
Pass three adds the implementation behind those interfaces until the tests pass (green). This
applies to both unit and integration tests, per the `@pytest.mark.integration` marker in
`pyproject.toml`.
- As much as possible, write parametrized tests against the protocol. Use the `rag_core` module as
an example.
- Docstrings are mandatory on every module, class, and function repo-wide — including fixtures and
pytest hooks in `conftest.py`. This is machine-enforced: ruff's pydocstyle presence rules
(`D100`–`D107`) run in the same `ruff check` the CI gate uses, so a missing docstring fails the
build. A test's docstring states what behavior it pins; a fixture's states what it provides. Keep
them to one line unless the why is non-obvious.

## Environment

- Python 3.12 on a `uv` workspace. Run `uv sync` once to resolve and install every workspace member
(root + `packages/*`) into a single `.venv`.
Expand All @@ -42,40 +61,47 @@ entry point — keep package-specific detail in the package's own `AGENTS.md`.
- Install hooks once with `pre-commit install`; `pre-commit run --all-files` runs lint + format +
typecheck across the tree.

## Testing instructions
## Testing

- The CI plan is in `.github/workflows/ci.yaml`: a `checks` job (ruff lint, ruff format check, mypy,
pytest against a pgvector service) and a `docs` job that builds the Sphinx site
(`uv run sphinx-build -b html docs site -W`, build-only — deployment lives in `docs-deploy.yaml`).
- Run the whole suite with `uv run pytest`. Integration tests need the database — run
`docker compose up -d` first or they fail to connect.
- Integration tests are marked `@pytest.mark.integration`. Scope a run with
`uv run pytest -m "not integration"` (fast, no DB) or `-m integration` (DB-backed); target one
test with `uv run pytest -k "<name>"`.
- Integration tests are marked `@pytest.mark.integration`. Scope a run with `uv run pytest -m unit`
(fast, no DB) or `-m integration` (DB-backed); target one test with `uv run pytest -k "<name>"`.
The `unit` marker is auto-applied to every non-integration test by the root `conftest.py`, so
`-m unit` always selects the full fast suite — mark only integration tests explicitly.
- Integration tests run against a separate database (`TEST_DATABASE_URL`, e.g.
`study_assistant_test`), never the app's `DATABASE_URL`, and truncate their tables between tests.
`docker compose up -d` remains the only setup step — the test database is created automatically by
`infra/postgres/init.sql` on first init, so a fresh clone needs nothing extra.
- Lint, format, and typecheck must also be green:
`uv run ruff check . && uv run ruff format --check . && uv run mypy`. Fix every error and type
failure until the whole suite is green before you merge.
- Docs must build clean: `uv run sphinx-build -b html docs site -W` (CI runs this too — `-W` turns
Sphinx warnings into errors, catching broken toctrees, anchors, and autodoc import failures).
- Add or update tests for the code you change, even if nobody asked.
- Tests come first, not alongside. Writing or updating tests for the code you change is mandatory
(even if nobody asked), and under the three-pass rule above it happens in pass one — before the
interface or implementation exists — not in the same pass as the code.
- Schema changes need a fresh DB: `initialize_schema()` is `CREATE ... IF NOT EXISTS` and will not
retrofit constraints, so run `docker compose down -v && docker compose up -d` after editing
`store/schema.py`.
Comment on lines 87 to 89

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

4. Root agents.md leaks paths 📘 Rule violation ⚙ Maintainability

Root-level AGENTS.md includes concrete, package-specific implementation references (e.g.,
rag_core and store/schema.py) rather than staying purely cross-cutting. This reduces clarity of
global guidance and should be moved to the package-scoped AGENTS.md.
Agent Prompt
## Issue description
The root `AGENTS.md` contains package-specific implementation details that should live in per-package `AGENTS.md` files.

## Issue Context
Compliance requires the root `AGENTS.md` to avoid concrete instructions scoped to a single package.

## Fix Focus Areas
- AGENTS.md[39-40]
- AGENTS.md[87-89]
- packages/rag_core/AGENTS.md[24-53]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


## Code style
## Style

- `ruff` formats and lints (line length 100, rule set `E,F,I,UP,B`); `mypy` runs in `strict` mode.
Both must pass — do not silence them without cause.
- Type every function signature; `mypy --strict` rejects untyped defs. Prefer explicit, narrow types
over `Any`.

## Binding decisions (ADRs)
## Decisions (ADRs)

The locked architectural decisions are recorded as ADRs, indexed in
[`docs/decisions/`](docs/decisions/). They are binding and the source of truth — read the relevant
ADR before changing what it governs, and do not restate its rules here.

## PR instructions
## PRs

- Branch from `dev`, naming the branch with its GitHub issue number first (e.g. `4-embeddings` for
issue #4) so the branch links back to its issue.
Expand Down
62 changes: 62 additions & 0 deletions CHEATSHEET.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Dev Cheatsheet

## Start the DB

```bash
docker compose up -d
```

## Stop / reset DB (after schema changes)

```bash
docker compose down -v && docker compose up -d
```

## Install deps

```bash
uv sync
```

## Tests

```bash
uv run pytest # everything
uv run pytest -m unit # fast, no DB
uv run pytest -m integration # DB-backed
uv run pytest -k "<test_name>" # one test
```

## Lint / format / typecheck

```bash
uv run ruff check .
uv run ruff format --check .
uv run mypy
```

## Docs preview (clean rebuild + serve)

```bash
rm -rf site && uv run sphinx-build -E -a -b html docs site -W
uv run python -m http.server -d site 8000
```

## Full pre-PR gate

```bash
uv run ruff check . && uv run ruff format --check . && uv run mypy && uv run pytest && uv run sphinx-build -b html docs site -W
```

## DB connection

| Field | Value |
| -------- | --------------- |
| Type | PostgreSQL |
| Host | localhost |
| Port | 5432 |
| Database | study_assistant |
| User | study |
| Password | change-me |

URL: `postgresql://study:change-me@localhost:5432/study_assistant`
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ free; only answer generation calls the Anthropic API.

## Status

Early scaffolding (Phase 0 — Foundations). The repo currently contains the `uv` workspace root, the
shared `packages/rag_core/` library, and the Postgres + pgvector dev stack. Later phases add the
CLI, MCP server, FastAPI backend, and React frontend.
Early scaffolding (Phase 1 — Storage + Schema). The repo contains the `uv` workspace root, the
shared `packages/rag_core/` library with the pgvector storage layer behind a `StoreProtocol`
interface (plus an in-memory fake for DB-free unit tests), and the Postgres + pgvector dev stack.
Later phases add ingestion, retrieval logic, the CLI, MCP server, FastAPI backend, and React
frontend.

## Prerequisites

Expand Down
16 changes: 16 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""Root pytest configuration shared across every workspace package.

Auto-applies the ``unit`` marker to any test not marked ``integration``, so ``uv run pytest -m
unit`` selects the fast, DB-free suite without each test file opting in, and keeps doing so as tests
are added. Integration tests opt in explicitly with ``@pytest.mark.integration`` (or a module-level
``pytestmark``); everything else is unit by default.
"""

import pytest


def pytest_collection_modifyitems(items: list[pytest.Item]) -> None:
"""Tag every collected test lacking the ``integration`` mark with the ``unit`` mark."""
for item in items:
if item.get_closest_marker("integration") is None:
item.add_marker(pytest.mark.unit)
Loading