Phase 7: serve the vet sample from the template tools and docs

- build.py: _TEMPLATE_COMPONENTS rewritten around the vet sample (53 kinds —
  per-resource slices, jobs, worked appointment_reminder family, tests);
  seed tokens dropped from the manifest ('sample: vet' instead)
- registry.py: get_app_component(kind) no longer renames item/example seeds;
  prompts and tool docs updated to 'copy a slice and adapt'
- templates/README.md, 01_build_recipe, 40_ui_admin, wiki/03 updated off the
  old seed scheme; repo inventory/config now exclude vet (docs move under
  standards; react/vet itself is deleted in a later phase)
- regenerated MCP bundle, vendored templates, and site output
This commit is contained in:
2026-10-20 14:58:17 +05:30
parent 56aa1322fb
commit 0cb35d10a6
107 changed files with 3292 additions and 937 deletions

View File

@@ -69,8 +69,7 @@ Then:
- call `find_library` with `db`, `di`, `routing`, `ingestion`, `pipeline`, `docs`
and note the Tier A libraries that already exist — never reimplement one;
- call `list_app_components()` and pull each file you need with
`get_app_component(kind, resource=..., family=...)` instead of writing it from
scratch.
`get_app_component(kind)` instead of writing it from scratch.
## Steps
@@ -117,10 +116,11 @@ Then:
with its lifespan. If the app has long-running jobs, adapt `worker.py` to poll
the job collection, run the pipeline, and publish progress.
8. **Add pipeline families (only if data-driven)** — copy `pipelines/example/`
to `pipelines/<family>/` with `abc.py`, `impl.py`, `pipeline.yaml`,
`resources/`, and reuse `pipelines/shared/` (loader + registry). Register the
root. Add fixtures and a parity test.
8. **Add pipeline families (only if data-driven)** — copy the worked family
`pipelines/appointment_reminder/` to `pipelines/<family>/` with `abc.py`,
`impl.py`, `pipeline.yaml`, `resources/`, and reuse `pipelines/shared/`
(loader + registry). Register the root, add the `job.kind` handler in
`worker.py`. Add fixtures and a parity test.
9. **Add infrastructure only where needed** — Tier A capability: use the
library. Tier B capability: copy the template. Never hand-write a Tier A

View File

@@ -57,7 +57,7 @@ docs://modules/react-openapi # module: specExtensions — the full catalo
The app's own spec carries the per-resource values; the catalog explains what
each field does. The template's `openapi.yaml` shows the convention on the
example `Item` and `Job` schemas.
example `Job` schema.
---
@@ -82,5 +82,7 @@ example `Item` and `Job` schemas.
- The server template ships authless by default (see
[22 – Auth Integration](22_auth_integration.md)); the client template pairs
with it and degrades to "no login" until a security scheme is declared.
- `react/vet` is the full-stack reference implementation: spec with x-
extensions, server, and the consuming client in one tree.
- The standards **app + client templates** are the full-stack reference: the
server spec carries the x- extensions, and the client renders the admin from
it. The wiki's **Reference App** walkthrough (`06_reference_app`) documents
the pairing end to end.

View File

@@ -10,7 +10,7 @@ chosen by what the repository produces:
|------|------|----------|-------|
| **A — PyPI package** | `templates/drone/python-lib.yaml` | A wheel + sdist on the private index | `dagpipe`, `doc-forge`, `hexa`, `mail-intake`, `mongo-ops`, `omniread`, `openapi-first`, `py-jwt` |
| **B — npm package** | `templates/drone/npm-lib.yaml` | A package published to the private npm registry | `doc-weaver`, `react-auth`, `react-openapi` |
| **C — Docker deployment** | `templates/drone/service-docker.yaml` | An image pushed to the registry and run as a container | `auth-server`, `vet` |
| **C — Docker deployment** | `templates/drone/service-docker.yaml` | An image pushed to the registry and run as a container | `auth-server` |
All templates run on `platform: linux / arm64` with the workspace at
`/drone/src`. Copy the matching template to `<repo>/.drone.yml`; the Type A and

View File

@@ -45,15 +45,14 @@ source is `package.json`; Drone file is `npm-lib.yaml` (tag-triggered).
---
## Services & Apps (Type C)
## Services (Type C)
A container image pushed to the registry and run on the Docker host. Version
source is the `VERSION` file; Drone file is `service-docker.yaml`.
| Repo | Path | Type | Trigger | Docs |
|------|------|------|---------|------|
| `auth-server` | `auth-server` | service | tag | api, lib, wiki |
| `vet` | `react/vet` | app | tag | lib, wiki |
| Repo | Path | Trigger | Docs |
|------|------|---------|------|
| `auth-server` | `auth-server` | tag | api, lib, wiki |
Tag-triggered and enforces `tag == VERSION`.
@@ -65,7 +64,7 @@ Tag-triggered and enforces `tag == VERSION`.
|------|----------------|-----------|-------|
| package (PyPI) | `pyproject.toml` | `CHANGELOG.md` | `python-lib.yaml` |
| package (npm) | `package.json` | `CHANGELOG.md` | `npm-lib.yaml` |
| service / app | `VERSION` | `CHANGELOG.md` | `service-docker.yaml` |
| service | `VERSION` | `CHANGELOG.md` | `service-docker.yaml` |
Every covered repository must be able to satisfy `tag == version`:
the version file (never a commit id) is bumped in the release MR, the MR is

View File

@@ -122,16 +122,6 @@
"trigger": "tag",
"docs": ["api", "lib", "wiki"],
"mcp": null
},
{
"name": "vet",
"type": "app",
"path": "react/vet",
"version_source": "VERSION",
"drone": "service-docker.yaml",
"trigger": "tag",
"docs": ["lib", "wiki"],
"mcp": null
}
]
}

View File

@@ -1,16 +1,19 @@
# Application Template
A minimal, runnable skeleton of the standardized architecture. It demonstrates
both axes of the blueprint (see `standards`):
A runnable sample of the standardized architecture — the **vet** veterinary
clinic domain, kept as the standards' reference sample. It demonstrates both
axes of the blueprint (see `standards`):
1. **Resource axis** — items and jobs, each a Claude-style generic CRUD slice
(model → document → repo → service → route), all driven from `openapi.yaml`.
2. **Pipeline axis** — a background `worker.py` that polls pending jobs and runs
a pipeline; `pipelines/example/` shows the reusable family skeleton and
`pipelines/item_sync.py` the simple end-to-end form.
1. **Resource axis** — five domain aggregates (parents, pets, treatments,
vets, appointments) plus a **jobs** queue, each a CRUD slice
(model → document → repo → service → route), all driven from
`openapi.yaml`. x- extension fields on the spec drive the admin client.
2. **Pipeline axis** — a background `worker.py` that polls pending jobs and
dispatches by `job.kind`; `pipelines/appointment_reminder/` is the worked
family and `pipelines/shared/` the reusable scaffold.
Everything here is deliberately small so an agent can rewrite each file rather
than delete unused code. The domain is a neutral "item", not an app noun.
Copy a slice, replace the domain with your own — the layer structure, wiring
patterns and tests stay.
## Internal dependencies
@@ -38,11 +41,19 @@ The app depends on the internal Aetos libraries (`openapi-first`, `mongo-ops`,
cd apps/<your-app>
1. `pyproject.toml` — rename the package; keep the internal library pins.
2. `config.py` — replace/add settings consumed by your domain.
3. `openapi.yaml` — replace the `Item`/`Job` resources with your resources.
4. `domain/` — rename `item` and `job` slices to your aggregates.
5. `pipelines/` — replace the demo with your pipeline (see below).
6. `tests/` — keep the two test files as the pattern for your own.
2. `config.py` — replace/add settings consumed by your domain (keep the
worker knobs if you run jobs).
3. `openapi.yaml` — replace the vet resources with yours; keep the x-
extension conventions on schemas and fields.
4. `domain/` — replace each aggregate slice with your own; copy
`domain/parents/` as the simplest pattern, `domain/appointments/` when you
need FK expansion.
5. `interfaces/` — one `routes.py` per resource re-exported from
`openapi.py`; keep `_common.py` as-is.
6. `pipelines/` — replace the appointment_reminder family with yours (see
below); keep `pipelines/shared/` as-is.
7. `tests/` — keep `test_openapi_app_builds.py`; adapt the unit tests as
patterns for your own.
Install and run:
@@ -53,8 +64,7 @@ Install and run:
## Pipeline families
`pipelines/item_sync.py` is the smallest possible pipeline (plain async steps).
When a family needs its own stages, copy `pipelines/example/`:
Copy `pipelines/appointment_reminder/` as the family pattern:
pipelines/<family>/
abc.py # port contracts
@@ -68,7 +78,8 @@ When a family needs its own stages, copy `pipelines/example/`:
The shared loader wires the root through the DI library (`hexa.build`) and merges
the pattern fragments; the registry resolves a `(kind, variant, mode)` triple to
a root class. See standards "50_pipeline_scaffold".
a root class. The worker maps `job.kind` to a handler in its `HANDLERS`
dispatch table. See standards "50_pipeline_scaffold" and "51_worker_and_progress".
## What to keep, what to replace
@@ -79,9 +90,10 @@ a root class. See standards "50_pipeline_scaffold".
| openapi-first routing | Paths, schemas, operationIds |
| mongo-ops repo factory | Collections, doc models |
| generic CRUD adaptor | Nothing (reuse as-is) |
| `interfaces/_common.py` | Nothing (reuse as-is) |
| `pipelines/shared/` | Nothing (reuse as-is) |
| `pipelines/example/` | Family name, stages, patterns |
| worker poll + status loop | Job payloads, pipeline steps |
| `pipelines/appointment_reminder/` | Family name, stages, patterns |
| worker poll + dispatch loop | Job kinds, payloads, pipeline steps |
| `scripts/` | Task bodies |
## Where the internal libraries slot in
@@ -95,4 +107,4 @@ a root class. See standards "50_pipeline_scaffold".
Confirm current endpoints and ownership with the `standards` registry MCP tools:
`find_library("pipeline")`, `find_library("auth")`, or
`get_app_component("pipeline-abc", family="csv")`.
`get_app_component("pipeline-abc")`.

View File

@@ -40,8 +40,7 @@ From an MCP client connected to the `standards` server:
**`start_app`** to intake-and-build in one call.
3. The prompt hands off to `docs://modules/build_recipe`; the agent scaffolds
with `get_app_template()` and pulls exact files with
`get_app_component(kind, resource=..., family=...)`, authoring only the
app-specific parts.
`get_app_component(kind)`, authoring only the app-specific parts.
4. To validate the standard without touching a real app, invoke **`trial`**
(`trial(app_name=..., build_path=...)`) to build into a scratch directory,
prove it builds, and report findings.