From bea79c43a54f2391ce5eb6e598a52fcc8033b099 Mon Sep 17 00:00:00 2001 From: Luca Ostinelli Date: Fri, 16 Oct 2026 12:46:40 -0500 Subject: [PATCH 1/2] chore(ci): add the CI workflow with a single quality gate and Dependabot Every pull request and every push to main runs four jobs: - lint: ruff check and format; - typecheck: mypy; - import-contracts: import-linter; - test: pytest with coverage, plus a markdown coverage summary. The quality-gate job aggregates them and fails if any of them did not succeed. It is meant to be the only required status check. Dependabot updates uv dependencies and GitHub Actions weekly on Mondays (Europe/Rome). Minor and patch updates are grouped, and major updates arrive as separate PRs. Refs #4 --- .github/dependabot.yml | 25 +++++++++++++ .github/workflows/ci.yml | 79 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/ci.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..d31f593 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,25 @@ +version: 2 +updates: + - package-ecosystem: "uv" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + timezone: "Europe/Rome" + commit-message: + prefix: "chore(deps)" + groups: + python-minor-patch: + update-types: ["minor", "patch"] + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + timezone: "Europe/Rome" + commit-message: + prefix: "chore(ci)" + groups: + actions-minor-patch: + update-types: ["minor", "patch"] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9b6f91c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,79 @@ +name: CI + +on: + pull_request: + push: + branches: [main] + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - uses: astral-sh/setup-uv@v6 + with: + enable-cache: true + - run: uv sync --locked + - name: Ruff lint + run: uv run ruff check . + - name: Ruff format + run: uv run ruff format --check . + + typecheck: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - uses: astral-sh/setup-uv@v6 + with: + enable-cache: true + - run: uv sync --locked + - name: mypy + run: uv run mypy + + import-contracts: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - uses: astral-sh/setup-uv@v6 + with: + enable-cache: true + - run: uv sync --locked + - name: import-linter + run: uv run lint-imports + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - uses: astral-sh/setup-uv@v6 + with: + enable-cache: true + - run: uv sync --locked + - name: pytest + run: uv run pytest + - name: Coverage summary + if: always() + run: uv run coverage report --format=markdown >> "$GITHUB_STEP_SUMMARY" + + quality-gate: + if: always() + needs: [lint, typecheck, import-contracts, test] + runs-on: ubuntu-latest + steps: + - name: Fail unless every required job succeeded + if: >- + contains(needs.*.result, 'failure') || + contains(needs.*.result, 'cancelled') || + contains(needs.*.result, 'skipped') + run: | + echo "Required job results: ${{ join(needs.*.result, ', ') }}" + exit 1 + - name: All required jobs succeeded + run: echo "quality-gate passed" From 2790f041f6514ce6f6dc38ac6ff5012d529cd561 Mon Sep 17 00:00:00 2001 From: Luca Ostinelli Date: Fri, 16 Oct 2026 12:52:23 -0500 Subject: [PATCH 2/2] docs: add contributor guide, agent instructions, architecture overview and CODEOWNERS A new contributor can now go from cloning the repository to a merged PR by reading the repository docs alone. - CONTRIBUTING.md encodes every convention from spec section 9: - setup and the quality checks; - the board workflow and the Definition of Ready; - branch naming, Conventional Commits and the scope list; - pull request and merge rules, including the eval block for retrieval changes; - when an ADR is required; - porting from Academy; - labels and cadence. - AGENTS.md condenses the same rules for automated contributors. - docs/architecture.md gives a one-page map of the packages, layers, data flow and tracks. - CODEOWNERS routes reviews to @BitPolito/ai-ml, and ADRs to the lead maintainer. - README gains a quick start and links to the docs. Refs #5 --- .github/CODEOWNERS | 5 ++ AGENTS.md | 41 +++++++++++++ CONTRIBUTING.md | 140 +++++++++++++++++++++++++++++++++++++++++++ README.md | 18 +++++- docs/architecture.md | 67 +++++++++++++++++++++ 5 files changed, 269 insertions(+), 2 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 AGENTS.md create mode 100644 CONTRIBUTING.md create mode 100644 docs/architecture.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..f89d67e --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# Default owners: the BitPolito AI/ML team. +* @BitPolito/ai-ml + +# Architecture decisions are approved by the lead maintainer. +/docs/adr/ @lucaosti diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..b371d48 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,41 @@ +# Instructions for automated contributors + +These rules apply to any coding agent that works in this repository. Humans should read `CONTRIBUTING.md`, which these rules condense. + +## Before you write code + +1. Read the issue completely: Goal, Scope, Out of scope, Files, Acceptance criteria, How to verify. +2. Read `docs/specs/2026-10-16-agentic-rag-design.md`, at least sections 4, 5 and 9, and every ADR the issue references in `docs/adr/`. +3. If the issue is ambiguous or contradicts the spec, comment on the issue and stop. Do not guess. + +## While you work + +- Change only what the issue's Scope covers. Do not refactor, rename or "improve" anything outside it. +- Respect the architecture (ADR-0001): + - core code depends only on `agentic_rag.types` and `agentic_rag.ports`; + - backends live in `agentic_rag.adapters`; + - dependencies are injected through constructors; + - no module-level singletons; + - no `os.getenv` or `os.environ` outside `EngineConfig`. +- Never change a port or a public contract without an accepted ADR. +- Write the tests first. Every acceptance criterion needs a test that proves it. +- All code, comments, docstrings and messages are written in English. Docstrings use the Google style. +- Do not add references to AI tools or assistants, or attribution trailers, in code, docs or commit messages. + +## Before you open a pull request + +Run every check, and the issue's own "How to verify" commands: + +```bash +uv run ruff check . && uv run ruff format --check . +uv run mypy +uv run lint-imports +uv run pytest +``` + +Then: + +- **Branch:** `/-`. +- **Commits:** Conventional Commits, `type(scope): summary`, with a `Refs #` footer. +- **Pull request:** against `main`, filling in the template, with `Closes #`. For retrieval changes, paste the before and after `arag-eval` SUMMARY. +- Never merge your own pull request. A human reviews and merges it. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..7dc602d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,140 @@ +# Contributing to Agentic-RAG + +This guide covers everything you need to go from cloning the repository to getting a pull request merged. The design behind these rules is in `docs/specs/2026-10-16-agentic-rag-design.md`, and the architecture decisions are in `docs/adr/`. + +All code, comments, documentation, issues, commit messages and pull requests are written in **English**. + +## 1. Setup + +You need [uv](https://docs.astral.sh/uv/). uv installs Python 3.11 for you, following `.python-version`. + +```bash +git clone https://github.com/BitPolito/Agentic-RAG.git +cd Agentic-RAG +uv sync +uv run pytest +``` + +Always run project commands through `uv run`, so they use the project's virtual environment. + +## 2. Quality checks + +These are the same checks CI runs. Run them before you push: + +```bash +uv run ruff check . +uv run ruff format --check . +uv run mypy +uv run lint-imports +uv run pytest +``` + +| Check | What it enforces | +|---|---| +| ruff | Lint and formatting, Python 3.11, line length 100, Google-style docstrings. Docstrings are not required in tests. | +| mypy | Strict typing on `packages/`. | +| import-linter | The architecture rules from ADR-0001: types and ports never import adapters; the engine never imports `agentic_rag_code`; engine modules respect the layer order. | +| pytest | Tests with coverage. The build fails below 80%. | + +CI runs every check on each pull request. The `quality-gate` job aggregates them, and it is the only required status check. + +## 3. Picking up work + +1. **Find an issue.** Open the [project board](https://github.com/orgs/BitPolito/projects/23) and choose an issue in the **Ready** column. + - Issues labelled `good first issue` are a good starting point. + - Do not start an issue in **Backlog**. Its blockers are not closed yet. +2. **Claim it.** Assign the issue to yourself and move it to **In progress**. +3. **Read before coding.** Read the issue's Goal, Scope, Out of scope and Acceptance criteria. Read the spec sections and ADRs it references. +4. **Ask early.** If anything is unclear, ask in the issue. Do not guess. + +### Definition of Ready + +An issue is **Ready** only when all of these hold: + +- its acceptance criteria are testable; +- every issue it is blocked by is closed; +- its size is `S`, `M` or `L`. + +Work larger than `L` is turned into an epic with sub-issues. + +## 4. Branches + +- `main` is protected. Never commit to it directly. +- Create one short-lived branch per issue, named `/-`. For example: `feat/12-hybrid-retriever`, `fix/31-bm25-delete`. +- Branch types: `feat`, `fix`, `refactor`, `docs`, `test`, `chore`, `perf`, `research`. +- A branch is deleted after its pull request is merged. + +## 5. Commits + +Use [Conventional Commits](https://www.conventionalcommits.org/), in the form `type(scope): summary`. + +- **Summary:** imperative mood, at most about 72 characters. +- **Body:** explains *why*, when the reason is not obvious. +- **Footer:** `Refs #`. + +Allowed scopes: `engine`, `ingest`, `retrieval`, `evidence`, `generation`, `agent`, `adapters`, `eval`, `code-rag`, `dataset`, `bench`, `qvac`, `ci`, `docs`. + +Example: + +``` +feat(retrieval): add reciprocal rank fusion + +Weighted fusion is sensitive to score scales across backends; RRF is +scale-free and is needed for the QVAC and local stacks to be comparable. + +Refs #18 +``` + +## 6. Pull requests + +1. **Open a draft early.** Open a pull request against `main` as soon as you have something to show. Keep it a draft until it is ready. +2. **Fill in the PR template.** It covers What, Why, `Closes #`, how you verified the change, and reviewer notes. +3. **Keep it small.** Aim for about 400 changed lines or fewer. Split anything larger. +4. **Include eval results for retrieval changes.** If the PR changes retrieval behaviour (ingestion, chunking, search, fusion, reranking or the evidence pack), paste the `arag-eval` SUMMARY block from before and after the change. +5. **Request review.** A review is requested automatically from `@BitPolito/ai-ml` (see `CODEOWNERS`). Move the issue to **In review**. +6. **Address feedback with new commits.** Do not force-push a branch that is under review. +7. **Merge.** A pull request is merged when `quality-gate` is green and it has at least one approval. Always merge with a merge commit, never squash or rebase, and delete the branch: + + ```bash + gh pr merge --merge --delete-branch + ``` + +8. **Close the issue.** `Closes #` in the PR closes the issue automatically. If the PR only covers part of the issue, use `Refs #` and comment on the issue with the progress. + +## 7. Architecture Decision Records + +An ADR in `docs/adr/` is required, before the implementation, for any change to: + +- a port (`agentic_rag.ports`) or a public contract, such as `EvidencePack` or the QVAC HTTP contract; +- the repository layout or the core tooling; +- a technology choice that other code will depend on, such as the vector store or the code graph store. + +Copy the format of an existing ADR. Open it with status **Proposed**. It becomes **Accepted** once its pull request is merged. The lead maintainer approves ADRs. + +## 8. Porting code from BitPolito Academy + +The engine is extracted from `BitPolito/bitcoin-academy` (ADR-0004). When you port code: + +- Copy from the pinned commit named in the backlog (`b78d661`). Record the source in the PR as `Source: bitcoin-academy@ `. +- Port the matching tests together with the code. +- Remove domain-specific code while porting: course and Bitcoin vocabulary, book-specific rules, user-facing strings. Pass these in as configuration instead. +- Do not modify Academy. Its migration is milestone E6. + +## 9. Labels + +| Label | Meaning | +|---|---| +| `type/*` | Kind of change: feature, bug, refactor, docs, test, chore, research. | +| `area/*` | Part of the system: ingest, retrieval, adapters, eval, agent, code-rag, dataset, benchmark, qvac, infra. | +| `track/*` | Foundation (M0–M2), engine (E1–E6) or research (R1–R5). | +| `priority/p0`–`p2` | p0 blocks its milestone, p1 is needed for it, p2 is nice to have. | +| `size/S`, `size/M`, `size/L` | S is up to about half a day, M is one to three days, L is about a week. | +| `status/blocked`, `status/needs-design` | Waiting on something, or needs an ADR first. | +| `epic` | Tracks the sub-issues of a later milestone. | +| `agent-ready` | Precise enough to hand to a coding agent. A human still reviews the resulting PR. | +| `good first issue` | A good starting point for newcomers. | + +## 10. Cadence + +- **Weekly update:** each contributor posts a short async update on their issue or in the team channel, covering done, next and blocked. +- **Milestone review:** when a milestone's exit criteria are met, the team reviews it and the next epic is broken down into issues. diff --git a/README.md b/README.md index f617df4..1e30c87 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,23 @@ Agentic-RAG is a local-first Retrieval-Augmented Generation engine built by the Everything runs locally. The project does not use frontier or hosted commercial models. -## Status +## Quick start -The project is being set up. The design is described in `docs/specs/`, and architecture decisions are recorded in `docs/adr/`. +```bash +git clone https://github.com/BitPolito/Agentic-RAG.git +cd Agentic-RAG +uv sync +uv run pytest +``` + +## Documentation + +- [Contributing guide](CONTRIBUTING.md): workflow, conventions and how to pick up work. +- [Architecture overview](docs/architecture.md): packages, layers and data flow. +- [Design specification](docs/specs/2026-10-16-agentic-rag-design.md): goals, architecture, milestones and conventions. +- [Architecture Decision Records](docs/adr/README.md). +- [Project board](https://github.com/orgs/BitPolito/projects/23). +- Instructions for automated contributors: [AGENTS.md](AGENTS.md). ## License diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..7685367 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,67 @@ +# Architecture overview + +This page is a one-page map of the repository. The full design is in [`docs/specs/2026-10-16-agentic-rag-design.md`](specs/2026-10-16-agentic-rag-design.md), and the decisions are recorded in [`docs/adr/`](adr/README.md). + +## Packages + +| Path | Distribution | Import | Role | +|---|---|---|---| +| `packages/engine` | `agentic-rag` | `agentic_rag` | Domain-agnostic RAG engine: types, ports, pipelines, evidence pack, evaluation, adapters | +| `packages/code-rag` | `agentic-rag-code` | `agentic_rag_code` | AST-aware code retrieval for Python and TypeScript, built on the engine's ports | +| `services/qvac-worker` | none (Node 22) | none | QVAC SDK service used by the `qvac` adapter (ported in milestone E3) | +| `research/` | none | none | Benchmark runners, dataset builders, experiments and the technical report | + +## Engine layers + +Each layer may import only the layers below it. import-linter enforces this in CI. + +``` +agentic_rag.adapters backends behind optional extras (qvac, local, vector, lexical, sql, cache, memory) +agentic_rag.ingest | retrieval | generation | agent | eval +agentic_rag.evidence EvidencePack construction +agentic_rag.ports typing.Protocol interfaces +agentic_rag.types domain-neutral data model +``` + +`agentic_rag` never imports `agentic_rag_code`. The dependency only goes the other way. + +## Data flow + +**Ingestion** + +``` +file -> Parser -> Document(blocks) -> Cleaner -> Chunker -> (parents, children) + -> ParentStore.put_many(parents) + -> Embedder.embed(children) -> VectorStore.upsert + -> LexicalIndex.add(children) + -> IngestResult(stats, section_tree, warnings) +``` + +**Query** + +``` +query -> QueryTransform* -> {VectorStore.search, LexicalIndex.search} -> Fusion + -> Reranker -> MMR -> ParentStore expansion -> EvidencePackBuilder + -> (optional) LLM with strict citation policy -> Answer(evidence, citations) +``` + +## Ports + +The ports are: + +- `Embedder` +- `VectorStore` +- `LexicalIndex` +- `ParentStore` +- `Reranker` +- `LLM` +- `Cache` +- `TokenCounter` + +Their exact signatures are fixed by ADR-0005 (milestone M1). Every port has an in-memory fake in `agentic_rag.adapters.memory`, and a conformance suite that every adapter must pass. + +## Tracks + +- **Foundation (M0–M2):** workspace, contracts and the evaluation harness. +- **Engine (E1–E6):** extract ingestion, retrieval, adapters and the agent runtime from BitPolito Academy, release the engine, then migrate Academy onto it. +- **Research (R1–R5):** code ingestion, code retrieval, the benchmark dataset, the agent and its Task Completion Rate harness, and the technical report.