docs(standards): split genericity matrix and infra adapters into Tier A/B/C

This commit is contained in:
2026-10-12 21:06:35 +05:30
parent 9390839d9b
commit 99fac53c2b
3 changed files with 70 additions and 36 deletions

View File

@@ -3,7 +3,9 @@
## Summary
All external systems are reached through adapters in `infra/`. Prefer an
existing internal library over writing a new adapter.
existing internal library over writing a new adapter; where no library exists,
copy the Tier B scaffold from `templates/app`. See the Genericity Matrix for the
Tier A / B / C split.
---
@@ -31,11 +33,13 @@ existing internal library over writing a new adapter.
- Transactions use a session context manager provided by the library.
**Library:** the Mongo operations library (see registry). Do not write raw
Motor calls in the domain.
**Tier A — Library (Mongo Ops).** Do not write raw Motor calls in the domain;
consult the registry and the library's MCP before touching the driver.
## HTTP response cache
**Tier B — template.** Copy from `templates/app`; not a standalone library.
A generic GET cache sits behind a decorator.
```python
@@ -50,6 +54,8 @@ async def list_items(request): ...
## Event / progress bus
**Tier B — template.** Copy from `templates/app`.
A port with an in-memory default adapter (`publish`, `get_events`). Swap for a
durable broker in production (see Worker & Progress).
@@ -59,10 +65,12 @@ External fetchers (files, mail, HTTP) are adapters that wrap ingestion
libraries. Construct them in the composition root and inject into
orchestrators.
**Libraries:** the ingestion library (formats) and the mail library (email).
**Tier A — Libraries:** Omniread (formats) and Mail Intake (email).
## LLM clients
**Tier B — template.** Copy the pool scaffold from `templates/app`.
When a pipeline calls a model provider, route through a pool adaptor that
handles provider selection, retries, and client lifecycle:
@@ -75,10 +83,17 @@ Providers are selected by `LLM_PROVIDER` and configured by environment.
## Key-value store
**Tier B — template.** Copy from `templates/app`.
For report/snapshot storage, provide a pluggable store port with a Redis
adapter and an in-memory fallback.
## Rule
If a capability already exists as a library (DB, DI, ingestion, mail, auth,
docs), **use it**. Writing a private copy of a library is a defect.
- **Tier A (libraries: DB, DI, ingestion, mail, auth, docs, pipelines)** — use
the library; writing a private copy is a defect. Query `find_library` first.
- **Tier B (cache, progress bus, LLM pool, KV store, composition shape, worker,
tests)** — these are template code, not libraries: copy them from
`templates/app` rather than searching the registry.
- **Tier C (models, business logic, pipeline families, rules)** — author them
yourself.

View File

@@ -2,50 +2,68 @@
## Summary
This page states precisely what is **reusable as-is**, what is a **template to
adapt**, and what is **app-specific and must be authored**. Use it to scope a
new build.
This page states precisely what is **library-backed**, what is
**template-provided**, and what is **app-specific and must be authored**. Use it
to scope a new build and to know, for any given capability, whether to call a
library, copy template code, or write it yourself.
---
## Reusable as-is (do not rewrite)
## Tier A — Library-backed (use; never reimplement)
| Area | Artifact |
|---|---|
| Layering & dependency rule | the package layout and import rules |
| Composition root | the `init.py` shape, idempotency, `get_svc` overloading |
| Web edge | `OpenAPIFirstApp` bootstrap, handler-name = `operationId`, thin handlers |
| CRUD slice | the four-file pattern (model / ports-db / ports-service / converters) |
| Generic CRUD service | the base service adaptor |
| Repository factory | base / populating / cached selection |
| Worker | the poll loop, backoff, retry, status machine |
| Progress bus | the bus port + in-memory adapter + streaming endpoint |
| Human-in-the-loop | the durable pause + question document + resolve endpoint + resume map |
| Infra adaptors | HTTP cache decorator, KV store port, LLM pool scaffold |
| Testing | integration harness with fakes, fixture-parity pattern |
| Docs | GSDFC + generated stubs + MCP bundle pipeline |
These capabilities already exist as internal libraries. Reach them through the
library registry MCP (`find_library(capability)`) and read the library's own MCP
for its API. Writing a private copy of any of these is a defect.
## Template to adapt (copy, then change names)
| Capability | Library | MCP |
|---|---|---|
| Persistence: repositories, cache, populate, transactions | Mongo Ops (`mongo_ops`) | `:8007` |
| Dependency injection / composition | Hexa (`hexa`) | `:8008` |
| Deterministic multi-step transformation engine | DAG Pipe (`dagpipe`) | `:8006` |
| Spec-first HTTP edge, client, codegen | OpenAPI First (`openapi_first`) | `:8004` |
| Format-agnostic fetch + parse (HTML, PDF, CSV, XLSX) | Omniread (`omniread`) | `:8003` |
| Read-only email ingestion | Mail Intake (`mail_intake`) | `:8002` |
| JWT auth primitives (register, login, introspect) | Py JWT (`jwtlib`) | `:8005` |
| Documentation build (MkDocs + MCP) | Doc Forge (`docforge`) | `:8001` |
| Artifact | Change |
|---|---|
| `pyproject.toml` | project name, dependencies |
| `Dockerfile` / `docker-compose.yaml` | service name, ports, services |
| `.env.example` | connection strings, provider keys |
| `openapi.yaml` | every path/schema/operationId |
| `scripts/` | seed and operator tasks |
## Tier B — Template-provided (copy from `templates/app`, then adapt)
## App-specific (must be authored)
These are reusable internal components shipped **inside** the template — they are
not independent libraries. Copy them as-is, then rename/populate only what is
app-specific. They give every app the same wiring shape as the reference app.
| Component | Template location | Action |
|---|---|---|
| Layering & dependency rule | the package layout + import rules | keep |
| Composition root shape | `init.py` (`get_svc`/`get_db`, idempotency) | keep |
| Spec-first web edge | `interfaces/openapi.py`, thin handlers bound to `operationId` | keep |
| CRUD slice pattern | `domain/<resource>/{models.py, ports/db.py, ports/service.py, converters.py}` | rename + fill |
| Generic CRUD service | `infra/adapters/service.py` (`CrudsServiceAdaptor`) | keep |
| Repository factory | `infra/db/repos/mongo.py` (`_repo_factory`) | keep |
| Worker poll + status loop | `worker.py` | keep |
| Progress bus + streaming | bus port + in-memory adapter + SSE endpoint | keep |
| Human-in-the-loop | durable pause + question document + resolve endpoint + resume map | keep |
| HTTP response cache | `cache_response` decorator + generation invalidation | keep |
| Key-value store | KV store port + Redis adapter + in-memory fallback | keep |
| LLM client pool | provider-select + retry pool scaffold | keep |
| Pipeline scaffold | `pipelines/shared/{ports,loader,registry}.py` + `pipelines/<family>/` | rename + fill |
| Operator scripts | `scripts/` (`init()` / `get_svc()` / `shutdown()`) | rename |
| Testing harness | integration fakes + fixture-parity pattern | keep |
| Project scaffolding | `pyproject.toml`, `Dockerfile`, `docker-compose.yaml`, `.env.example`, `openapi.yaml` | rename + fill |
## Tier C — App-specific (must be authored)
| Artifact | Why |
|---|---|
| Resource models | the business shape |
| Repository populate/cache rules | the relationships |
| Service business logic | domain behaviour |
| Pipeline families (if any) | the transformation graph |
| Pipeline families | the transformation graph |
| Pattern/rule resources | data-driven policy |
| Fixtures & golden outputs | test data |
---
## The two axes
Everything app-specific reduces to **two axes**:
@@ -54,4 +72,5 @@ Everything app-specific reduces to **two axes**:
the OpenAPI contract.
2. **Pipeline family** — only if inputs require multi-step transformation.
If you can specify those two axes, the rest of the app follows mechanically.
If you can specify those two axes, the rest of the app follows mechanically:
Tier A is imported, Tier B is copied, and Tier C is the only thing you author.

View File

@@ -13,7 +13,7 @@ patterns, and the internal library catalog that agents consult while coding.
- **Worker & Progress** — queued work, progress reporting, and visibility.
- **Human-in-the-Loop** — guardrails and approvals inside automations.
- **Infra Adapters** — how infrastructure connects without leaking into domain.
- **Genericity Matrix** — what is generic vs app-specific.
- **Genericity Matrix** — what is library-backed, template-provided, or authored.
- **Library Registry** — the catalog of internal libraries behind all of it.
Read the **Wiki** for the philosophy and rationale; these pages are the