Files
docs/standards/mcp/modules/build_recipe.json
Vishesh 'ironeagle' Bangotra fced40af59 feat(standards): codify codegen, ship generic Tier-B infra, add get_app_template + prompts; fix docs:// regressions
P0: fix doc:// -> docs:// across standards src/server/registry and regenerate stale mongo-ops bundle. P1: build recipe + spec-first routing now document the openapi-first codegen fast path (models/routes with --inject-request/--package). P4: CRUD template documents the model-vs-document id rule (BaseDocument owns id). P5: authless guidance (omit security keys). P6: template gains generic infra (http_cache, keyed SSE bus, KV port+in-memory+Redis), interfaces/openapi.py + .dockerignore + generic build test registered as components, and a get_app_template tool; genericity matrix marks LLM pool + human-in-loop as reference-app patterns. P7: intake/build/start_app/trial prompts. P8: template ships tests/integration/test_openapi_app_builds.py. Rebuilt standards + openapi-first bundles and re-collected.
2026-10-13 03:26:51 +05:30

8 lines
8.7 KiB
JSON
Raw 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\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\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, resource=..., family=...)` instead of writing it from\n 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\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. 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 `pipelines/example/`\n to `pipelines/<family>/` with `abc.py`, `impl.py`, `pipeline.yaml`,\n `resources/`, and reuse `pipelines/shared/` (loader + registry). Register the\n root. 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- **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- [02 – Layering Rules](02_layering_rules.md) · [05 – CRUD Template](05_crud_template.md) · [06 – Pipeline Scaffold](06_pipeline_scaffold.md) · [12 – Genericity Matrix](12_genericity_matrix.md)\n",
"objects": {}
}
}