

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
1# GitHub Copilot — Instructions for Delphi Projects23## Contexto45This is a **Delphi (Object Pascal)** project that follows SOLID principles, clean code and the Object Pascal Style Guide. See `AGENTS.md` in the project root for the complete convention reference.67## General Guidelines891. **Always generate code in Object Pascal** (Delphi) unless explicitly requested in another language.102. **Use PascalCase** for all identifiers. Lowercase reserved words.113. **Respect the prefixes** of the Pascal convention: `T` (classes), `I` (interfaces), `E` (exceptions), `F` (private fields), `A` (parameters), `L` (local variables).124. **Prefer interfaces** over concrete classes for dependencies.135. **Use constructor injection** for dependency injection.146. **Never put business logic in form event handlers** (`OnClick`, `OnChange`, etc.). Delegate to services.1516## Code Style1718### Indentation and Formatting19- Indentation: **2 spaces** (no tabs)20- `begin` on the **same line** of `if`, `for`, `while`, `with` when in a single block21- `begin` on **new line** for method implementations22- Limit of **120 characters** per line2324### Unit Sections25Order unit sections according to:26```27unit Nome;2829interface3031uses32 { RTL units },33 { Units do projeto };3435type36 { Enums e Records }37 { Interfaces }38 { Classes }3940implementation4142uses43 { Units adicionais só necessárias na implementação };4445{ Implementações }4647end.48```4950### Variable Declaration51```pascal52// Preferir inline var quando disponível (Delphi 10.3+)53var LCustomer := TCustomer.Create('João');5455// Ou declaraction explícita com prefixo L56var57 LCustomer: TCustomer;58 LCount: Integer;59```6061## Error Handling6263- Use **specific exceptions** (create exception classes per domain):64```pascal65 EBusinessRuleException = class(Exception);66 EEntityNotFoundException = class(Exception);67 EValidationException = class(Exception);68```69- **Guard clauses** at the beginning of the method instead of deep nesting70- **Try/finally** for memory management71- **Try/except** only for actual error handling, never for control flow7273## Documentation7475- Generate **XMLDoc** for public methods and properties76- Comments in **Portuguese** for Brazilian projects77- Do not comment self-explanatory code7879## Design Patterns8081When creating new features, follow the layered architecture:82- **Domain:** Entities, Value Objects, Interfaces83- **Application:** Services, Use Cases, DTOs84- **Infrastructure:** Repositories (FireDAC), external APIs85- **Presentation:** Forms VCL/FMX8687## What NOT to generate8889- ❌ Do not use `with` statement90- ❌ Do not create global variables91- ❌ Do not use `AnsiString` when `string` (UnicodeString) is appropriate92- ❌ Don't use magic numbers — declare constants93- ❌ Don't do generic catch (`except on E: Exception do ShowMessage`)94- ❌ Don't mix UI logic with business logic95- ❌ Do not create methods with more than 20 lines96- ❌ Don't ignore `Free` of temporary objects (use try/finally)9798## REST Frameworks99100### Horse101- Controller: class with `class procedure RegisterRoutes`102- Handler: `class procedure Nome(AReq: THorseRequest; ARes: THorseResponse; ANext: TProc)`103- Middleware: `THorse.Use(Jhonson)`, `THorse.Use(CORS)`, `THorse.Use(HandleException)`104- Routes: kebab-case, plural — `/api/customers`, `/api/order-items`105- Always delegate to Services — never access data in the controller106107### DelphiMVCFramework108- Controller: inherits `TMVCController` with `[MVCPath('/api/resource')]`109- Routes: attributes `[MVCPath]`, `[MVCHTTPMethod([httpGET])]`110- Active Record: inherits `TMVCActiveRecord` with `[MVCTable]`, `[MVCTableField]`111- Serialization via `Render()` — do not use `Response.Content` directly112- JWT: `TMVCJWTAuthenticationMiddleware`113114### Dext Framework115- Minimal API: `App.Builder.MapGet`, `MapPost` using anonymous functions (handlers)116- Native routing with Auto Model Binding populating DTOs117- Dependency Injection: `App.Services.AddSingleton`, `AddScoped`118- Entity ORM: `DbContext.Where(U.Age > 18)` (Smart Properties expressions instead of SQL strings)119- Async: use `TAsyncTask` for asynchronism and promises120121### DevExpress Components122- DevExpress component prefixes: `grd` (TcxGrid), `tvw` (TcxGridDBTableView), `lyt` (TdxLayoutControl), `skn` (TdxSkinController)123- Prefer `TdxLayoutControl` to manual positioning124- Configure grid via code when columns are dynamic125- Export: use `cxGridExportLink` for Excel/PDF126127### ACBr Project (Commercial Automation)128- **Golden Rule:** Do not attach components (`TACBrNFe`, `TACBrCTe`, etc.) directly to UI forms.129- Isolate tax logic in Service classes (e.g. `TNFeService`) or Repositories.130- Configure certificates and cryptographic libraries (WinCrypt/OpenSSL) via code, with data dynamically obtained from abstraction classes.131- Always guarantee memory freeing if you build ACBr components dynamically in a Service (`try...finally Free;`).132- Common prefixes in the base UI or DataModules: `acbrNFe`, `acbrECF`, `acbrTef`, `acbrBoleto`.133134### Firebird Database135- **Rule of Thumb:** Dialect 3 ALWAYS (`SQLDialect := '3'`), CharacterSet UTF8, PageSize 16384.136- **RETURNING:** `INSERT INTO ... RETURNING id` requires `LQuery.Open`, NEVER `ExecSQL` (which discards the result).137- **Generators:** Use `GEN_ID(generator, 1)` in `BEFORE INSERT` or `IDENTITY` triggers (Firebird 3+).138- **Stored Procedures:** Selectable (with `SUSPEND`) → `SELECT * FROM SP_NOME(...)`. Executable → `EXECUTE PROCEDURE SP_NOME(...)`.139- **Transactions:** Explicitly use `StartTransaction/Commit/Rollback` for compound operations. Isolation pattern: `xiReadCommitted`.140- **Error Handling:** Treat `EFDDBEngineException.Kind` → `ekRecordLocked` (deadlock), `ekUKViolated` (duplicate), `ekFKViolated` (FK).141- **Domains:** Use Domains (`DM_ID`, `DM_NAME`, `DM_MONEY`) to centralize types and validations in the schema.142- **Anti-patterns:** ❌ Concatenate SQL, ❌ `ExecSQL` with `RETURNING`, ❌ Ignore `CharacterSet`, ❌ `CREATE TABLE IF NOT EXISTS` (use `RDB$RELATIONS`).143144### PostgreSQL Database145- **Driver:** `DriverName := 'PG'`, `CharacterSet := 'UTF8'`, default port 5432.146- **IDENTITY:** Use `GENERATED ALWAYS AS IDENTITY` instead of `SERIAL` for new projects (PG 10+).147- **RETURNING:** Same rule as Firebird — `INSERT ... RETURNING id` requires `LQuery.Open`, not `ExecSQL`.148- **UPSERT:** `INSERT ... ON CONFLICT (col) DO UPDATE SET ...` — native to PostgreSQL.149- **JSONB:** Use for semi-structured data. Cast in SQL with `::jsonb`. Indexable with GIN.150- **ENUM Types:** `CREATE TYPE status AS ENUM (...)` mapped to Pascal enum via string constants.151- **Functions:** Return value or table — `SELECT * FROM fn_nome(...)`. Procedures (PG 11+): `CALL sp_nome(...)`.152- **Metadata:** Use `information_schema.tables` / `information_schema.columns` (not `RDB$`).153- **Anti-patterns:** ❌ `SERIAL` (use `IDENTITY`), ❌ `SELECT *` in large tables, ❌ N+1 queries, ❌ JSON as TEXT (use `JSONB`).154155### MySQL / MariaDB Database156- **Driver:** `DriverName := 'MySQL'`, default port 3306. Client library: `libmysql.dll` (or `libmariadb.dll`).157- **Charset:** `utf8mb4` ALWAYS. MySQL's `utf8` is only 3 bytes long (does not support emoji). Collation: `utf8mb4_unicode_ci`.158- **AUTO_INCREMENT:** MySQL DOES NOT support `RETURNING`. Get ID via `LAST_INSERT_ID()` or `FConnection.GetLastAutoGenValue('')`.159- **UPSERT:** `INSERT ... ON DUPLICATE KEY UPDATE name = VALUES(name)` — native to MySQL.160- **JSON:** Native `JSON` type (MySQL 5.7+). `->>`/`JSON_EXTRACT` operators. Index via Generated Column.161- **Engine:** `InnoDB` ALWAYS (never MyISAM). Need FK and transactions.162- **Procedures:** `CALL sp_nome(...)`. Functions: `SELECT fn_nome(...)`. `SIGNAL SQLSTATE` for errors.163- **Anti-patterns:** ❌ `utf8` (use `utf8mb4`), ❌ `RETURNING` (use `LAST_INSERT_ID()`), ❌ MyISAM, ❌ N+1 queries.164165### Intraweb Framework166- **Stateful Web:** Never use global variables (variables declared in the unit interface) for interactive data (they leak cross-session). Save status to `UserSession`.167- Avoid blocking UI code from Classic VCL (`ShowMessage()`, `InputBox()`, Modal calls).168- Give full preference to asynchronous rendering using Ajax interrupts, encoding events in type `OnAsyncClick` instead of standard entire posts.169- Standard component prefixes: always use `iw` base (`iwBtnSave`, `iwEdtUser`).170171---172173## 🧵 Threads and Multi-Threading174175- **Golden Rule:** NEVER access visual components (VCL/FMX) directly from secondary thread. Use `TThread.Synchronize` (blocking) or `TThread.Queue` (non-blocking).176- **Simple tasks:** `TThread.CreateAnonymousThread` or `TTask.Run` (PPL — modern form, managed pool).177- **Parallel loops:** `TParallel.For` to process independent collections. Protect shared variables with `TInterlocked` or `TCriticalSection`.178- **Asynchronous result:** `TFuture<T>` — `.Value` blocks until the result is ready.179- **Thread-Safety:** `TCriticalSection` (Enter/Leave in `finally`), `TMonitor`, `TInterlocked` (atomic operations), `TThreadList<T>`, `TMultiReadExclusiveWriteSynchronizer` (cache).180- **Producer-Consumer:** `TThreadedQueue<T>` with `PushItem`/`PopItem`.181- **Cancellation:** Check `Terminated` in `TThread` loops, or use custom cancellation token.182- **Debugging:** `TThread.NameThreadForDebugging('NomeDaThread')` to facilitate identification in the IDE.183- **Anti-patterns:** ❌ `Sleep()` in the main thread, ❌ `FreeOnTerminate + WaitFor`, ❌ Shared variables without lock, ❌ Unhandled exceptions in threads (they are silent).184185---186187## 🛑 Memory Management and Exception Control188189- **Never suggest code prone to Memory Leaks:** In Delphi, every `TObject` created without `Owner` or outside `Interfaces` (ARC) must **obligatorily** be protected by `try..finally` and `Free` and the keyword `try` must come IMMEDIATELY AFTER its creation. No exception between Create and Try.190- **Do not create instances in parameters directly:** If the `Foo(TObjeto.Create)` calls do not belong to a native release managed by the signed receiver, you must instantiate first, protect with try and send the var.191- **Domain-Based Exception Handling:** Use and create `Exception` Classes customized for your logics.192- **Exception Transparency:** When using the `except` block, be strictly focused on specific exceptions (`on E: EFDDBEngineException do`). If you use the generic `Exception` from scratch, NEVER stop using the pure `raise;` at the end of the exception block so as not to hide technical errors from global Stack Traces.193194---195196## 🚫 Context Scope for Copilot197198### Recommended Context (always relevant)199200- `AGENTS.md`, `README.md`, `.github/copilot-instructions.md`201- `.claude/rules/**/*.md`, `.claude/skills/**/SKILL.md`202- `examples/**/*.pas`, `docs/**/*.md`203204### Excludes (never useful as context)205206- Build artifacts: `*.dcu`, `*.exe`, `*.dll`, `*.bpl`, `*.dcp`, `*.map`207- IDE temporaries: `*.local`, `*.identcache`, `__history/`, `__recovery/`208- Output dirs: `Win32/`, `Win64/`, `Debug/`, `Release/`209- Secrets and noise: `*.key`, `*.pfx`, `.env`, `*.log`, `*.bak`210211> Full strategy: `docs/ai-ignore-strategy.md`. Patterns enforced via `.gitignore`, `.cursorignore` and `.vscode/settings.json`.212213214
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| delphicleancode/delphi-spec-kit.claude/CLAUDE.md · 49 | CLAUDE.md | teststyleperformancedo-not | 60/100 | today | |
| delphicleancode/delphi-spec-kitAGENTS.md · 49 | AGENTS.md | teststylearchtesting-strategy+4 | 61/100 | today |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/delphicleancode-delphi-spec-kit-github-copilot-instructions)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.