Skip to content

Workflow & the three contracts

How we make changes. The one rule that governs everything: change the contract before the code. This is Extended Spec-Driven Development (SDD). The full reference is SDD workflow; this page is the practical day-to-day.

The environment

There is one stack — no dev/production split. The app image ships the full toolchain and the repo is bind-mounted, so host edits hot-reload and you never pip install by hand:

make up                               # build + start the stack (CPU-only; no GPU needed)
docker compose exec app make ci       # run the offline gate inside the container

The three contracts

This product has three sources of truth that are protected. Each has a change-it-first rule and a CI gate:

Contract Source of truth After you change it Gate
API specs/openapi.yaml make generate → regenerates Pydantic models make test-contracts (schemathesis)
DB schema Alembic migrations alembic upgrade head make migrate-test (up/down round-trip)
Model/eval set specs/schemas/eval_dataset.schema.json + the eval gate an imported adapter is registered the eval gate (held-out score; CPU gate arrives with E4.3)

Why three and not one: this is self-hosted (you upgrade customers' databases, so migrations are mandatory, not optional) with an adapter core (an unverified adapter must never auto-serve, so the eval gate is a hard gate). See Learning the system for what the eval gate measures.

Recipes

Adding or changing an API endpoint

  1. Edit specs/openapi.yaml first (the SSOT).
  2. make generate — regenerate adapta/models/generated/models.py. Never hand-edit generated files.
  3. Implement the handler in adapta/api/v1/* and the logic in adapta/services/*.
  4. make check-models (drift gate) and make test-contracts (schemathesis against a live server) must pass.

Changing the database schema

  1. Change the ORM in adapta/db/models.py.
  2. Autogenerate a migration, then review it (autogenerated ≠ correct).
  3. make migrate-test — the up→down→up round-trip must pass on seeded data.

Changing the eval set format / the eval gate

  1. The dataset shape is governed by specs/schemas/eval_dataset.schema.json (SFT rows only); the validator is adapta/services/datasets.py. The gate itself returns with E4.3 — see the roadmap.
  2. Don't rewrite the inference engine or the model manager internals — wrap/call them (hard constraint).

The CI gates

Two gates run in .github/workflows/ci.yml:

  • fast (every push, offline, no infra) — check-leaks, lint, lint-imports, coverage (with an enforced floor), validate-spec, check-models, import smoke, console build, and mkdocs build --strict (the docs gate — a broken internal link fails here).
  • full (PR→main and push→main, live stack) — migrate-test, boot smoke, contract tests, integration tests.

Run the fast gate locally before pushing: docker compose exec app make ci.

Definition of done

A change is done only when: (1) the contract changed first if it touched API/schema/model; (2) the relevant gate is green in CI, not just locally; (3) no detail=str(e) was reintroduced (make check-leaks); (4) generated artifacts were regenerated, not hand-edited; (5) docs were updated in the same change.

Console visual documentation

make screenshots and make gif regenerate the screenshots and hero GIF committed to docs/screenshots/. Re-run them whenever you change the console UI — they are the visual changelog for reviewers and users.

Prerequisites (once, on the host):

cd e2e && npm install && npx playwright install chromium
# ffmpeg must be on PATH

Usage (stack must be up):

make console-build  # rebuild adapta/console/dist/ (always needed after source changes)
make screenshots    # console-build + seed + capture 9 PNGs at 1440×900 → docs/screenshots/
make gif            # console-build + seed + record walkthrough → docs/screenshots/hero.gif

make screenshots and make gif both depend on console-build and run it automatically — the console is a compiled Svelte SPA and the container serves the pre-built adapta/console/dist/ directory, so a stale build produces screenshots with stale content. Both seed demo data fresh on each run (wipes existing projects → creates 3). Commit the updated docs/screenshots/ files alongside the console change. These targets are host-only and never run in CI.

Retrieval quality. make golden (live stack, opt-in via ADAPTA_RUN_GOLDEN=1) indexes the bilingual corpus in tests/fixtures/golden/docs, runs every question in questions.jsonl ({q, expected_file, expected_page?, lang}) through retrieve(), prints recall@5, MRR and p50 latency, and fails if recall@5 drops below tests/fixtures/golden/floor.json. Run it before and after any change to chunking, embeddings, fusion or reranking and report both numbers; the floor is a ratchet, so raise it deliberately and never lower it silently.

For coding style, branch/commit conventions, and the contributor checklist, see CONTRIBUTING.md.