Files
docs/standards/mcp/modules/build_recipe.json
Vishesh 'ironeagle' Bangotra 0cb35d10a6 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
2026-10-20 14:58:17 +05:30

8 lines
9.9 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"module": "build_recipe",
"content": {
"path": "build_recipe",
"docstring": "# Build Recipe\n\n## Summary\n\nThe ordered, deterministic checklist for generating a new application of the\nstandard shape. Every step is fixed; only the resource model (step 2), the\ncodegen pass (step 3), and the pipeline family (step 8) need app-specific work.\n\nThe reference pages behind this recipe are organized as an anatomy: the\ndomains layer, the OpenAPI contract that drives routing *and* the admin UI,\nthe interfaces/infra seam, the auto-rendered UI client, and an optional\npipelines layer — see the [Standards Reference](index.md) index.\n\nThis page is served by the `standards` MCP as `docs://modules/build_recipe`. The\n`start_app` prompt on that server collects the two axes and hands off here; pull\nexact files with `get_app_component`.\n\n---\n\n## 🚀 Bootstrap\n\nFrom the standards docs checkout:\n\n```bash\ncp -r <docs>/standards/src/templates/app apps/<your-app>\ncd apps/<your-app>\n```\n\nPair it with the React client template when a UI is needed (auto-rendered\nadmin from the spec — see [40 – UI](40_ui_admin.md)):\n\n```bash\ncp -r <docs>/standards/src/templates/client apps/<your-app>-client\ncd apps/<your-app>-client && npm install\n```\n\nInstall the internal libraries — editable local checkouts (preferred in\ndevelopment) or the private index (CI / fresh machines). Credentials are\nenvironment-only; never commit them.\n\n```bash\n# local checkouts\npip install -e ../aetos/openapi-first -e ../aetos/mongo-ops -e ../aetos/hexa \\\n -e ../aetos/dagpipe -e ../aetos/doc-forge\n# private index\npip install --extra-index-url \\\n \"https://$PIP_REGISTRY_USERNAME:$PIP_REGISTRY_PASSWORD@pip.aetoskia.com/simple\" .\n```\n\n---\n\n## 📋 Agent prompt (copyable)\n\n````markdown\n# Build a new application from the Aetos Standards blueprint\n\nYou are coding a complete new backend application conforming to the Aetos\nstandard app blueprint. Execute every step in order. Only steps 2–4 use the\napp-specific details provided by the user; everything else is deterministic.\n\n## Before writing any code\n\nConnect to the `standards` MCP server and read:\n- `docs://nav` (the module list)\n- `docs://modules/genericity_matrix` (Tier A library / Tier B template / Tier C authored)\n- `docs://modules/layering_rules` (the dependency rules)\n\nThen:\n- call `find_library` with `db`, `di`, `routing`, `ingestion`, `pipeline`, `docs`\n and note the Tier A libraries that already exist — never reimplement one;\n- call `list_app_components()` and pull each file you need with\n `get_app_component(kind)` instead of writing it from scratch.\n\n## Steps\n\n1. **Scaffold** — copy `standards/src/templates/app/` into `apps/<your-app>/`\n (or pull the same tree via `get_app_template`). Keep the tree: `domain/`,\n `infra/`, `interfaces/`, `pipelines/`, `tests/`, `scripts/`, plus\n `pyproject.toml`, `openapi.yaml`, `config.py`, `init.py`, `main.py`,\n `worker.py`, `Dockerfile`, `docker-compose.yaml`, `.env.example`.\n\n2. **Author the spec (app-specific)** — write `openapi.yaml`: resources,\n schemas, `operationId`s, security, and extension metadata. This is the\n contract and drives all routing. Every operation MUST have an `operationId`.\n\n3. **Generate the scaffold (codegen)** — from the spec, generate the wire\n models and the exact handler signatures:\n ```bash\n openapi-first models openapi.yaml -o _gen/models.py\n openapi-first routes openapi.yaml -o _gen/routes \\\n --use-models --models-module _gen.models --inject-request --package --template-style\n ```\n `_gen/models.py` is the **wire contract** (Pydantic, one class per\n `components.schemas` entry). `_gen/routes/<resource>/routes.py` lists every\n `operationId` with its exact parameter signature. `--template-style` makes\n those stubs `async def` with a `body` parameter, matching the handlers you\n keep in `interfaces/` (without it they are sync `def` stubs taking\n `payload`; both bind the same way). Treat `_gen/` as generated\n (never hand-edit it) — the canonical handlers live in `interfaces/`.\n\n4. **Write each CRUD slice (app-specific)** — per resource create the four-file\n slice: `models.py` (domain model, **no `id`**), `ports/db.py`\n (`class XDocument(BaseDocument, X)` — id comes from `BaseDocument`),\n `ports/service.py`, and optional `converters.py`. Follow the CRUD template.\n\n5. **Wire the composition root** — in `init.py`, build leaf repositories, then\n dependent repositories, then services; add infra adapters (db, cache, stores,\n progress bus, fetchers). Expose `get_svc` overloads.\n\n6. **Add routes** — create `interfaces/<resource>/routes.py` thin handlers whose\n names match the `operationId`s (use the signatures from step 3 as your\n checklist) and re-export them in `interfaces/openapi.py`. Add the cache\n decorator to read endpoints.\n\n7. **Bootstrap app and worker** — confirm `main.py` runs the OpenAPI-first app\n with its lifespan. If the app has long-running jobs, adapt `worker.py` to poll\n the job collection, run the pipeline, and publish progress.\n\n8. **Add pipeline families (only if data-driven)** — copy the worked family\n `pipelines/appointment_reminder/` to `pipelines/<family>/` with `abc.py`,\n `impl.py`, `pipeline.yaml`, `resources/`, and reuse `pipelines/shared/`\n (loader + registry). Register the root, add the `job.kind` handler in\n `worker.py`. Add fixtures and a parity test.\n\n9. **Add infrastructure only where needed** — Tier A capability: use the\n library. Tier B capability: copy the template. Never hand-write a Tier A\n library.\n\n10. **Tests** — integration tests with fakes at the HTTP edge; unit tests for\n domain and pipeline logic; a config-consistency test for rule-driven\n pipelines. Include `tests/integration/test_openapi_app_builds.py` (imports\n the app, asserts `import main` binds every operation).\n\n11. **Scripts and seeds** — operator scripts under `scripts/` using\n `init()` / `get_svc()` / `shutdown()`; run as `python -m scripts.<name>`.\n\n12. **Docs** — author GSDFC docstrings, generate `.pyi` stubs, mark the package\n `py.typed`, and build the docs.\n\n**Definition of done:**\n- `python -c \"import main\"` succeeds.\n- `pytest` passes.\n- The app serves every operation in the spec; the worker drains its queue.\n- No domain module imports a web framework.\n- No Tier A library was reimplemented.\n````\n\n---\n\n## 🧭 Where the steps land\n\nThe steps map onto the layers as follows:\n\n| Step | Package / file | Depends on |\n|---------------------|-----------------------------------|---------------------------------------------|\n| 1 · Scaffold | whole `templates/app/` | — |\n| 2 · Spec | `openapi.yaml` | — |\n| 3 · Codegen | `_gen/` (generated) | spec, openapi-first |\n| 4 · CRUD slices | `domain/<resource>/` | spec, CRUD template |\n| 5 · Wiring | `init.py` | every slice |\n| 6 · Routes | `interfaces/<resource>/` | services, openapi route registry |\n| 7 · Bootstrap | `main.py`, `worker.py` | composition root |\n| 8 · Pipelines | `pipelines/<family>/`, `shared/` | library pipeline engine |\n| 9 · Infra | `infra/` | domain ports |\n| 10 · Tests | `tests/` | app + fixtures |\n| 11 · Scripts | `scripts/` | composition root |\n| 12 · Docs | docstrings + docs build | code, Doc Forge |\n\n---\n\n## 🔧 The codegen fast path, in detail\n\n`openapi-first` is spec → code only (it never generates a spec). Use it to erase\nthe two mechanical parts of the build:\n\n| Generated artifact | Replaces | Notes |\n|--------------------|----------|-------|\n| `_gen/models.py` | hand-writing Pydantic wire models | one class per `components.schemas` entry |\n| `_gen/routes/<resource>/routes.py` | hand-typing handler signatures | names == `operationId`s; `request: Request` injected |\n\nRules of the road:\n\n- **Wire models are not domain models.** `_gen/models.py` is the HTTP contract;\n `domain/<resource>/models.py` is your business shape. If the spec's schema has\n a required `id: str`, keep it off the domain model and let the document get its\n id from `BaseDocument`.\n- **Use `--template-style`.** Stubs are then `async def ...(request, body: ...)`\n matching `interfaces/`; without it they are sync `def ...(payload: ...)`.\n Either binds (the router introspects the signature), but `--template-style`\n keeps the scaffold consistent with the code you keep.\n- **Resource names are sanitized.** `/fetch-requests` → `fetch_requests.py`.\n- **Multipart bodies expand** to `UploadFile = File(...)` / `Form(...)` params.\n- **`_gen/` is disposable.** Regenerate on every spec change; `git diff` shows\n exactly what moved.\n\n---\n\n## ⚠️ Definition of done\n\n- `python -c \"import main\"` succeeds.\n- `pytest` passes.\n- The app serves the spec's operations; the worker drains its queue.\n- No domain module imports a web framework.\n- No Tier A library was reimplemented.\n\n---\n\n## Related\n\n- [10 – Layering Rules](10_layering_rules.md) · [21 – CRUD Template](21_crud_template.md) · [22 – Auth Integration](22_auth_integration.md) · [40 – UI](40_ui_admin.md) · [50 – Pipeline Scaffold](50_pipeline_scaffold.md) · [92 – Genericity Matrix](92_genericity_matrix.md)\n",
"objects": {}
}
}