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¶
- Edit
specs/openapi.yamlfirst (the SSOT). make generate— regenerateadapta/models/generated/models.py. Never hand-edit generated files.- Implement the handler in
adapta/api/v1/*and the logic inadapta/services/*. make check-models(drift gate) andmake test-contracts(schemathesis against a live server) must pass.
Changing the database schema¶
- Change the ORM in
adapta/db/models.py. - Autogenerate a migration, then review it (autogenerated ≠ correct).
make migrate-test— the up→down→up round-trip must pass on seeded data.
Changing the eval set format / the eval gate¶
- The dataset shape is governed by
specs/schemas/eval_dataset.schema.json(SFT rows only); the validator isadapta/services/datasets.py. The gate itself returns with E4.3 — see the roadmap. - 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, andmkdocs 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):
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.