(llm-first): context budget, validation, and eval harness, orchestration general-prompt

This commit is contained in:
MaKarin
2026-04-03 14:17:21 +03:00
parent 79c9589658
commit c42a88dff6
189 changed files with 15538 additions and 9109 deletions

View File

@@ -1,79 +1,95 @@
# Auth Rules
This repository keeps the current LLM-first CRUD generation architecture as the primary working baseline.
<!-- prompt-version: 2.0 -->
<!-- applies-to: client/src/auth/, server/src/auth/, toir-realm.json -->
<!-- validated-by: tools/validate-generation.mjs §validateAuthChecks §validateRealmChecks -->
- Auth is part of the default generation path, not a post-generation addon.
- `server/` is the active backend target output path.
- `client/` is the active frontend target output path.
- The generated runtime stays SPA + API + external Keycloak + PostgreSQL only.
Use this document during the **Auth / Runtime / Realm** stage defined in `prompts/general-prompt.md`.
## Frontend auth invariants
## Purpose
- Use `keycloak-js` with redirect-based login only.
- Initialize Keycloak before rendering the SPA.
- Use Authorization Code Flow + PKCE (`S256`).
- Keep `authProvider`, `dataProvider`, `getIdentity()`, `getPermissions()`, and `checkError()` as stable provider seams.
- Derive identity from token claims already present in the parsed token.
- Do not call `loadUserProfile()` and do not depend on `/account` for the baseline app.
- `401` must force re-authentication; `403` must stay an authorization error.
- Keep token handling in memory and refresh through one shared in-flight operation.
Generate and preserve the auth contracts that let the CRUD app run as a React Admin SPA backed by a NestJS API protected by external Keycloak.
## Working runtime defaults
## Mandatory Inputs
Use the already working project defaults unless a prompt explicitly overrides them.
- `prompts/general-prompt.md`
- `prompts/runtime-rules.md`
- current repository auth/runtime defaults
- Frontend Keycloak base URL example:
- `VITE_KEYCLOAK_URL=https://sso.greact.ru`
- Frontend realm and client example:
- `VITE_KEYCLOAK_REALM=toir`
- `VITE_KEYCLOAK_CLIENT_ID=toir-frontend`
- Backend issuer and audience example:
- `KEYCLOAK_ISSUER_URL=https://sso.greact.ru/realms/toir`
- `KEYCLOAK_AUDIENCE=toir-backend`
- CORS example:
- `CORS_ALLOWED_ORIGINS=http://localhost:5173,https://toir-frontend.greact.ru`
## Expected Outputs
Anti-regression rule:
- `client/src/auth/`
- `client/src/dataProvider.ts`
- `server/src/auth/`
- `toir-realm.json`
- Do not switch the baseline Keycloak example back to `http://localhost:8080` in generated `.env.example` files unless the prompt explicitly asks for a local Keycloak runtime.
- Localhost Keycloak values may exist in private `.env.local` or `.env` overrides, but they are not the default project examples.
## Frontend Auth Invariants
## Backend auth invariants
- use `keycloak-js` with redirect-based login only
- initialize Keycloak before rendering the SPA
- use Authorization Code Flow + PKCE (`S256`)
- keep `authProvider`, `dataProvider`, `getIdentity()`, `getPermissions()`, and `checkError()` as stable seams
- derive identity from token claims already present in the token
- do not call `loadUserProfile()`
- `401` forces re-authentication; `403` remains an authorization error
- keep token handling in memory with one shared in-flight refresh path
- Verify JWTs with `jose`.
- Validate issuer + audience + signature via JWKS.
- Resolve JWKS in this order:
## Backend Auth Invariants
- verify JWTs with `jose`
- validate issuer, audience, and signature via JWKS
- resolve JWKS in this order:
1. `KEYCLOAK_JWKS_URL`
2. OIDC discovery at `/.well-known/openid-configuration`
3. `${issuer}/protocol/openid-connect/certs`
- Extract roles only from `realm_access.roles`.
- Keep `/health` public and all generated CRUD routes protected by default.
- extract roles only from `realm_access.roles`
- keep `/health` public
- generated CRUD routes stay protected by default
## Auth anti-regression invariants
## Working Runtime Defaults
- The accepted JWKS resolution chain above is the only baseline truth path. Do not document one order and implement another.
- If auth implementation changes, `prompts/auth-rules.md` and `prompts/validation-rules.md` must be updated in the same change.
- Do not skip OIDC discovery when no explicit `KEYCLOAK_JWKS_URL` is provided.
- Do not switch role extraction to alternative claims unless the prompt explicitly changes the baseline contract.
- Do not reintroduce localhost Keycloak defaults into shared baseline examples.
Keep these defaults unless a task explicitly overrides them:
## Realm artifact contract
- `VITE_KEYCLOAK_URL=https://sso.greact.ru`
- `VITE_KEYCLOAK_REALM=toir`
- `VITE_KEYCLOAK_CLIENT_ID=toir-frontend`
- `KEYCLOAK_ISSUER_URL=https://sso.greact.ru/realms/toir`
- `KEYCLOAK_AUDIENCE=toir-backend`
- `CORS_ALLOWED_ORIGINS=http://localhost:5173,https://toir-frontend.greact.ru`
- A physical root-level `*-realm.json` artifact is mandatory output.
- The artifact must be importable, versioned, and aligned with generated backend/frontend env contracts.
- It must parameterize:
Anti-regression rule:
- do not revert shared examples to localhost Keycloak defaults unless a task explicitly requests a local Keycloak baseline
## Realm Artifact Contract
The root realm artifact is mandatory and must:
- be importable and versioned
- align with generated frontend/backend env contracts
- parameterize:
- realm name
- frontend client id
- backend client id / audience
- local and production frontend URLs
- artifact filename
- It must explicitly deliver:
- explicitly deliver:
- `sub`
- `aud`
- `realm_access.roles`
- It must define:
- define:
- realm roles `admin`, `editor`, `viewer`
- a public SPA client with PKCE S256
- a bearer-only backend client
- an explicit audience client scope
- explicit protocol mappers for baseline identity and role claims
- protocol mappers for baseline identity and role claims
## Completion Expectations
Auth/runtime generation is incomplete if any of the following is true:
- frontend and backend auth seams drift from each other
- JWKS resolution order changes
- `/health` stops being public
- shared Keycloak defaults regress to localhost examples
- the realm artifact no longer matches backend/frontend expectations

View File

@@ -1,88 +1,147 @@
# Backend Rules
The backend remains derived from `domain/*.dsl` inside the existing LLM-first pipeline. No compiler platform or generator engine is introduced.
<!-- prompt-version: 2.0 -->
<!-- applies-to: server/src/modules/, server/src/app.module.ts -->
<!-- validated-by: tools/validate-generation.mjs §validateApiDslCoverage §validateNaturalKeyChecks -->
## Backend scaffold baseline
Use this document during the **Backend** stage defined in `prompts/general-prompt.md`.
- Start backend initialization from the official NestJS CLI workspace, not from manually created files.
- The backend must remain compatible with standard Nest workspace tooling such as `nest build` and `nest start`.
- Preserve the core Nest workspace files generated by the CLI, especially:
## Purpose
Generate NestJS CRUD artifacts that match the DSL contract exactly and remain compatible with a standard NestJS workspace.
## Mandatory Inputs
- `prompts/general-prompt.md`
- the active `api API.<Entity>` block from `domain/toir.api.dsl`
- referenced DTOs and enums from `domain/toir.api.dsl`
- an intact or repaired official NestJS scaffold under `server/`
`api-summary.json` may be consulted only as an auxiliary inventory or validator-related artifact. It must never replace the DSL as the backend source of truth.
## Expected Outputs
Per entity:
- `server/src/modules/<kebab>/<kebab>.module.ts`
- `server/src/modules/<kebab>/<kebab>.controller.ts`
- `server/src/modules/<kebab>/<kebab>.service.ts`
- `server/src/modules/<kebab>/dto/create-<kebab>.dto.ts`
- `server/src/modules/<kebab>/dto/update-<kebab>.dto.ts`
Repository-wide:
- `server/src/app.module.ts` registrations
## Scaffold Baseline
- Start backend initialization and repair from the official NestJS CLI workspace, not from hand-written files.
- Preserve Nest workspace essentials:
- `server/tsconfig.json`
- `server/tsconfig.build.json`
- `server/nest-cli.json`
- `server/src/main.ts`
- `server/src/app.module.ts`
- For domain resources, prefer official Nest CLI generation patterns for modules/controllers/services/resources and then adapt the generated code to Prisma and auth requirements.
- Do not delete required Nest workspace files just because the LLM can inline a smaller custom structure.
- If the workspace is degraded, repair it before generating domain code.
## Forbidden backend generation patterns
Forbidden patterns:
- Do not bootstrap `server/` by hand-writing a pseudo-Nest project from memory.
- Do not remove `tsconfig.json`, `tsconfig.build.json`, or `nest-cli.json` after generation.
- Do not replace standard Nest package scripts with ad hoc commands that break `nest build` or `nest start`.
- Do not continue CRUD generation on top of a degraded backend workspace without repairing the workspace first.
- hand-written pseudo-Nest scaffolds
- deleting required Nest config files after generation
- replacing normal Nest build/start behavior with ad hoc scripts
## Domain-derived output
- `domain/*.dsl` is the source of truth for entities, fields, primary keys, foreign keys, and enums.
- `domain-summary.json` is a derived artifact used to stabilize LLM generation and validation. It must never replace the DSL as the source of truth.
- Each entity becomes:
- a Prisma model
- a NestJS module
- a controller
- a service
- create/update DTOs
## DTO and Prisma mapping
- `decimal` -> Prisma `Decimal`, DTO/API `string`
- `date` -> Prisma `DateTime`, DTO/API `string`
- Enums remain string-valued in DTO/API contracts
## CRUD and natural-key invariants
## Route And Resource Contract
- Use the shared entity-to-resource naming convention from `prompts/general-prompt.md`.
- Each entity becomes a NestJS module, controller, service, and create/update DTO pair.
- CRUD routes use the real primary key name in the path.
- Every API record returned to React Admin must include `id`.
- For entities whose primary key is not `id`, the backend must map the real key to `id`.
- Natural-key list/sort logic must never build ORM `orderBy` against a fake physical `id`.
- For natural-key entities, map the real primary key to `id` in responses and sort translation.
## Service invariants
## DTO Contract
- Never pass raw update DTOs into Prisma update `data`.
- Remove `id`, the real primary key, and readonly fields from update payloads before calling Prisma.
- Keep PrismaService lightweight:
- `DTO.<Entity>Create` defines `Create<Entity>Dto`.
- `DTO.<Entity>Update` defines `Update<Entity>Dto`.
- Do not invent fields or pull field lists from memory.
- Never include `id` in Create/Update DTOs.
Type and decorator rules:
| DSL type | TS DTO type | class-validator decorator | Notes |
|-----------|-------------|---------------------------|-------|
| `uuid` | `string` | `@IsUUID()` | |
| `string` | `string` | `@IsString()` | |
| `text` | `string` | `@IsString()` | |
| `integer` | `number` | `@IsInt()` | |
| `number` | `number` | `@IsNumber()` | |
| `decimal` | `string` | `@IsString()` | serialize with Prisma Decimal |
| `date` | `string` | `@IsString()` | serialize as ISO string |
| `boolean` | `boolean` | `@IsBoolean()` | |
| enum name | `string` | `@IsEnum(EnumName)` | |
Nullability rules:
- every field that is not `is required` gets `@IsOptional()` before the type decorator
- every generated DTO imports from `'class-validator'`
## Controller Contract
- Apply `@UseGuards(JwtAuthGuard, RolesGuard)` at controller class level.
- Roles per verb:
- `GET` -> `viewer | editor | admin`
- `POST`, `PATCH`, `PUT` -> `editor | admin`
- `DELETE` -> `admin`
- Reconcile DSL HTTP shapes for repository compatibility:
- list endpoints declared as `POST .../page` generate as `@Get()` with React Admin query params
- update endpoints declared as `PUT` generate as `@Patch(':<pk>')`
- Path parameters are taken from the DSL endpoint contract, not invented from generic CRUD memory.
## Service Contract
- Never pass raw update DTOs directly into Prisma update `data`.
- Strip `id`, the real primary key, and readonly fields before writes.
- Keep `PrismaService` lightweight:
- extend `PrismaClient`
- implement `OnModuleInit`
- call `$connect()`
- do not use `beforeExit`
- do not add `beforeExit`
## Filtering contract
List endpoint requirements:
- List endpoints must support React Admin query parameters:
- `_start`, `_end`, `_sort`, `_order`
- arbitrary field filters from query string
- `q` for reference autocomplete search
- String/text search filters may use `contains` with case-insensitive mode.
- Foreign key filters must use exact-match semantics (no `contains` for FK scalar keys).
- Enum filters must support both single and repeated query params:
- `status=Draft`
- `status=Draft&status=Approved`
- Repeated enum params must map to Prisma `{ in: [...] }`.
- Sorting must use real model scalar fields only; natural-key entities must not fallback to fake physical `id`.
- accept React Admin query params: `_start`, `_end`, `_sort`, `_order`, `q`
- set `Content-Range`
- set `Access-Control-Expose-Headers: Content-Range`
## Reproducibility invariants
Filtering rules:
- A freshly generated backend must be bootstrappable with ordinary Nest + Prisma commands from `prompts/runtime-rules.md`.
- Missing TypeScript or Nest workspace config is a generation failure, not an acceptable simplification.
- The baseline backend should fail only on missing runtime dependencies or env values, not because the Nest workspace itself is incomplete.
- string/text filters may use case-insensitive `contains`
- foreign-key scalar filters must use exact-match semantics
- enum filters must support both single and repeated params
- repeated enum params must map to Prisma `{ in: [...] }`
- `_sort=id` must map to the real primary key for natural-key entities
## Recovery rule if backend workspace degraded
Decimal and date handling:
- If required Nest scaffold files are missing or broken, restore the official workspace baseline before editing Prisma models, modules, controllers, services, or DTOs.
- Treat workspace repair as higher priority than feature generation, because generated domain code on top of a broken workspace is invalid baseline output.
- `decimal` writes: `new Prisma.Decimal(value)`
- `decimal` reads: `.toString()`
- `date` writes: `new Date(value)`
- `date` reads: `.toISOString()`
## Backend auth defaults
## Natural-Key Rules
- `GET` -> `viewer | editor | admin`
- `POST`, `PATCH`, `PUT` -> `editor | admin`
- `DELETE` -> `admin`
For entities whose physical primary key is not `id`:
- route params use the real primary key name
- responses expose `id` mapped from that primary key
- sort/update behavior never targets a fake physical `id`
- update payload sanitization removes both `id` and the real primary key
## Completion Expectations
Backend generation is incomplete if any of the following is true:
- required Nest scaffold files are missing
- DTO decorators are incomplete or type-incorrect
- controllers are missing guards or role decorators
- natural-key handling regresses to a fake physical `id`
- list/filter behavior is incompatible with React Admin expectations

View File

@@ -1,65 +1,118 @@
# Frontend Rules
The frontend stays a React Admin SPA generated from `domain/*.dsl` and anchored to the existing auth seams.
<!-- prompt-version: 2.0 -->
<!-- applies-to: client/src/resources/, client/src/App.tsx -->
<!-- validated-by: tools/validate-generation.mjs §validateApiDslCoverage -->
## Frontend scaffold baseline
Use this document during the **Frontend** stage defined in `prompts/general-prompt.md`.
- Start frontend initialization from the official Vite React TypeScript scaffold, not from manually assembled files.
- Preserve a valid Vite workspace baseline, including:
## Purpose
Generate React Admin resources that stay aligned with the DSL contract, the backend contract, and the repository auth/data provider seams.
## Mandatory Inputs
- `prompts/general-prompt.md`
- the active `api API.<Entity>` block from `domain/toir.api.dsl`
- referenced DTOs and enums from `domain/toir.api.dsl`
- an intact or repaired official Vite React TypeScript scaffold under `client/`
## Expected Outputs
Per entity:
- `client/src/resources/<kebab>/<Entity>List.tsx`
- `client/src/resources/<kebab>/<Entity>Create.tsx`
- `client/src/resources/<kebab>/<Entity>Edit.tsx`
- `client/src/resources/<kebab>/<Entity>Show.tsx`
Repository-wide:
- `client/src/App.tsx` resource registrations
## Scaffold Baseline
- Start frontend initialization and repair from the official Vite React TypeScript scaffold, not from a hand-written shell.
- Preserve workspace essentials:
- `client/index.html`
- `client/tsconfig.json`
- `client/vite.config.*`
- `client/src/main.tsx`
- Add React Admin and auth seams on top of that baseline instead of replacing the workspace with a hand-written minimal shell.
- Do not delete required Vite entry/config files just because the LLM can write a shorter custom setup.
- Repair the scaffold before generating resources if it is degraded.
## Forbidden frontend generation patterns
## Resource Contract
- Do not bootstrap `client/` by hand-writing a pseudo-Vite project from memory.
- Do not remove `index.html`, `tsconfig*`, or `vite.config.*` after generation.
- Do not replace standard Vite package scripts with ad hoc commands that break `vite build`, `vite dev`, or `vite preview`.
- Do not continue React Admin resource generation on top of a degraded frontend workspace without repairing the workspace first.
- Use the shared entity-to-resource naming convention from `prompts/general-prompt.md`.
- Every entity becomes a React Admin resource with `list`, `create`, `edit`, and `show`.
- `Resource` registration in `client/src/App.tsx` must include `show={...}`.
- Every frontend record must work with React Admin's `id` contract, including natural-key entities.
## Resource generation
DTO-driven view rules:
- Each entity becomes a React Admin resource with list/create/edit/show views.
- Resource names must stay aligned with backend path segments.
- Foreign keys must use `ReferenceInput` / `ReferenceField`.
- Foreign keys shown in list/show views must stay clickable via `ReferenceField link="show"` to open full details of the related resource.
- Lists must expose filters through `List` `filters` and an actions toolbar with `FilterButton`.
- For enum fields where multi-select is required (for example `status`), use `SelectArrayInput` in list filters.
- For foreign key filters and form selection use `ReferenceInput` + `AutocompleteInput` with `filterToQuery={(searchText) => ({ q: searchText })}`.
- Form mapping must stay type-safe:
- `integer` / `decimal` -> `NumberInput`
- `date` -> `DateInput`
- List and Show views use fields from `DTO.<Entity>`
- Create view uses fields from `DTO.<Entity>Create`
- Edit view uses fields from `DTO.<Entity>Update`
- Do not derive form fields directly from model attributes when the DTO contract is narrower
## Provider seams
## Input And Field Mapping
- `client/src/dataProvider.ts` is the single authenticated request seam.
- `client/src/auth/authProvider.ts` is the single React Admin auth seam.
- Auth logic must not leak into resource components.
Form inputs:
## Identity and permissions
- `integer`, `number`, `decimal` -> `NumberInput`
- `date` -> `DateInput`
- required `boolean` -> `BooleanInput`
- nullable `boolean` -> `NullableBooleanInput`
- enum -> `SelectInput`
- FK reference -> `ReferenceInput` + `AutocompleteInput`
- `getIdentity()` must resolve from parsed token claims.
- `getPermissions()` may expose realm roles for UI awareness.
- Backend enforcement remains authoritative.
Display fields:
## React Admin compatibility
- `integer`, `number`, `decimal` -> `NumberField`
- `date` -> `DateField`
- `boolean` -> `BooleanField`
- enum -> `SelectField`
- FK reference -> `ReferenceField`
- Every resource record must include `id`.
- Natural-key resources must preserve route, update, and sort compatibility with React Admin contracts.
- Frontend requests must continue to work when the real primary key is not named `id`.
- `dataProvider` query serialization must preserve repeated query params for array filters (for example enum multi-select).
- `Resource` wiring in `App.tsx` must keep `show={...}` registration for all generated resources.
Hard failure rule:
## Reproducibility invariants
- using plain `TextInput` for `integer`, `number`, `decimal`, `date`, or `boolean` is a generation failure
- A freshly generated frontend must remain compatible with standard Vite commands such as `npm run dev` and `npm run build`.
- Missing Vite workspace files or missing local Vite executable wiring is a generation failure, not an acceptable simplification.
- The generated frontend should fail only on missing installation/env/runtime backend availability, not because the Vite app structure itself is incomplete.
## Filter And Reference Contract
## Recovery rule if frontend workspace degraded
- Lists must expose filters and include a toolbar with `FilterButton`.
- Enum multi-select filters use `SelectArrayInput`.
- Reference filters and form selectors use `ReferenceInput` + `AutocompleteInput` with `filterToQuery={(searchText) => ({ q: searchText })}`.
- FK list/show rendering must use `ReferenceField link=\"show\"`.
- `dataProvider` query serialization must preserve repeated params for array filters.
- If required Vite scaffold files are missing or broken, restore the official workspace baseline before editing resources, auth seams, or UI code.
- Treat workspace repair as higher priority than feature generation, because generated React Admin code on top of a broken Vite workspace is invalid baseline output.
Reference display expression priority:
1. if `inventoryNumber` exists: ``(record) => `${record.inventoryNumber} — ${record.name ?? record.inventoryNumber}``
2. else if `code` exists: ``(record) => `${record.code} — ${record.name ?? record.code}``
3. else if `number` exists: ``(record) => `${record.number} — ${record.name ?? record.number}``
4. else if `name` exists: `(record) => record.name ?? record.id`
5. else: `(record) => record.id`
## Auth And Provider Seams
- `client/src/dataProvider.ts` remains the single authenticated request seam.
- `client/src/auth/authProvider.ts` remains the single React Admin auth seam.
- Resource components must not embed auth logic.
- `getIdentity()` resolves from token claims.
- `getPermissions()` may expose realm roles for UI awareness, but backend enforcement stays authoritative.
## Natural-Key Compatibility
- Frontend requests and routes must continue to work when the real primary key is not named `id`.
- Edit/show/delete flows must preserve compatibility with backend natural-key handling.
- Sorting and filtering assumptions must not regress to a fake physical `id`.
## Completion Expectations
Frontend generation is incomplete if any of the following is true:
- required Vite scaffold files are missing
- Create/Edit inputs are type-incorrect
- filter UI is missing or incomplete
- reference fields stop linking to `show`
- resource registration omits `show={...}`

View File

@@ -1,146 +1,298 @@
ROLE
<!-- prompt-version: 3.0 -->
<!-- applies-to: all generation tasks (master orchestration prompt) -->
<!-- validated-by: tools/validate-generation.mjs + npm run eval:generation -->
You are a Staff-level Fullstack Platform Engineer working inside the established LLM-first CRUD generation baseline.
# Role
Use context7 when official framework guidance is needed.
You are the master orchestrator of the KIS-TOiR generation pipeline.
This repository is not a new generator engine. Do not redesign it into a planner/emitter/runtime platform.
Own the full run: understand the current workspace, read the domain contract, coordinate sub-agents and MCP tools, generate or repair artifacts in the correct order, run the required gates, fix failures, and stop only when the repository is genuinely generation-complete.
GOAL
# Project Description
Strengthen and use the existing LLM-first CRUD generation pipeline.
KIS-TOiR is an LLM-first fullstack CRUD generation project for equipment maintenance management.
- Keep `domain/*.dsl` as the source of truth for the domain model.
- Keep `server/` as the active backend target output path.
- Keep `client/` as the active frontend target output path.
- Keep Keycloak auth in the default generation path.
- Keep PostgreSQL as the only Dockerized runtime dependency.
- Generate and maintain:
- `domain-summary.json`
- a root-level `*-realm.json`
- backend/frontend auth seams
- runtime/env/bootstrap artifacts
- validation-gate-compatible output
- Backend: NestJS + Prisma
- Frontend: Vite React TypeScript + React Admin
- Auth/runtime: external Keycloak + PostgreSQL + repository-managed env/runtime artifacts
Use the already working runtime defaults for this project unless the prompt explicitly overrides them:
The repository is intentionally prompt-driven. `prompts/*.md` define generation policy; generated code lives under `server/` and `client/`.
- frontend Keycloak URL example: `https://sso.greact.ru`
- frontend realm/client examples: `toir`, `toir-frontend`
- backend issuer/audience examples: `https://sso.greact.ru/realms/toir`, `toir-backend`
- production frontend origin example: `https://toir-frontend.greact.ru`
# Mission
Do not silently regress these examples to localhost Keycloak defaults.
Turn the repository source contract into a buildable, validated workspace by:
ACTIVE KNOWLEDGE BLOCKS
1. starting from official framework scaffolding when a workspace is missing or degraded
2. generating Prisma, backend, frontend, auth, runtime, and realm artifacts from the DSL
3. using sub-agents intentionally instead of carrying every concern in one context window
4. proving completion with builds and repository validation gates
Read in this order:
# Source Of Truth
1. `domain/dsl-spec.md`
2. `domain/*.dsl`
3. `domain-summary.json` if present
4. `prompts/auth-rules.md`
5. `prompts/backend-rules.md`
6. `prompts/frontend-rules.md`
7. `prompts/runtime-rules.md`
8. `prompts/validation-rules.md`
`domain/toir.api.dsl` is the operative source of truth for generation runs.
Interpretation rules:
It is authoritative for:
- `domain/*.dsl` is authoritative.
- `domain-summary.json` is derived. Regenerate or validate it against the DSL; never treat it as the source of truth.
INPUT CONTRACT
Required:
- `domain/*.dsl`
Optional:
- `overrides/api-overrides.dsl`
- `overrides/ui-overrides.dsl`
- entities and enums
- DTO shapes per operation
- nullability and requiredness
- primary and foreign keys
- HTTP methods, endpoint paths, and pagination contracts
Rules:
- Do not require DTO/API/UI DSL files.
- Do not resurrect multi-DSL source-of-truth behavior.
- Optional overrides may refine derived API/UI behavior but must not redefine the domain model.
- Read the DSL directly. Do not substitute `api-summary.json` for `domain/toir.api.dsl`.
- Work from entity-scoped slices: the active `api API.<Entity>` block plus its referenced DTOs and enums.
- Quote the relevant DSL field definitions verbatim before generating DTOs, Prisma fields, controller contracts, or React Admin components.
- Treat `api-summary.json` only as an auxiliary artifact for quick inventory or validation/tooling that explicitly depends on it. It is never the authoritative generation input.
PIPELINE CONTRACT
# Orchestration Model
1. Parse `domain/*.dsl`.
2. Generate or refresh `domain-summary.json`.
3. Scaffold with official framework CLI conventions where scaffolding is needed.
4. Generate or maintain backend/frontend code in `server/` and `client/`.
5. Generate or maintain the root-level realm artifact.
6. Generate or maintain env/bootstrap/runtime artifacts.
7. Run the lightweight validation gate.
Use a manager-first, agent-as-tool architecture.
REPAIR-BEFORE-GENERATE ORDER
- Keep one orchestrator in charge of planning, sequencing, integration, and final acceptance.
- Delegate bounded work to specialists; do not let sub-agents redefine the source hierarchy or completion criteria.
- Delegate by stage or artifact family, and by entity when parallelism helps.
- If a sub-agent result conflicts with the DSL, companion rules, or validator output, trust the DSL and the gates.
1. Inspect whether `server/` and `client/` are still valid framework workspaces.
2. If either workspace is degraded, repair the official scaffold baseline first.
3. Only after workspace repair, generate or update domain-derived feature code.
4. Only after generation, run validation and buildability checks.
Mandatory delegation pattern for future runs:
CLI-FIRST SCAFFOLDING CONTRACT
- `explorer`
Use first for repo discovery, scaffold inspection, locating entity-scoped DSL context, and finding existing registrations/seams.
- `docs_researcher`
Use when framework behavior, CLI scaffolding, or prompt/orchestration patterns need verification against official docs or Context7.
- stage worker / generator
Use for bounded Prisma, backend, frontend, or auth/runtime implementation work after the orchestrator has assembled the right inputs.
- `reviewer`
Use before declaring completion. Reviewer must check DSL fidelity, prompt-contract compliance, and whether validation output supports the completion claim.
- Never hand-write a fresh framework workspace from scratch when an official CLI exists for that framework.
- For `server/`, initialize the workspace from the official NestJS CLI baseline first, then generate/adapt modules/resources inside that workspace.
- For `client/`, initialize the workspace from the official Vite React TypeScript baseline first, then add React Admin, auth seams, and generated resources.
- Treat CLI scaffolding as the required baseline for compiler config, package scripts, workspace metadata, and default entry files.
- Manual creation is allowed only for domain-derived feature code after the official workspace exists.
- If a workspace already exists but is missing required CLI baseline files, repair it back to a valid official-style workspace before adding more generated code.
If a runtime does not expose named sub-agents, preserve the same separation of responsibilities inside one agent and keep stage handoffs explicit.
ANTI-REGRESSION FAILURES
# MCP Usage Model
Treat the following as baseline violations, not acceptable improvisations:
Use MCP/tools deliberately, not reflexively.
- creating a NestJS workspace by manually writing `package.json`, `tsconfig*`, `nest-cli.json`, and `src/*` from memory instead of starting from official CLI conventions
- creating a Vite React TypeScript workspace by manually writing `package.json`, `index.html`, `tsconfig*`, `vite.config.*`, and `src/*` from memory instead of starting from official scaffold conventions
- deleting required framework scaffold files after generation because the app appears to work with a smaller custom structure
- declaring generation successful when workspace validity or buildability is broken or unverified
- letting prompts promise an auth/runtime contract that validation does not enforce
- treating one project-specific DSL filename as the only allowed source instead of supporting `domain/*.dsl`
- Filesystem/search tools: gather exact local context before making decisions.
- Shell/runtime tools: run official CLI scaffolding, Prisma commands, builds, validators, and evals. Do not simulate command results from memory.
- Context7: verify current NestJS, Prisma, React Admin, Vite, Keycloak, or prompt/orchestration guidance when repository docs are not enough.
- Web research: only after local files and Context7 are insufficient; prefer primary sources.
- Diff/validation tools: use before edits, after edits, and always at the end.
OUTPUT CONTRACT
Tool-order policy:
The baseline output must include:
1. local authoritative files
2. Context7 / official docs
3. web fallback
4. validation gates
# Generation Roadmap
## 1. Preparation / Discovery
Purpose:
- establish the active scope
- verify scaffold health
- load only the context needed for the next stage
Responsible:
- orchestrator
- `explorer` first
- `docs_researcher` if scaffold conventions or framework behavior are uncertain
Mandatory inputs:
- `AGENTS.md`
- `prompts/general-prompt.md`
- `domain/toir.api.dsl`
- `prompts/runtime-rules.md`
- `.codex/AGENTS.md` and `.codex/agents/*.toml` when the runtime supports those agents
Expected outputs:
- entity-scoped DSL quotes for the active work
- a clean stage plan
- `server/` and `client/` confirmed healthy or repaired from official scaffolding
Handoff:
- proceed to Prisma only after the repository has a valid NestJS workspace, Vite React TypeScript workspace, or a documented repair plan using official CLIs
Stage rules:
- Use official Nest CLI for initial backend workspace creation or repair.
- Use official Vite React TypeScript CLI for initial frontend workspace creation or repair.
- Use Prisma CLI for Prisma initialization when relevant.
- Do not handcraft framework scaffolds that should come from official CLIs.
## 2. Prisma
Purpose:
- generate the repository schema that reflects the DSL exactly
Responsible:
- orchestrator
- Prisma-focused stage worker
- `docs_researcher` when Prisma behavior is uncertain
Mandatory inputs:
- entity-scoped DSL quotes from `domain/toir.api.dsl`
- `prompts/prisma-rules.md`
Expected outputs:
- `server/prisma/schema.prisma`
- Prisma initialization or repair steps completed when the workspace was missing required baseline files
Handoff:
- backend generation starts only after schema output reflects the DSL and Prisma setup is coherent with runtime rules
## 3. Backend
Purpose:
- generate NestJS modules, controllers, services, DTOs, and module registration from the DSL contract
Responsible:
- orchestrator
- backend stage worker, ideally one entity at a time when parallelized
Mandatory inputs:
- entity-scoped DSL quotes from `domain/toir.api.dsl`
- `prompts/backend-rules.md`
Expected outputs:
- `server/src/modules/<entity>/...`
- `server/src/app.module.ts`
Handoff:
- frontend generation starts only after backend contracts, guards, DTOs, and natural-key behavior align with backend rules
## 4. Frontend
Purpose:
- generate React Admin resources and resource registration that match backend and DSL contracts
Responsible:
- orchestrator
- frontend stage worker, ideally one entity at a time when parallelized
Mandatory inputs:
- entity-scoped DSL quotes from `domain/toir.api.dsl`
- `prompts/frontend-rules.md`
Expected outputs:
- `client/src/resources/<entity>/...`
- `client/src/App.tsx`
Handoff:
- auth/runtime integration starts only after frontend resource contracts align with DTO-derived field sets and type mappings
## 5. Auth / Runtime / Realm Artifacts
Purpose:
- wire authentication, environment defaults, realm import, and runtime topology around the generated CRUD app
Responsible:
- orchestrator
- auth/runtime stage worker
- `docs_researcher` when Keycloak or framework integration behavior is uncertain
Mandatory inputs:
- `prompts/auth-rules.md`
- `prompts/runtime-rules.md`
Expected outputs:
- `server/src/auth/`
- `client/src/auth/`
- `client/src/dataProvider.ts`
- `server/.env.example`
- `client/.env.example`
- `client/src/auth/keycloak.ts`
- `client/src/auth/authProvider.ts`
- `client/src/dataProvider.ts`
- `server/src/auth/*`
- `docker-compose.yml`
- `domain-summary.json`
- root-level `*-realm.json`
- `toir-realm.json`
The baseline output must also remain a real framework workspace, not a prompt-only file collection:
Handoff:
- `server/tsconfig.json`
- `server/tsconfig.build.json`
- `server/nest-cli.json`
- `client/index.html`
- `client/tsconfig.json`
- `client/vite.config.*`
- verification starts only after auth seams, runtime artifacts, and realm output are aligned with backend/frontend expectations
NON-GOALS
## 6. Verification / Success Gate
- No new generator engine
- No compiler/IR platform
- No heavy codegen redesign
- No replacement of the old LLM-first architecture
Purpose:
COMPLETION INVARIANTS
- prove that the generation run is complete and not just plausible
- Generation is incomplete if `server/` is not a valid NestJS workspace.
- Generation is incomplete if `client/` is not a valid Vite React TypeScript workspace.
- Generation is incomplete if auth rules, runtime rules, and validation rules describe different truth paths.
- Generation is incomplete if buildability is broken.
- If buildability cannot be checked because dependencies are missing, report that state explicitly; do not report a green result for buildability.
Responsible:
VALIDATION
- orchestrator
- `reviewer` before completion
Before considering the output complete, satisfy `prompts/validation-rules.md`.
Mandatory inputs:
- `prompts/validation-rules.md`
- validation command output
- reviewer findings
Expected outputs:
- refreshed auxiliary artifacts if the validator/tooling requires them, including `api-summary.json`
- passing validation gates
- successful backend and frontend builds
Handoff:
- there is no next stage; report complete only when every success criterion below is satisfied
# Success Criteria
Generation is successful only if all of the following are true:
- `server/` exists in the project root
- `client/` exists in the project root
- the backend builds successfully
- the frontend builds successfully
- `node tools/validate-generation.mjs --artifacts-only` passes
- `npm run eval:generation` passes
- required auth/runtime/realm artifacts exist and match their companion rules
- module/resource registrations are complete
- any validator-required auxiliary artifacts, including `api-summary.json`, are refreshed and consistent
- the reviewer has not identified unresolved contract violations
# Non-Goals / Constraints
- Do not edit `domain/toir.api.dsl` during generation.
- Do not treat `api-summary.json` as the source of truth or default starting point.
- Do not inline large backend/frontend/prisma/auth/runtime/validation rule sets into this master prompt; load the companion docs instead.
- Do not generate domain artifacts on top of a broken scaffold when official CLI repair is required.
- Do not claim success from prompt reasoning alone; use builds and repository gates.
- Do not load the full DSL blob when entity-scoped context is enough.
# Companion Rule Documents
These documents are mandatory when their stage is active:
- Prisma stage: `prompts/prisma-rules.md`
- Backend stage: `prompts/backend-rules.md`
- Frontend stage: `prompts/frontend-rules.md`
- Auth / realm stage: `prompts/auth-rules.md`
- Runtime / bootstrap stage: `prompts/runtime-rules.md`
- Verification stage: `prompts/validation-rules.md`
The master prompt owns orchestration. Companion docs own artifact-specific detail.

119
prompts/prisma-rules.md Normal file
View File

@@ -0,0 +1,119 @@
# Prisma Rules
<!-- prompt-version: 2.0 -->
<!-- applies-to: server/prisma/schema.prisma -->
<!-- generated-by: LLM following these rules -->
<!-- source-of-truth: domain/toir.api.dsl -->
<!-- validated-by: tools/validate-generation.mjs §validateBuildChecks -->
Use this document during the **Prisma** stage defined in `prompts/general-prompt.md`.
## Purpose
Generate `server/prisma/schema.prisma` as a faithful reflection of `domain/toir.api.dsl`.
## Mandatory Inputs
- `prompts/general-prompt.md`
- the relevant entity/enum definitions from `domain/toir.api.dsl`
- the existing Prisma header if `server/prisma/schema.prisma` already exists
`api-summary.json` may be used only as an auxiliary validator/inventory artifact. It is not part of the authoritative Prisma source hierarchy.
## Expected Output
- `server/prisma/schema.prisma`
Never edit the schema manually during normal generation. Change the DSL and regenerate instead.
## Source Of Truth
Entity definitions, field types, PKs, FKs, enums, optionality, uniqueness, and defaults come from `domain/toir.api.dsl`.
## Scalar Type Mapping
| DSL type | Prisma scalar type |
| --------- | ------------------ |
| `uuid` | `String` |
| `string` | `String` |
| `text` | `String` |
| `integer` | `Int` |
| `number` | `Float` |
| `decimal` | `Decimal` |
| `date` | `DateTime` |
| `boolean` | `Boolean` |
| enum name | enum name as-is |
Unknown DSL types pass through as-is for forward compatibility.
## Primary Key Rules
- a field marked `key primary` becomes `@id`
- if the primary key type is `uuid` or the field name is `id`, use `@id @default(uuid())`
- non-uuid natural keys keep plain `@id`
- every entity must resolve to exactly one primary key
## Optionality And Defaults
- primary keys are required
- fields marked `is required` are required
- all other fields are optional with Prisma `?`
- non-primary unique fields get `@unique`
- `default <value>` maps to Prisma `@default(...)`
## Foreign Key And Relation Rules
For a DSL field declared `key foreign { relates Entity.field }`:
1. emit the FK scalar field first
2. add a relation field named `lowerFirst(relatedEntity)`
3. if that relation name collides, append `Ref`
4. annotate with `@relation(fields: [<fkField>], references: [<referencedField>])`
Inverse array relations:
- add inverse array fields for referencing entities automatically
- pluralization rules:
- `equipment` stays `equipment`
- names ending in `s` add `es`
- all others add `s`
- if the inverse name collides, append `List`
## Enum Rules
- every DSL enum becomes a Prisma enum
- preserve declaration order
- preserve the enum name exactly
## Header Preservation
If `server/prisma/schema.prisma` already contains a `generator client { ... }` block, preserve everything before the first `enum` or `model` keyword.
If no valid header exists, emit:
```prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
```
## Forbidden Patterns
- do not add fields not declared in the DSL
- do not add `@@index`, `@@map`, or schema-level directives not declared by the DSL
- do not add `@db.*` modifiers
- do not change the datasource provider away from `postgresql`
## Completion Expectations
Prisma generation is incomplete if any of the following is true:
- `server/prisma/schema.prisma` does not exist
- the schema no longer reflects the DSL
- required relation fields or inverse arrays are missing
- header generation or preservation breaks Prisma baseline behavior

View File

@@ -1,96 +1,86 @@
# Runtime Rules
This repository keeps the current LLM-first CRUD generation architecture as the primary working baseline and strengthens the existing pipeline instead of replacing it.
<!-- prompt-version: 2.0 -->
<!-- applies-to: docker-compose.yml, server/.env.example, client/.env.example -->
<!-- validated-by: tools/validate-generation.mjs §validateRuntimeContractChecks -->
## Baseline runtime topology
Use this document during the **Preparation / Discovery** and **Auth / Runtime / Realm** stages defined in `prompts/general-prompt.md`.
- `server/` is the active backend target output path.
- `client/` is the active frontend target output path.
- Docker scope remains PostgreSQL only.
- Keycloak remains external to the repository runtime.
- The project remains LLM-first: markdown knowledge blocks in `prompts/` orchestrate generation, while active generated/maintained code lives in `server/` and `client/`.
## Purpose
## Required input and derived artifacts
Define the runtime topology, environment defaults, scaffold expectations, and bootstrap sequence for a buildable generated workspace.
- Source of truth:
- `domain/*.dsl`
- Required derived artifacts:
- `domain-summary.json`
- root-level `*-realm.json`
## Mandatory Inputs
`domain-summary.json` exists to stabilize generation and validation; it must be regenerated from the DSL and treated as non-authoritative.
- `prompts/general-prompt.md`
- `prompts/auth-rules.md` when runtime changes affect auth defaults or seams
- current repository runtime/auth defaults
## Output contract
`api-summary.json` is an auxiliary artifact only. Refresh it when validator/tooling requires freshness checks or when a compact inventory helps discovery. Do not treat it as the runtime source of truth.
The strengthened baseline must produce and keep aligned:
## Expected Outputs
- `server/prisma/schema.prisma`
- backend/frontend env examples
- backend/frontend auth seams
- root `.gitignore`, `server/.gitignore`, `client/.gitignore`
- `docker-compose.yml`
- `domain-summary.json`
- root-level realm import artifact
- `server/.env.example`
- `client/.env.example`
- a buildable NestJS workspace under `server/`
- a buildable Vite React TypeScript workspace under `client/`
- any validator-required auxiliary artifacts such as `api-summary.json`
## Concrete runtime examples
## Baseline Runtime Topology
Use these as the baseline examples for this project unless the prompt explicitly overrides them:
- `server/` is the backend output path
- `client/` is the frontend output path
- Docker scope stays PostgreSQL-only
- Keycloak remains external to repository runtime
- the project remains LLM-first and prompt-driven
- Backend:
- `PORT=3000`
- `DATABASE_URL="postgresql://postgres:postgres@localhost:5432/toir"`
- `CORS_ALLOWED_ORIGINS="http://localhost:5173,https://toir-frontend.greact.ru"`
- `KEYCLOAK_ISSUER_URL="https://sso.greact.ru/realms/toir"`
- `KEYCLOAK_AUDIENCE="toir-backend"`
- Frontend:
- `VITE_API_URL=http://localhost:3000`
- `VITE_KEYCLOAK_URL=https://sso.greact.ru`
- `VITE_KEYCLOAK_REALM=toir`
- `VITE_KEYCLOAK_CLIENT_ID=toir-frontend`
## Concrete Runtime Defaults
These example values come from the already working runtime shape and are preferred over local-only Keycloak placeholders.
Backend:
## Runtime bootstrap
- `PORT=3000`
- `DATABASE_URL="postgresql://postgres:postgres@localhost:5432/toir"`
- `CORS_ALLOWED_ORIGINS="http://localhost:5173,https://toir-frontend.greact.ru"`
- `KEYCLOAK_ISSUER_URL="https://sso.greact.ru/realms/toir"`
- `KEYCLOAK_AUDIENCE="toir-backend"`
1. Import the root-level realm artifact into Keycloak.
2. Start PostgreSQL with `docker compose up -d`.
3. From `server/` run:
- initialize or repair the workspace with official Nest CLI scaffolding if required before generating domain code
- `npm install`
- `npx prisma generate`
- `npx prisma migrate dev`
- `npx prisma db seed`
- `npm run build`
- `npm run start`
4. From `client/` run:
- initialize or repair the workspace with official Vite React TypeScript scaffolding if required before generating app code
- `npm install`
- `npm run build`
- `npm run dev`
Frontend:
## Recovery and completion rules
- `VITE_API_URL=http://localhost:3000`
- `VITE_KEYCLOAK_URL=https://sso.greact.ru`
- `VITE_KEYCLOAK_REALM=toir`
- `VITE_KEYCLOAK_CLIENT_ID=toir-frontend`
- Repair degraded framework workspaces before applying any new domain-derived generation changes.
- Do not mark generation complete while `server/` or `client/` remains non-buildable.
- If dependency installation has not happened yet, buildability may be reported as skipped, but it must never be reported as green without verification.
- Runtime/bootstrap instructions are reusable project baseline rules; TOiR names remain examples, not the only supported domain project.
## Scaffold Expectations
## Scaffold expectations
- new or repaired backend workspaces start from the official Nest CLI
- new or repaired frontend workspaces start from the official Vite React TypeScript CLI
- Prisma initialization uses the official Prisma CLI when relevant
- the LLM may customize generated code after scaffold creation, but must not replace official initialization with ad hoc file creation
- NestJS workspace creation should follow the official Nest CLI path for new applications and resource scaffolding.
- Vite frontend creation should follow the official Vite `create-vite` path for React TypeScript applications.
- The LLM may customize generated code after scaffold creation, but must not replace official workspace initialization with ad hoc file creation.
## Runtime Bootstrap
## Common generation failures to avoid
1. import `toir-realm.json` into Keycloak
2. start PostgreSQL with `docker compose up -d`
3. from `server/`:
- repair or create the workspace with official Nest CLI if needed
- install dependencies
- run Prisma commands required by the schema stage
- run `npm run build`
- run `npm run start`
4. from `client/`:
- repair or create the workspace with official Vite CLI if needed
- install dependencies
- run `npm run build`
- run `npm run dev`
- starting feature generation before scaffold repair
- leaving deleted framework config files unrepaired because the current diff looks smaller
- accepting a form-only validation pass while buildability is unknown
- binding runtime rules to one project-specific DSL filename instead of `domain/*.dsl`
## Completion Expectations
## Baseline intent
Runtime preparation is incomplete if any of the following is true:
- No new generator engine
- No compiler platform
- No planner/emitter/runtime redesign
- Only the current LLM-first pipeline, strengthened by summary, realm, and validation artifacts
- `server/` is missing or not buildable as a NestJS workspace
- `client/` is missing or not buildable as a Vite React TypeScript workspace
- framework scaffolding was hand-built instead of created or repaired from official CLIs
- shared env defaults drift from the repository auth/runtime contract
- runtime success is claimed without actual build verification

View File

@@ -1,98 +1,101 @@
# Validation Rules
Validation is now a lightweight automated gate instead of a prose-only checklist.
<!-- prompt-version: 2.0 -->
<!-- applies-to: tools/validate-generation.mjs and npm run eval:generation -->
<!-- validated-by: self -->
## Commands
Use this document during the **Verification / Success Gate** stage defined in `prompts/general-prompt.md`.
- `npm run generate:domain-summary`
- `npm run validate:generation`
- `npm run validate:generation:runtime`
## Purpose
Define the repository gates that convert a plausible generation run into a verified one.
## Primary Gates
- `node tools/validate-generation.mjs --artifacts-only`
- `npm run eval:generation`
## Auxiliary Freshness Prep
- `npm run generate:api-summary`
Run the freshness prep when the repository validator or supporting tooling expects `api-summary.json` to exist and match the current DSL. This artifact is auxiliary to validation and inventory, not the generation source of truth.
## Prompt-Gate Alignment Rule
- Every invariant described as required in the active prompt corpus must either be enforced by this gate or be called out explicitly as a manual/runtime-only check.
- Validation must not stay silent about a violation that the prompts describe as forbidden.
- Validation must not report green buildability when build verification was skipped.
- every invariant marked required in the active prompt corpus must either be enforced by a gate or called out as manual/runtime-only
- validation must not silently ignore a forbidden pattern
- build verification must not be reported as green when it was skipped
## Gate groups
## Gate Groups
### Build checks
### Build Checks
- at least one `domain/*.dsl` file exists
- required artifacts exist
- Prisma schema exists
- frontend/backend env contracts exist
- frontend/backend framework workspace files exist
- `domain-summary.json` matches the current DSL
- project `.env.example` files keep the working domain-based Keycloak examples unless explicitly overridden
- at least one `domain/*.api.dsl` file exists
- required artifacts exist:
- `server/prisma/schema.prisma`
- env examples
- required scaffold files
- auth/runtime/realm artifacts
- if the current validator policy checks `api-summary.json`, it exists and is fresh relative to the DSL
- `server/` remains a valid Nest workspace
- `client/` remains a valid Vite workspace
- generation must not pass validation if framework scaffolding files were deleted and replaced by a hand-written minimal skeleton
- if dependencies are installed, build verification runs for `server/` and `client/`
- if dependencies are installed, backend and frontend build verification runs
- if dependencies are missing, build verification is reported as skipped with reason instead of green
### Auth checks
### Auth Checks
- frontend auth seam files exist
- backend auth seam files exist
- `401` and `403` semantics stay split
- `401` and `403` semantics remain split
- auth code keeps the required Keycloak/JWT contracts
- JWKS resolution chain matches the contract:
- JWKS resolution order remains:
1. explicit `KEYCLOAK_JWKS_URL`
2. OIDC discovery
3. certs fallback
### Filter checks
### Filter And UI Checks
- list resources expose filter UI (including `FilterButton`)
- list resources expose filter UI including `FilterButton`
- reference filters use `ReferenceInput` + `AutocompleteInput` with `filterToQuery`
- data provider preserves repeated query params for array filters
- backend FK filters keep exact-match semantics
- enum repeated params are mapped to Prisma `in`
- typed form mapping is preserved:
- `integer` / `decimal` -> `NumberInput`
- `date` -> `DateInput`
- reference fields intended for navigation keep `ReferenceField link="show"`
- `dataProvider` preserves repeated query params for array filters
- backend FK filters remain exact-match
- repeated enum params map to Prisma `in`
- Create/Edit forms keep type-correct inputs
- navigable references keep `ReferenceField link="show"`
- resources keep `show={...}` registration in `App.tsx`
### Natural-key checks
### Natural-Key Checks
- response records expose `id`
- route/update contracts use the real primary key
- natural-key sort/update paths do not regress to a fake physical `id`
### Realm checks
### Realm Checks
- a root `*-realm.json` artifact exists
- realm roles exist
- audience delivery exists
- required claims are explicit
- SPA/backend client structure is explicit
- required roles, audience delivery, and claims remain explicit
- SPA and backend client structure remains explicit
### Runtime checks
### Runtime Checks
- compose topology stays PostgreSQL-only
- Prisma lifecycle scripts remain in place
- `/health` stays public
- backend can execute `npm run build` inside `server/`
- frontend can execute `npm run build` inside `client/` after dependencies are installed
- client/server `.env.example` stay aligned with the working runtime defaults:
- `https://sso.greact.ru`
- `toir`
- `toir-frontend`
- `toir-backend`
- `https://toir-frontend.greact.ru`
- optional runtime execution mode runs:
- `npx prisma generate`
- `npx prisma migrate dev`
- `npx prisma db seed`
- Docker topology remains PostgreSQL-only
- Prisma lifecycle commands remain available where required
- `/health` remains public
- backend build runs inside `server/`
- frontend build runs inside `client/`
- client/server `.env.example` stay aligned with repository defaults
### Scaffold checks
### Output Contract Checks
- backend initialization starts from official Nest CLI scaffolding
- frontend initialization starts from official Vite React TypeScript scaffolding
- feature generation happens after scaffold creation, not instead of scaffold creation
- repair happens before generation when workspace is degraded
- required framework configs and entry files must survive subsequent LLM edits
- every generated Create/Update DTO imports from `'class-validator'`
- DTO fields have type-correct decorators
- optional/nullable fields carry `@IsOptional()` before the type decorator
- controllers carry the required guards and roles
- React Admin components use correct input/field types
The automated gate is intentionally small. It enforces the critical reproducibility contract without turning the repository into a test platform or a generator engine.
### Eval Harness
- `npm run eval:generation` runs fixture-based semantic checks
- eval failures block completion
- prompt changes that break evals are regressions, not acceptable simplifications