RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/delphicleancode/delphi-spec-kit/diff

Two files, one repository

delphicleancode/delphi-spec-kit ships 3 formats across 3 indexed files. The question worth asking is whether the second one says anything the first does not.

CompareAGENTS.md ↔ CLAUDE.mdAGENTS.md ↔ Copilot instructionsCLAUDE.md ↔ Copilot instructions
A · AGENTS.md · 3132 wordsB · .claude/CLAUDE.md · 217 words
What each file covers, counted
DimensionSharedOnly in AOnly in BOverlap
Sections05540%
Commands000—
Section tags44050%

What each file covers

Sections

0 shared · 55 only in A · 4 only in B
  • − Delphi AI Spec-Kit — AGENTS.md
  • − Language and Stack
  • − Naming Conventions — Pascal Guide
  • − General Rule
  • − Mandatory Prefixes
  • − Unit Naming
  • − Method Naming
  • − Unit Test Naming (TDD)
  • − Naming of Forms and DataModules
  • − Components in Forms
  • − DevExpress (DEXT) components in Forms
  • − ACBr Project (Commercial Automation)
  • − Intraweb Components (Web)
  • − REST Frameworks (Horse, DMVC, Dext)
  • − Dext Framework
  • − Horse Framework
  • − DelphiMVCFramework (DMVC)
  • − DevExpress Components
  • − Firebird Database
  • − Mandatory Connection Configuration
  • − Essential Rules Firebird
  • − Firebird Anti-Patterns
  • − PostgreSQL Database
  • − Connection Configuration
  • − Essential Rules PostgreSQL
  • − PostgreSQL Anti-Patterns
  • − MySQL / MariaDB Database
  • − Essential Rules MySQL
  • − MySQL Anti-Patterns
  • − Threads and Multi-Threading
  • − Golden Rule
  • − Threading Approaches
  • − Thread-Safety
  • − Threading Anti-Patterns
  • − SOLID principles in Delphi
  • − S — Single Responsibility Principle (SRP)
  • − O — Open/Closed Principle (OCP)
  • − L — Liskov Substitution Principle (LSP)
  • − I — Interface Segregation Principle (ISP)
  • − D — Dependency Inversion Principle (DIP)
  • − Clean Code — Essential Rules
  • − 1. Short Methods
  • − 2. Self-Descriptive Names
  • − 3. Avoid Magic Numbers
  • − 4. Guard Clauses
  • − 5. Focused and Typed Try/Except
  • − 6. Unit Organization
  • − Recommended Design Patterns
  • − Anti-Patterns to Avoid
  • − Memory Management (Critical)
  • − Documentation
  • − Layer Structure (Architecture)
  • − 🚫 AI Context Policy — What to Include and Exclude
  • − Files AI Must Always Use as Context
  • − Files AI Must Never Use as Context
  • + Delphi AI Spec-Kit
  • + Project Stack
  • + Crucial Directives (Memory Management)
  • + File Organization & Naming (PascalCase)

Commands

neither file has any

Section tags

4 shared · 4 only in A · 0 only in B
  • − architecture
  • − testing-strategy
  • − database
  • − docs
  •   test
  •   code-style
  •   performance
  •   do-not

Line diff

+25 added−714 removed12 unchanged1.7% identical
delphicleancode/delphi-spec-kit · AGENTS.md
@@ −1 @@
1# Delphi AI Spec-Kit — AGENTS.md
2 
3> This file is automatically recognized by **Antigravity**, **GitHub Copilot**, **Cursor** and **Kiro**.
4> It defines the universal rules for Delphi development with AI.
5 
6## Language and Stack
7 
8- **Language:** Object Pascal (Delphi)
9- **Native IDE:** RAD Studio / Delphi
10- **Frameworks:** VCL, FMX, FireDAC
11- **Database:** FireDAC (SQLite, PostgreSQL, Firebird, SQL Server)
12- **Tests:** DUnitX
13- **Build:** MSBuild / Delphi Compiler (dcc32/dcc64)
14- **File extensions:** `.pas` (units), `.dfm`/`.fmx` (forms), `.dpr` (project), `.dpk` (package), `.dproj` (project config)
15 
16## Naming Conventions — Pascal Guide
17 
18### General Rule
19 
20Use **PascalCase** (InfixCaps) for all identifiers. Reserved words are always in **TOK_6__, `end`, `if`, `then`, `else`, `nil`, `string`).
21 
22### Mandatory Prefixes
23 
24| Type | Prefix | Example |
25|------|---------|---------|
26| Class | `T` | `TCustomerRepository` |
27| Interface | `I` | `ICustomerRepository` |
28| Exception | `E` | `ECustomerNotFound` |
29| Private field | `F` | `FCustomerName` |
30| Parameter | `A` | `ACustomerName` |
31| Enumerated type | `T` | `TOrderStatus` |
32| Enum Items | short prefix | `osNew`, `osPending`, `osClosed` |
33 
34### Unit Naming
35 
36```
37NomeProjeto.Camada.Dominio.Funcionalidade.pas
38```
39 
40Examples:
41 
42- `MyApp.Domain.Customer.Entity.pas`
43- `MyApp.Infra.Customer.Repository.pas`
44- `MyApp.Application.Customer.Service.pas`
45- `MyApp.Presentation.Customer.View.pas`
46 
47### Method Naming
48 
49- Action methods: use verbs — `Execute`, `CreateOrder`, `ValidateCustomer`
50- Getters: prefix `Get` — `GetCustomerName`
51- Setters: prefix `Set` — `SetCustomerName`
52- Boolean functions: prefix `Is`, `Has`, `Can` — `IsValid`, `HasPermission`, `CanDelete`
53 
54### Unit Test Naming (TDD)
55 
56- Follow the generic behavioral pattern in DUnitX tests: `Action_Condition_ExpectedResult`
57- Example: `ProcessOrder_WithoutStock_RaisesException`, `CalculateTotal_WithDiscount_ReturnsLowerValue`
58- Create fakes in the test unit with prefix `TFake` (ex: `TFakeInventoryRepository`)
59 
60### Naming of Forms and DataModules
61 
62- Type: `TfrmCustomerEdit`, `TdmDatabase`
63- Variable: `frmCustomerEdit`, `dmDatabase`
64- Unit: `MyApp.Presentation.Customer.Edit.pas`
65 
66### Components in Forms
67 
68Use a 3-letter prefix indicating the type:
69 
70| Component | Prefix | Example |
71|-----------|---------|---------|
72| TButton | `btn` | `btnSave` |
73| TEdit | `edt` | `edtName` |
74| TLabel | `lbl` | `lblName` |
75| TComboBox | `cmb` | `cmbStatus` |
76| TDBGrid | `dbg` | `dbgCustomers` |
77| TPanel | `pnl` | `pnlTop` |
78| TPageControl | `pgc` | `pgcMain` |
79| TTabSheet | `tab` | `tabSearch` |
80| TDataSource | `ds` | `dsCustomers` |
81| TFDQuery | `qry` | `qryCustomers` |
82| TFDConnection | `con` | `conMain` |
83| TMemo | `mmo` | `mmoObservation` |
84| TCheckBox | `chk` | `chkActive` |
85| TDateTimePicker | `dtp` | `dtpBirthDate` |
86| TImage | `img` | `imgPhoto` |
87| TListView | `lvw` | `lvwItems` |
88| TTreeView | `tvw` | `tvwCategories` |
89| TToolBar | `tlb` | `tlbMain` |
90| TActionList | `act` | `actMain` |
91| TPopupMenu | `pmn` | `pmnGrid` |
92| T Hours | `tmr` | `tmrRefresh` |
93| TStatusBar | `stb` | `stbMain` |
94 
95### DevExpress (DEXT) components in Forms
96 
97| Component | Prefix | Example |
98|-----------|---------|---------|
99| TcxGrid | `grd` | `grdCustomers` |
100| TcxGridDBTableView | `tvw` | `tvwCustomers` |
101| TcxDBTreeList | `trl` | `trlCategories` |
102| TdxLayoutControl | `lyt` | `lytMain` |
103| TdxLayoutGroup | `lgrp` | `lgrpPersonal` |
104| TdxLayoutItem | `litm` | `litmName` |
105| TcxDBTextEdit | `edt` | `edtName` |
106| TcxDBComboBox | `cmb` | `cmbStatus` |
107| TcxDBDateEdit | `dte` | `dtpBirthDate` |
108| TcxDBCurrencyEdit | `cur` | `curPrice` |
109| TcxDBLookupComboBox | `lcb` | `lcbCity` |
110| TdxBarManager | `bar` | `barMain` |
111| TdxRibbon | `rbn` | `rbnMain` |
112| TdxSkinController | `skn` | `sknController` |
113 
114### ACBr Project (Commercial Automation)
115 
116| Component | Prefix | Example |
117|-----------|---------|---------|
118| TACBrNFe | `acbrNFe` | `acbrNFe1` ou `acbrNfeEmissor` |
119| TACBrCTe | `acbrCte` | `acbrCteMain` |
120| TACBrBoleto | `acbrBoleto` | `acbrBoletoCob` |
121| TACBrTEFD | `acbrTef` | `acbrTefVisa` |
122| TACBrPosPrinter | `acbrPosPrinter`| `acbrPosPrinterCaixa` |
123| TACBrSAT | `acbrSat` | `acbrSatFiscal` |
124| TACBrCEP | `acbrCep` | `acbrCepBusca` |
125 
126**ACBr Note:** Avoid trapping the UI directly in component interactive events. Isolate tax logic.
127 
128### Intraweb Components (Web)
129 
130| Component | Prefix | Example |
131|-----------|---------|---------|
132| TIWAppForm | `iwForm`| `iwFormLogin` |
133| TIWButton | `iwBtn` | `iwBtnSave` |
134| TIWEdit | `iwEdt` | `iwEdtName` |
135| TIWLabel | `iwLbl` | `iwLblTitle` |
136| TIWComboBox | `iwCmb` | `iwCmbStatus` |
137| TIWGrid | `iwGrd` | `iwGrdItems` |
138| TIWRegion | `iwReg` | `iwRegContainer` |
139 
140**Intraweb Note:** Avoid global unit variables to control user state. Always store transient data in `UserSession` to avoid leaks between sessions.
141 
142## REST Frameworks (Horse, DMVC, Dext)
143 
144### Dext Framework
145 
146Dext (<https://github.com/cesarliws/dext>) is an enterprise landmark inspired by the .NET ecosystem. Conventions:
147 
148- **Minimal APIs:** Use `App.Builder.MapGet` with Auto-Binding for DTOs
149- **Dependency Injection:** Mandatory. Inject into endpoints: `function(Dto: MyDto; Rep: ICustomerRepository): IResult`
150- **Entity ORM:** LINQ type queries (`DbContext.Where(U.Age > 18)`). Do not use queries in pure SQL chained.
151- **Async:** Use `TAsyncTask.Run` from `Dext.Core.Tasks`.
152- **Results:** Return typed frameworks or Records directly, serialized as JSON.
153 
154### Horse Framework
155 
156Horse is a minimalist REST framework for Delphi (Express style). Conventions:
157 
158- **Controller:** Class with `class procedure RegisterRoutes`
159- **Handler:** `class procedure Nome(AReq: THorseRequest; ARes: THorseResponse; ANext: TProc)`
160- **Middleware:** `procedure Nome(AReq: THorseRequest; ARes: THorseResponse; ANext: TProc)`
161- **Routes:** Kebab-case, plural — `/api/customers`, `/api/order-items`
162- **JSON:** Use `Jhonson` middleware for automatic serialization
163- **CORS:** Use `Horse.CORS` middleware
164- **Structure:** Controllers separated from Services, Services separated from Repositories
165- **Packages:** `boss install horse horse-jhonson horse-cors horse-jwt`
166 
167### DelphiMVCFramework (DMVC)
168 
169DMVC is a classic MVC framework with Active Record, JWT and Swagger:
170 
171- **Controller:** Inherits from `TMVCController` with `[MVCPath]` attribute
172- **Routes:** Attributes — `[MVCPath]`, `[MVCHTTPMethod]`, `[MVCProduces]`, `[MVCConsumes]`
173- **Active Record:** Inherits from `TMVCActiveRecord` with `[MVCTable]`, `[MVCTableField]`
174- **Serialization:** Automatic via `Render()` (JSON by default)
175- **WebModule:** `TMVCEngine` created in WebModule with controllers and middleware
176- **JWT:** `TMVCJWTAuthenticationMiddleware` built-in
177- **RQL:** Resource Query Language for filters via query string
178 
179### DevExpress Components
180 
181Advanced visual components for VCL:
182 
183- **Grid:** `TcxGrid` with `TcxGridDBTableView` (data-aware)
184- **Layout:** `TdxLayoutControl` for responsive forms
185- **Skins:** `TdxSkinController` for global themes
186- **Export:** `cxGridExportLink` to Excel/PDF
187- **Filters:** `DataController.Filter` for programmatic filters
188 
189## Firebird Database
190 
191Firebird is the most used corporate database with Delphi. Access via **FireDAC** (driver `FB`).
192 
193### Mandatory Connection Configuration
194 
195```pascal
196FConnection.DriverName := 'FB';
197FConnection.Params.Values['CharacterSet'] := 'UTF8'; //ALWAYS UTF8
198FConnection.Params.Values['SQLDialect'] := '3'; //NEVER Dialect 1
199FConnection.Params.Values['Protocol'] := 'TCPIP'; //Or 'Local' for embedded
200FConnection.Params.Values['PageSize'] := '16384'; // 16KB recomendado
201FConnection.TxOptions.Isolation := xiReadCommitted; //Standard isolation
202```
203 
204### Essential Rules Firebird
205 
206- **Dialect 3 ALWAYS** — Dialect 1 is InterBase legacy and causes ambiguity with `DATE`
207- **CharacterSet UTF8** — required for correct accent support
208- **Parameterized queries** — never concatenate strings in SQL
209- **RETURNING with Open** — `INSERT ... RETURNING id` requires `LQuery.Open`, not `ExecSQL`
210- **Generators** for auto-increment with `BEFORE INSERT` triggers
211- **Domains** to centralize types and validations in the schema
212- **Stored Procedures:** Selectable (with `SUSPEND`) uses `SELECT FROM SP`; Executable uses `EXECUTE PROCEDURE`
213- **Explicit transactions** for compound operations (StartTransaction/Commit/Rollback)
214- **Treat deadlocks** via `EFDDBEngineException.Kind = ekRecordLocked`
215 
216### Firebird Anti-Patterns
217 
218- ❌ `SQLDialect := '1'` — ALWAYS use `'3'`
219- ❌ `ExecSQL` with `RETURNING` — use `Open`
220- ❌ Concatenate SQL — use parameters
221- ❌ Ignore `CharacterSet` — set `UTF8`
222- ❌ `PAGE_SIZE 4096` — use `16384` for production
223- ❌ Bypass deadlocks — handle `ekRecordLocked`
224- ❌ `CREATE TABLE IF NOT EXISTS` — does not exist in Firebird (check via `RDB$RELATIONS`)
225 
226> **Skills:** `.gemini/skills/firebird-database/SKILL.md`
227> **Rules:** `.cursor/rules/firebird-patterns.md`
228 
229## PostgreSQL Database
230 
231PostgreSQL is the most advanced open-source database, ideal for modern projects. Access via **FireDAC** (driver `PG`).
232 
233### Connection Configuration
234 
235```pascal
236FConnection.DriverName := 'PG';
237FConnection.Params.Values['Server'] := 'localhost';
238FConnection.Params.Values['Port'] := '5432';
239FConnection.Params.Database := 'meubanco';
240FConnection.Params.UserName := 'postgres';
241FConnection.Params.Password := 'senha';
242FConnection.Params.Values['CharacterSet'] := 'UTF8';
243FConnection.TxOptions.Isolation := xiReadCommitted;
244```
245 
246### Essential Rules PostgreSQL
247 
248- **IDENTITY instead of SERIAL** — use `GENERATED ALWAYS AS IDENTITY` for new projects (PG 10+)
249- **RETURNING with Open** — `INSERT ... RETURNING id` requires `LQuery.Open`, not `ExecSQL`
250- **native UPSERT** — `INSERT ... ON CONFLICT (col) DO UPDATE SET ...`
251- **JSONB** — for semi-structured data, indexable with GIN
252- **ENUM types** — `CREATE TYPE status AS ENUM ('active', 'inactive')` mapped to Pascal enum
253- **PL/pgSQL** — Functions (`RETURNS TABLE` = Selectable), Procedures (`CALL`, PG 11+)
254- **Explicit transactions** — `StartTransaction/Commit/Rollback`, supports `SAVEPOINT`
255- **Full-Text Search** — `tsvector` + `tsquery` with GIN index
256- **Metadata via `information_schema`** — do not use `RDB$` (this is Firebird)
257 
258### PostgreSQL Anti-Patterns
259 
260- ❌ Concatenate SQL — use parameterized parameters
261- ❌ `ExecSQL` with `RETURNING` — use `Open`
262- ❌ `SERIAL` in new projects — use `IDENTITY`
263- ❌ `SELECT *` in large tables — select required columns
264- ❌ N+1 queries — use JOIN or subquery
265- ❌ Save JSON as TEXT — use `JSONB`
266- ❌ Ignore indexes on WHERE/JOIN columns
267 
268> **Skills:** `.gemini/skills/postgresql-database/SKILL.md`
269> **Rules:** `.cursor/rules/postgresql-patterns.md`
270 
271## MySQL / MariaDB Database
272 
273MySQL is the most popular open-source database in the world. MariaDB is a compatible fork. Access via **FireDAC** (driver `MySQL`).
274 
275### Connection Configuration
276 
277```pascal
278FConnection.DriverName := 'MySQL';
279FConnection.Params.Values['Server'] := 'localhost';
280FConnection.Params.Values['Port'] := '3306';
281FConnection.Params.Database := 'meubanco';
282FConnection.Params.UserName := 'root';
283FConnection.Params.Password := 'senha';
284FConnection.Params.Values['CharacterSet'] := 'utf8mb4'; //NEVER 'utf8' (only 3 bytes!)
285FConnection.TxOptions.Isolation := xiReadCommitted;
286```
287 
288### Essential Rules MySQL
289 
290- **`utf8mb4` ALWAYS** — `utf8` in MySQL only has 3 bytes (does not support emoji). Use `utf8mb4`
291- **AUTO_INCREMENT + LAST_INSERT_ID()** — MySQL does NOT support `RETURNING`. Get ID via `LAST_INSERT_ID()`
292- **native UPSERT** — `INSERT ... ON DUPLICATE KEY UPDATE`
293- **Native JSON** — `JSON` type with `->>`/`JSON_EXTRACT` operators (MySQL 5.7+)
294- **InnoDB ALWAYS** — never MyISAM in new projects (needs FK and transactions)
295- **Stored Procedures** — `CALL sp_nome(...)` for procedures, `SELECT fn_nome(...)` for functions
296- **Explicit transactions** — `StartTransaction/Commit/Rollback`, supports `SAVEPOINT`
297- **COLLATE** — `utf8mb4_unicode_ci` for correct case-insensitive comparison
298- **Metadata via `information_schema`** — use `DATABASE()` for current schema
299 
300### MySQL Anti-Patterns
301 
302- ❌ `utf8` as charset — use `utf8mb4`
303- ❌ Try `RETURNING` — does not exist, use `LAST_INSERT_ID()`
304- ❌ `MyISAM` in new tables — use `InnoDB`
305- ❌ Concatenate SQL — use parameters
306- ❌ `SELECT *` without `LIMIT` — page results
307- ❌ N+1 queries — use JOIN or subquery
308- ❌ Ignore indexes on WHERE/JOIN columns
309 
310> **Skills:** `.gemini/skills/mysql-database/SKILL.md`
311> **Rules:** `.cursor/rules/mysql-patterns.md`
312 
313## Threads and Multi-Threading
314 
315Threads are essential for keeping the UI responsive and processing data in parallel. Delphi offers `TThread`, PPL (`TTask`, `TParallel.For`, `TFuture<T>`) and synchronization primitives.
316 
317### Golden Rule
318 
319> **NEVER access visual components (VCL/FMX) directly from a secondary thread.**
320> Use `TThread.Synchronize` (blocking) or `TThread.Queue` (non-blocking) to update the UI.
321 
322### Threading Approaches
323 
324| Approach | When to Use |
325|-----------|-------------|
326| `TThread.CreateAnonymousThread` | Simple, one-shot tasks |
327| `TTask.Run` (PPL) | Modern way, managed pool |
328| `TParallel.For` | Parallel loop in independent collections |
329| `TFuture<T>` | Asynchronous result with return value |
330| `TThread` (inheritance) | Permanent workers, queues, servers |
331 
332### Thread-Safety
333 
334- **`TCriticalSection`** — Classic critical section (`Enter`/`Leave` ALWAYS in `finally`)
335- **`TMonitor`** — Native object lock (`Enter`/`Exit`)
336- **`TInterlocked`** — Atomic operations (`Increment`, `Decrement`, `Exchange`)
337- **`TThreadList<T>`** — Thread-safe list with `LockList`/`UnlockList`
338- **`TMultiReadExclusiveWriteSynchronizer`** — Cache: multiple reads, few writes
339- **`TThreadedQueue<T>`** — Thread-safe queue for Producer-Consumer
340 
341### Threading Anti-Patterns
342 
343- ❌ Access VCL/FMX directly from secondary thread
344- ❌ `Sleep()` in the main thread (freezes the UI!)
345- ❌ `FreeOnTerminate := True` + `WaitFor` (crash!)
346- ❌ Access shared variables without locking
347- ❌ Ignore exceptions in threads (they are silent!)
348- ❌ `TCriticalSection.Leave` fora de `finally`
349 
350> **Skills:** `.gemini/skills/threading/SKILL.md`
351> **Rules:** `.cursor/rules/threading-patterns.md`
352 
353## SOLID principles in Delphi
354 
355### S — Single Responsibility Principle (SRP)
356 
357Each unit and each class must have **a single responsibility**:
358 
359```pascal
360//✅ GOOD — separate responsibilities
361TCustomerValidator = class
362 function Validate(ACustomer: TCustomer): TValidationResult;
363end;
364 
365TCustomerRepository = class(TInterfacedObject, ICustomerRepository)
366 function FindById(AId: Integer): TCustomer;
367 procedure Save(ACustomer: TCustomer);
368end;
369 
370//❌ BAD — class doing it all
371TCustomer = class
372 procedure Validate; //should be a Validator
373 procedure SaveToDb; //should be a Repository
374 procedure SendEmail; //should be a Service
375end;
376```
377 
378### O — Open/Closed Principle (OCP)
379 
380Classes should be **open for extension**, closed for modification. Use inheritance and interfaces:
381 
382```pascal
383type
384 IReportExporter = interface
385 procedure Export(AReport: TReport);
386 end;
387 
388 TPdfExporter = class(TInterfacedObject, IReportExporter)
389 procedure Export(AReport: TReport);
390 end;
391 
392 TExcelExporter = class(TInterfacedObject, IReportExporter)
393 procedure Export(AReport: TReport);
394 end;
395```
396 
397### L — Liskov Substitution Principle (LSP)
398 
399Subtypes must be replaceable with the base type without breaking behavior:
400 
401```pascal
402//✅ GOOD — any ICustomerRepository works
403procedure TCustomerService.LoadCustomer(ARepo: ICustomerRepository);
404begin
405 //works with TFireDACCustomerRepo, TMemoryCustomerRepo, TMockCustomerRepo
406 FCustomer := ARepo.FindById(FCustomerId);
407end;
408```
409 
410### I — Interface Segregation Principle (ISP)
411 
412Small, cohesive interfaces, not "fat" interfaces:
413 
414```pascal
415//✅ GOOD — segregated interfaces
416type
417 IReadableRepository<T> = interface
418 function FindById(AId: Integer): T;
419 function FindAll: TObjectList<T>;
420 end;
421 
422 IWritableRepository<T> = interface
423 procedure Save(AEntity: T);
424 procedure Delete(AId: Integer);
425 end;
426 
427 ICustomerRepository = interface(IReadableRepository<TCustomer>)
428 ['{GUID}']
429 function FindByCpf(const ACpf: string): TCustomer;
430 end;
431```
432 
433### D — Dependency Inversion Principle (DIP)
434 
435Depend on **abstractions** (interfaces), not concrete implementations. Use **constructor injection**:
436 
437```pascal
438type
439 TOrderService = class
440 private
441 FOrderRepo: IOrderRepository;
442 FNotifier: INotificationService;
443 public
444 constructor Create(AOrderRepo: IOrderRepository; ANotifier: INotificationService);
445 procedure PlaceOrder(AOrder: TOrder);
446 end;
447 
448constructor TOrderService.Create(AOrderRepo: IOrderRepository; ANotifier: INotificationService);
449begin
450 inherited Create;
451 FOrderRepo := AOrderRepo;
452 FNotifier := ANotifier;
453end;
454```
455 
456## Clean Code — Essential Rules
457 
458### 1. Short Methods
459 
460- Maximum **20 lines** per method (ideal: 5-10)
461- If a method needs a comment explaining "what it does", it should be extracted into a method with a descriptive name
462 
463### 2. Self-Descriptive Names
464 
465```pascal
466//❌ SPACIOUS
467procedure Proc1(S: string; N: Integer);
468function Calc(V: Double): Double;
469 
470// ✅ BOM
471procedure SendNotificationEmail(const ARecipientEmail: string; ATemplateId: Integer);
472function CalculateDiscountedPrice(AOriginalPrice: Double): Double;
473```
474 
475### 3. Avoid Magic Numbers
476 
477```pascal
478//❌ SPACIOUS
479if ACustomer.Age > 18 then
480 
481// ✅ BOM
482const
483 MINIMUM_AGE = 18;
484// ...
485if ACustomer.Age > MINIMUM_AGE then
486```
487 
488### 4. Guard Clauses
489 
490```pascal
491//❌ BAD — excessive nesting
492procedure ProcessOrder(AOrder: TOrder);
493begin
494 if Assigned(AOrder) then
495 begin
496 if AOrder.Items.Count > 0 then
497 begin
498 if AOrder.IsValid then
499 begin
500 //real logic here
501 end;
502 end;
503 end;
504end;
505 
506//✅ BOM — guard clauses
507procedure ProcessOrder(AOrder: TOrder);
508begin
509 if not Assigned(AOrder) then
510 raise EArgumentNilException.Create('AOrder cannot be nil');
511 if AOrder.Items.Count = 0 then
512 raise EBusinessRuleException.Create('Order must have at least one item');
513 if not AOrder.IsValid then
514 raise EValidationException.Create('Order validation failed');
515 
516 //real logic here — no nesting
517end;
518```
519 
520### 5. Focused and Typed Try/Except
521 
522```pascal
523//❌ BAD — generic catch swallowing critical errors (Access Violation, OOM)
524try
525 //large block of long code
526except
527 on E: Exception do //Or worse: without declaring "on E:"
528 ShowMessage(E.Message);
529end;
530 
531//✅ GOOD — specific exceptions and granular recovery
532try
533 FConnection.Open;
534 PerformCriticalAction;
535except
536 on E: EFDDBEngineException do
537 raise EDatabaseConnectionException.Create('Falha local no banco: ' + E.Message);
538 on E: EBusinessRuleException do
539 raise; //Pass the exception to the Controller to catch
540 on E: Exception do
541 begin
542 Logger.LogError('Critical unexpected failure', E);
543 raise; //NEVER hide pure root Exception exceptions without rethrowing!
544 end;
545end;
546```
547 
548### 6. Unit Organization
549 
550```pascal
551unit MyApp.Domain.Customer.Entity;
552 
553interface
554 
555uses
556 System.SysUtils,
557 System.Classes,
558 System.Generics.Collections;
559 
560type
561 //1. Types, enums and records first
562 TCustomerStatus = (csActive, csInactive, csSuspended);
563 
564 //2. Interfaces
565 ICustomer = interface
566 ['{GUID}']
567 function GetName: string;
568 property Name: string read GetName;
569 end;
570 
571 //3. Classes
572 TCustomer = class(TInterfacedObject, ICustomer)
573 private
574 FId: Integer;
575 FName: string;
576 FStatus: TCustomerStatus;
577 function GetName: string;
578 public
579 //Constructor and Destructor first
580 constructor Create(const AName: string);
581 destructor Destroy; override;
582 
583 //After public methods
584 function IsActive: Boolean;
585 procedure Activate;
586 procedure Deactivate;
587 
588 //Properties last
589 property Id: Integer read FId write FId;
590 property Name: string read GetName;
591 property Status: TCustomerStatus read FStatus;
592 end;
593 
594implementation
595 
596{ TCustomer }
597 
598constructor TCustomer.Create(const AName: string);
599begin
600 inherited Create;
601 if AName.Trim.IsEmpty then
602 raise EArgumentException.Create('Customer name cannot be empty');
603 FName := AName.Trim;
604 FStatus := csActive;
605end;
606 
607//... other implementations
608```
609 
610## Recommended Design Patterns
611 
612| Standard | Use in Delphi |
613|--------|---------------|
614| **Repository** | Abstracts data access via interface (FireDAC, REST, etc.) |
615| **Service** | Contains business logic orchestrating repositories and other services |
616| **Factory** | Creates instances of complex objects or with dependencies |
617| **Observer** | Use `TNotifyEvent` or interfaces to decouple notifications |
618| **Strategy** | Interfaces to vary algorithms (e.g. tax calculation) |
619| **Unit of Work** | Manages database transactions |
620 
621## Anti-Patterns to Avoid
622 
623- ❌ **God class / God unit** — units with thousands of lines doing everything
624- ❌ **Direct coupling to forms** — business logic in `OnClick` of buttons
625- ❌ **Uses circular** — resolved by separating into layers (Domain, Infra, Application, Presentation)
626- ❌ **Global variables** — use dependency injection
627- ❌ **Hardcoded Strings** — use `resourcestring` or constants
628- ❌ **Ignoring memory management** — always free unmanaged objects by reference
629- ❌ **`with` statement** — avoid `with` as it reduces readability and makes debugging difficult
630- ❌ **Testing in Banco Real** — attach DUnitX projects directly to `TFDConnection`, skipping Mocks/Fakes.
631 
632## Memory Management (Critical)
633 
634- **Watched Blocks:** The golden rule in Delphi: Whenever there is code calling `.Create` for instances of TObject Classes, the IMMEDIATELY subsequent line must be a `try`. NO intermediate lines of code!
635 
636```pascal
637//✅ The Gold Standard for Disposable Objects
638var LList: TStringList;
639begin
640 LList := TStringList.Create;
641 try
642 LList.Add('item');
643 // ...
644 finally
645 LList.Free; //i FreeAndNil(LList)
646 end;
647end;
 
 
 
 
648 
649//✅ Objects with owner - VCL/FMX components
650TMyComponent := TMyComponent.Create(Self); //Owner (Self) assumes release
 
 
 
 
 
 
651 
652//✅ Garbage Collection com Interfaces (ARC)
653//The object will be automatically cleaned up at the end of the scope, eliminating the need for try..free
654var LService: IMyService;
655begin
656 LService := TMyService.Create;
657 LService.DoSomething;
658end;
659 
660//✅ Local variables: use L prefix
661var LCustomer: TCustomer;
662```
663 
664## Documentation
665 
666- Use **XMLDoc** for public methods and interfaces:
667 
668```pascal
669///<summary>
670///Locates a customer by the CPF entered.
671///</summary>
672///<param name="ACpf">Customer CPF (numbers only)</param>
673///<returns>TCustomer instance or nil if not found</returns>
674///<exception cref="EArgumentException">If ACpf is empty</exception>
675function FindByCpf(const ACpf: string): TCustomer;
676```
677 
678- Comments in **Portuguese** for Brazilian projects
679- Don't comment obvious code — let the method name explain
680 
681## Layer Structure (Architecture)
682 
683```
684src/
685├── Domain/ ← Entidades, Value Objects, Interfaces de repositório
686├── Application/ ← Services, Use Cases, DTOs
687├── Infrastructure/ ← Implementações de repositório (FireDAC), APIs externas
688└── Presentation/ ← Forms (VCL/FMX), ViewModels
689tests/
690└── Unit/ ← Projetos DUnitX e Fakes/Mocks isolados por contexto
691```
692 
693> **Dependency rule:** `Presentation → Application → Domain ← Infrastructure`
694> The Domain **never** depends on other layers. `tests` depend on `Application` and `Domain` but inject Fake implementations by copying `Infrastructure` alone.
695 
696---
697 
698## 🚫 AI Context Policy — What to Include and Exclude
699 
700> Full strategy documented in `docs/ai-ignore-strategy.md`.
701 
702### Files AI Must Always Use as Context
703 
704- `AGENTS.md` — universal rules
705- `README.md` — project overview
706- `.github/copilot-instructions.md` — Copilot pre-prompt
707- `.claude/CLAUDE.md` — Claude master prompt
708- `.claude/rules/**/*.md` — context-specific rules
709- `.claude/skills/**/SKILL.md` — on-demand skills
710- `.cursor/rules/**/*.md` — Cursor rules
711- `.gemini/skills/**/SKILL.md` — Gemini skills
712- `.kiro/steering/**/*.md` — Kiro steering docs
713- `examples/**/*.pas` — good practice examples
714- `docs/**/*.md` — documentation
715 
716### Files AI Must Never Use as Context
717 
718- Build artifacts: `*.dcu`, `*.exe`, `*.dll`, `*.bpl`, `*.dcp`, `*.map`, `*.res`
719- IDE temporaries: `*.local`, `*.identcache`, `*.stat`, `__history/`, `__recovery/`
720- Output directories: `Win32/`, `Win64/`, `Debug/`, `Release/`, `build/`, `dist/`
721- Secrets: `*.key`, `*.pfx`, `*.p12`, `.env`, `.env.*`
722- Noise: `*.log`, `*.dmp`, `*.bak`, `*.tmp`
723 
724See `.cursorignore`, `.gitignore` and `.vscode/settings.json` for the enforced patterns.
725 
726 
delphicleancode/delphi-spec-kit · .claude/CLAUDE.md
@@ +1 @@
1# Delphi AI Spec-Kit
2 
3This is the **Delphi AI Spec-Kit**, the master guide for Delphi (Object Pascal) development in this repository.
 
4 
5## Project Stack
 
6- **Language:** Object Pascal (Delphi)
7- **Native IDE:** RAD Studio / Delphi
8- **Main Frameworks:** VCL, FMX, FireDAC
 
9- **Tests:** DUnitX
10- **Build / Tooling:** MSBuild, dcc32/dcc64, Boss (Package Manager)
 
11 
12## Crucial Directives (Memory Management)
13- **Watched Blocks (Required):** EVERYTHING you instantiate with `.Create` (if it is `TObject` and does not have `Owner`) **MUST** have a `try..finally` on the IMMEDIATELY subsequent line.
14 ```pascal
15 Obj := TMyClass.Create;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16 try
17 Obj.DoSomething;
 
18 finally
19 Obj.Free; //my FreeAndNil(Obj)
20 end;
21 ```
22- **DO NOT use** `with`.
23- **DO NOT create** God Classes. Use SOLID Principles.
24- Isolate visual components (FMX/VCL) from strict business rules. Do not access DBGrid or form edits in pure logical units.
25- For dependency injection, pass abstractions in the constructor.
26 
27## File Organization & Naming (PascalCase)
28- Classes: Start with `T` (ex: `TCustomer`).
29- Interfaces: Start with `I` (ex: `ICustomer`).
30- Exceptions: Start with `E` (ex: `EValidationError`).
31- Private attributes or fields: Start with `F` (ex: `FName`).
32- Local variables: Start with `L` (ex: `LCustomer`).
33- Parameters: Start with `A` (ex: `ACustomer`).
34- Unit nomenclature: `NomeProjeto.Camada.Dominio.Funcionalidade.pas`
35 
36*(See the `AGENTS.md` global file and `rules/` folder for guidelines specific to frameworks such as FireDAC, Rest, Horse and Database).*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37 
@@ −1 +1 @@
1−# Delphi AI Spec-Kit — AGENTS.md
1+# Delphi AI Spec-Kit
22  
3−> This file is automatically recognized by **Antigravity**, **GitHub Copilot**, **Cursor** and **Kiro**.
4−> It defines the universal rules for Delphi development with AI.
3+This is the **Delphi AI Spec-Kit**, the master guide for Delphi (Object Pascal) development in this repository.
54  
6−## Language and Stack
7− 
5+## Project Stack
86 - **Language:** Object Pascal (Delphi)
97 - **Native IDE:** RAD Studio / Delphi
10−- **Frameworks:** VCL, FMX, FireDAC
11−- **Database:** FireDAC (SQLite, PostgreSQL, Firebird, SQL Server)
8+- **Main Frameworks:** VCL, FMX, FireDAC
129 - **Tests:** DUnitX
13−- **Build:** MSBuild / Delphi Compiler (dcc32/dcc64)
14−- **File extensions:** `.pas` (units), `.dfm`/`.fmx` (forms), `.dpr` (project), `.dpk` (package), `.dproj` (project config)
10+- **Build / Tooling:** MSBuild, dcc32/dcc64, Boss (Package Manager)
1511  
16−## Naming Conventions — Pascal Guide
17− 
18−### General Rule
19− 
20−Use **PascalCase** (InfixCaps) for all identifiers. Reserved words are always in **TOK_6__, `end`, `if`, `then`, `else`, `nil`, `string`).
21− 
22−### Mandatory Prefixes
23− 
24−| Type | Prefix | Example |
25−|------|---------|---------|
26−| Class | `T` | `TCustomerRepository` |
27−| Interface | `I` | `ICustomerRepository` |
28−| Exception | `E` | `ECustomerNotFound` |
29−| Private field | `F` | `FCustomerName` |
30−| Parameter | `A` | `ACustomerName` |
31−| Enumerated type | `T` | `TOrderStatus` |
32−| Enum Items | short prefix | `osNew`, `osPending`, `osClosed` |
33− 
34−### Unit Naming
35− 
36−```
37−NomeProjeto.Camada.Dominio.Funcionalidade.pas
38−```
39− 
40−Examples:
41− 
42−- `MyApp.Domain.Customer.Entity.pas`
43−- `MyApp.Infra.Customer.Repository.pas`
44−- `MyApp.Application.Customer.Service.pas`
45−- `MyApp.Presentation.Customer.View.pas`
46− 
47−### Method Naming
48− 
49−- Action methods: use verbs — `Execute`, `CreateOrder`, `ValidateCustomer`
50−- Getters: prefix `Get` — `GetCustomerName`
51−- Setters: prefix `Set` — `SetCustomerName`
52−- Boolean functions: prefix `Is`, `Has`, `Can` — `IsValid`, `HasPermission`, `CanDelete`
53− 
54−### Unit Test Naming (TDD)
55− 
56−- Follow the generic behavioral pattern in DUnitX tests: `Action_Condition_ExpectedResult`
57−- Example: `ProcessOrder_WithoutStock_RaisesException`, `CalculateTotal_WithDiscount_ReturnsLowerValue`
58−- Create fakes in the test unit with prefix `TFake` (ex: `TFakeInventoryRepository`)
59− 
60−### Naming of Forms and DataModules
61− 
62−- Type: `TfrmCustomerEdit`, `TdmDatabase`
63−- Variable: `frmCustomerEdit`, `dmDatabase`
64−- Unit: `MyApp.Presentation.Customer.Edit.pas`
65− 
66−### Components in Forms
67− 
68−Use a 3-letter prefix indicating the type:
69− 
70−| Component | Prefix | Example |
71−|-----------|---------|---------|
72−| TButton | `btn` | `btnSave` |
73−| TEdit | `edt` | `edtName` |
74−| TLabel | `lbl` | `lblName` |
75−| TComboBox | `cmb` | `cmbStatus` |
76−| TDBGrid | `dbg` | `dbgCustomers` |
77−| TPanel | `pnl` | `pnlTop` |
78−| TPageControl | `pgc` | `pgcMain` |
79−| TTabSheet | `tab` | `tabSearch` |
80−| TDataSource | `ds` | `dsCustomers` |
81−| TFDQuery | `qry` | `qryCustomers` |
82−| TFDConnection | `con` | `conMain` |
83−| TMemo | `mmo` | `mmoObservation` |
84−| TCheckBox | `chk` | `chkActive` |
85−| TDateTimePicker | `dtp` | `dtpBirthDate` |
86−| TImage | `img` | `imgPhoto` |
87−| TListView | `lvw` | `lvwItems` |
88−| TTreeView | `tvw` | `tvwCategories` |
89−| TToolBar | `tlb` | `tlbMain` |
90−| TActionList | `act` | `actMain` |
91−| TPopupMenu | `pmn` | `pmnGrid` |
92−| T Hours | `tmr` | `tmrRefresh` |
93−| TStatusBar | `stb` | `stbMain` |
94− 
95−### DevExpress (DEXT) components in Forms
96− 
97−| Component | Prefix | Example |
98−|-----------|---------|---------|
99−| TcxGrid | `grd` | `grdCustomers` |
100−| TcxGridDBTableView | `tvw` | `tvwCustomers` |
101−| TcxDBTreeList | `trl` | `trlCategories` |
102−| TdxLayoutControl | `lyt` | `lytMain` |
103−| TdxLayoutGroup | `lgrp` | `lgrpPersonal` |
104−| TdxLayoutItem | `litm` | `litmName` |
105−| TcxDBTextEdit | `edt` | `edtName` |
106−| TcxDBComboBox | `cmb` | `cmbStatus` |
107−| TcxDBDateEdit | `dte` | `dtpBirthDate` |
108−| TcxDBCurrencyEdit | `cur` | `curPrice` |
109−| TcxDBLookupComboBox | `lcb` | `lcbCity` |
110−| TdxBarManager | `bar` | `barMain` |
111−| TdxRibbon | `rbn` | `rbnMain` |
112−| TdxSkinController | `skn` | `sknController` |
113− 
114−### ACBr Project (Commercial Automation)
115− 
116−| Component | Prefix | Example |
117−|-----------|---------|---------|
118−| TACBrNFe | `acbrNFe` | `acbrNFe1` ou `acbrNfeEmissor` |
119−| TACBrCTe | `acbrCte` | `acbrCteMain` |
120−| TACBrBoleto | `acbrBoleto` | `acbrBoletoCob` |
121−| TACBrTEFD | `acbrTef` | `acbrTefVisa` |
122−| TACBrPosPrinter | `acbrPosPrinter`| `acbrPosPrinterCaixa` |
123−| TACBrSAT | `acbrSat` | `acbrSatFiscal` |
124−| TACBrCEP | `acbrCep` | `acbrCepBusca` |
125− 
126−**ACBr Note:** Avoid trapping the UI directly in component interactive events. Isolate tax logic.
127− 
128−### Intraweb Components (Web)
129− 
130−| Component | Prefix | Example |
131−|-----------|---------|---------|
132−| TIWAppForm | `iwForm`| `iwFormLogin` |
133−| TIWButton | `iwBtn` | `iwBtnSave` |
134−| TIWEdit | `iwEdt` | `iwEdtName` |
135−| TIWLabel | `iwLbl` | `iwLblTitle` |
136−| TIWComboBox | `iwCmb` | `iwCmbStatus` |
137−| TIWGrid | `iwGrd` | `iwGrdItems` |
138−| TIWRegion | `iwReg` | `iwRegContainer` |
139− 
140−**Intraweb Note:** Avoid global unit variables to control user state. Always store transient data in `UserSession` to avoid leaks between sessions.
141− 
142−## REST Frameworks (Horse, DMVC, Dext)
143− 
144−### Dext Framework
145− 
146−Dext (<https://github.com/cesarliws/dext>) is an enterprise landmark inspired by the .NET ecosystem. Conventions:
147− 
148−- **Minimal APIs:** Use `App.Builder.MapGet` with Auto-Binding for DTOs
149−- **Dependency Injection:** Mandatory. Inject into endpoints: `function(Dto: MyDto; Rep: ICustomerRepository): IResult`
150−- **Entity ORM:** LINQ type queries (`DbContext.Where(U.Age > 18)`). Do not use queries in pure SQL chained.
151−- **Async:** Use `TAsyncTask.Run` from `Dext.Core.Tasks`.
152−- **Results:** Return typed frameworks or Records directly, serialized as JSON.
153− 
154−### Horse Framework
155− 
156−Horse is a minimalist REST framework for Delphi (Express style). Conventions:
157− 
158−- **Controller:** Class with `class procedure RegisterRoutes`
159−- **Handler:** `class procedure Nome(AReq: THorseRequest; ARes: THorseResponse; ANext: TProc)`
160−- **Middleware:** `procedure Nome(AReq: THorseRequest; ARes: THorseResponse; ANext: TProc)`
161−- **Routes:** Kebab-case, plural — `/api/customers`, `/api/order-items`
162−- **JSON:** Use `Jhonson` middleware for automatic serialization
163−- **CORS:** Use `Horse.CORS` middleware
164−- **Structure:** Controllers separated from Services, Services separated from Repositories
165−- **Packages:** `boss install horse horse-jhonson horse-cors horse-jwt`
166− 
167−### DelphiMVCFramework (DMVC)
168− 
169−DMVC is a classic MVC framework with Active Record, JWT and Swagger:
170− 
171−- **Controller:** Inherits from `TMVCController` with `[MVCPath]` attribute
172−- **Routes:** Attributes — `[MVCPath]`, `[MVCHTTPMethod]`, `[MVCProduces]`, `[MVCConsumes]`
173−- **Active Record:** Inherits from `TMVCActiveRecord` with `[MVCTable]`, `[MVCTableField]`
174−- **Serialization:** Automatic via `Render()` (JSON by default)
175−- **WebModule:** `TMVCEngine` created in WebModule with controllers and middleware
176−- **JWT:** `TMVCJWTAuthenticationMiddleware` built-in
177−- **RQL:** Resource Query Language for filters via query string
178− 
179−### DevExpress Components
180− 
181−Advanced visual components for VCL:
182− 
183−- **Grid:** `TcxGrid` with `TcxGridDBTableView` (data-aware)
184−- **Layout:** `TdxLayoutControl` for responsive forms
185−- **Skins:** `TdxSkinController` for global themes
186−- **Export:** `cxGridExportLink` to Excel/PDF
187−- **Filters:** `DataController.Filter` for programmatic filters
188− 
189−## Firebird Database
190− 
191−Firebird is the most used corporate database with Delphi. Access via **FireDAC** (driver `FB`).
192− 
193−### Mandatory Connection Configuration
194− 
195−```pascal
196−FConnection.DriverName := 'FB';
197−FConnection.Params.Values['CharacterSet'] := 'UTF8'; //ALWAYS UTF8
198−FConnection.Params.Values['SQLDialect'] := '3'; //NEVER Dialect 1
199−FConnection.Params.Values['Protocol'] := 'TCPIP'; //Or 'Local' for embedded
200−FConnection.Params.Values['PageSize'] := '16384'; // 16KB recomendado
201−FConnection.TxOptions.Isolation := xiReadCommitted; //Standard isolation
202−```
203− 
204−### Essential Rules Firebird
205− 
206−- **Dialect 3 ALWAYS** — Dialect 1 is InterBase legacy and causes ambiguity with `DATE`
207−- **CharacterSet UTF8** — required for correct accent support
208−- **Parameterized queries** — never concatenate strings in SQL
209−- **RETURNING with Open** — `INSERT ... RETURNING id` requires `LQuery.Open`, not `ExecSQL`
210−- **Generators** for auto-increment with `BEFORE INSERT` triggers
211−- **Domains** to centralize types and validations in the schema
212−- **Stored Procedures:** Selectable (with `SUSPEND`) uses `SELECT FROM SP`; Executable uses `EXECUTE PROCEDURE`
213−- **Explicit transactions** for compound operations (StartTransaction/Commit/Rollback)
214−- **Treat deadlocks** via `EFDDBEngineException.Kind = ekRecordLocked`
215− 
216−### Firebird Anti-Patterns
217− 
218−- ❌ `SQLDialect := '1'` — ALWAYS use `'3'`
219−- ❌ `ExecSQL` with `RETURNING` — use `Open`
220−- ❌ Concatenate SQL — use parameters
221−- ❌ Ignore `CharacterSet` — set `UTF8`
222−- ❌ `PAGE_SIZE 4096` — use `16384` for production
223−- ❌ Bypass deadlocks — handle `ekRecordLocked`
224−- ❌ `CREATE TABLE IF NOT EXISTS` — does not exist in Firebird (check via `RDB$RELATIONS`)
225− 
226−> **Skills:** `.gemini/skills/firebird-database/SKILL.md`
227−> **Rules:** `.cursor/rules/firebird-patterns.md`
228− 
229−## PostgreSQL Database
230− 
231−PostgreSQL is the most advanced open-source database, ideal for modern projects. Access via **FireDAC** (driver `PG`).
232− 
233−### Connection Configuration
234− 
235−```pascal
236−FConnection.DriverName := 'PG';
237−FConnection.Params.Values['Server'] := 'localhost';
238−FConnection.Params.Values['Port'] := '5432';
239−FConnection.Params.Database := 'meubanco';
240−FConnection.Params.UserName := 'postgres';
241−FConnection.Params.Password := 'senha';
242−FConnection.Params.Values['CharacterSet'] := 'UTF8';
243−FConnection.TxOptions.Isolation := xiReadCommitted;
244−```
245− 
246−### Essential Rules PostgreSQL
247− 
248−- **IDENTITY instead of SERIAL** — use `GENERATED ALWAYS AS IDENTITY` for new projects (PG 10+)
249−- **RETURNING with Open** — `INSERT ... RETURNING id` requires `LQuery.Open`, not `ExecSQL`
250−- **native UPSERT** — `INSERT ... ON CONFLICT (col) DO UPDATE SET ...`
251−- **JSONB** — for semi-structured data, indexable with GIN
252−- **ENUM types** — `CREATE TYPE status AS ENUM ('active', 'inactive')` mapped to Pascal enum
253−- **PL/pgSQL** — Functions (`RETURNS TABLE` = Selectable), Procedures (`CALL`, PG 11+)
254−- **Explicit transactions** — `StartTransaction/Commit/Rollback`, supports `SAVEPOINT`
255−- **Full-Text Search** — `tsvector` + `tsquery` with GIN index
256−- **Metadata via `information_schema`** — do not use `RDB$` (this is Firebird)
257− 
258−### PostgreSQL Anti-Patterns
259− 
260−- ❌ Concatenate SQL — use parameterized parameters
261−- ❌ `ExecSQL` with `RETURNING` — use `Open`
262−- ❌ `SERIAL` in new projects — use `IDENTITY`
263−- ❌ `SELECT *` in large tables — select required columns
264−- ❌ N+1 queries — use JOIN or subquery
265−- ❌ Save JSON as TEXT — use `JSONB`
266−- ❌ Ignore indexes on WHERE/JOIN columns
267− 
268−> **Skills:** `.gemini/skills/postgresql-database/SKILL.md`
269−> **Rules:** `.cursor/rules/postgresql-patterns.md`
270− 
271−## MySQL / MariaDB Database
272− 
273−MySQL is the most popular open-source database in the world. MariaDB is a compatible fork. Access via **FireDAC** (driver `MySQL`).
274− 
275−### Connection Configuration
276− 
277−```pascal
278−FConnection.DriverName := 'MySQL';
279−FConnection.Params.Values['Server'] := 'localhost';
280−FConnection.Params.Values['Port'] := '3306';
281−FConnection.Params.Database := 'meubanco';
282−FConnection.Params.UserName := 'root';
283−FConnection.Params.Password := 'senha';
284−FConnection.Params.Values['CharacterSet'] := 'utf8mb4'; //NEVER 'utf8' (only 3 bytes!)
285−FConnection.TxOptions.Isolation := xiReadCommitted;
286−```
287− 
288−### Essential Rules MySQL
289− 
290−- **`utf8mb4` ALWAYS** — `utf8` in MySQL only has 3 bytes (does not support emoji). Use `utf8mb4`
291−- **AUTO_INCREMENT + LAST_INSERT_ID()** — MySQL does NOT support `RETURNING`. Get ID via `LAST_INSERT_ID()`
292−- **native UPSERT** — `INSERT ... ON DUPLICATE KEY UPDATE`
293−- **Native JSON** — `JSON` type with `->>`/`JSON_EXTRACT` operators (MySQL 5.7+)
294−- **InnoDB ALWAYS** — never MyISAM in new projects (needs FK and transactions)
295−- **Stored Procedures** — `CALL sp_nome(...)` for procedures, `SELECT fn_nome(...)` for functions
296−- **Explicit transactions** — `StartTransaction/Commit/Rollback`, supports `SAVEPOINT`
297−- **COLLATE** — `utf8mb4_unicode_ci` for correct case-insensitive comparison
298−- **Metadata via `information_schema`** — use `DATABASE()` for current schema
299− 
300−### MySQL Anti-Patterns
301− 
302−- ❌ `utf8` as charset — use `utf8mb4`
303−- ❌ Try `RETURNING` — does not exist, use `LAST_INSERT_ID()`
304−- ❌ `MyISAM` in new tables — use `InnoDB`
305−- ❌ Concatenate SQL — use parameters
306−- ❌ `SELECT *` without `LIMIT` — page results
307−- ❌ N+1 queries — use JOIN or subquery
308−- ❌ Ignore indexes on WHERE/JOIN columns
309− 
310−> **Skills:** `.gemini/skills/mysql-database/SKILL.md`
311−> **Rules:** `.cursor/rules/mysql-patterns.md`
312− 
313−## Threads and Multi-Threading
314− 
315−Threads are essential for keeping the UI responsive and processing data in parallel. Delphi offers `TThread`, PPL (`TTask`, `TParallel.For`, `TFuture<T>`) and synchronization primitives.
316− 
317−### Golden Rule
318− 
319−> **NEVER access visual components (VCL/FMX) directly from a secondary thread.**
320−> Use `TThread.Synchronize` (blocking) or `TThread.Queue` (non-blocking) to update the UI.
321− 
322−### Threading Approaches
323− 
324−| Approach | When to Use |
325−|-----------|-------------|
326−| `TThread.CreateAnonymousThread` | Simple, one-shot tasks |
327−| `TTask.Run` (PPL) | Modern way, managed pool |
328−| `TParallel.For` | Parallel loop in independent collections |
329−| `TFuture<T>` | Asynchronous result with return value |
330−| `TThread` (inheritance) | Permanent workers, queues, servers |
331− 
332−### Thread-Safety
333− 
334−- **`TCriticalSection`** — Classic critical section (`Enter`/`Leave` ALWAYS in `finally`)
335−- **`TMonitor`** — Native object lock (`Enter`/`Exit`)
336−- **`TInterlocked`** — Atomic operations (`Increment`, `Decrement`, `Exchange`)
337−- **`TThreadList<T>`** — Thread-safe list with `LockList`/`UnlockList`
338−- **`TMultiReadExclusiveWriteSynchronizer`** — Cache: multiple reads, few writes
339−- **`TThreadedQueue<T>`** — Thread-safe queue for Producer-Consumer
340− 
341−### Threading Anti-Patterns
342− 
343−- ❌ Access VCL/FMX directly from secondary thread
344−- ❌ `Sleep()` in the main thread (freezes the UI!)
345−- ❌ `FreeOnTerminate := True` + `WaitFor` (crash!)
346−- ❌ Access shared variables without locking
347−- ❌ Ignore exceptions in threads (they are silent!)
348−- ❌ `TCriticalSection.Leave` fora de `finally`
349− 
350−> **Skills:** `.gemini/skills/threading/SKILL.md`
351−> **Rules:** `.cursor/rules/threading-patterns.md`
352− 
353−## SOLID principles in Delphi
354− 
355−### S — Single Responsibility Principle (SRP)
356− 
357−Each unit and each class must have **a single responsibility**:
358− 
359−```pascal
360−//✅ GOOD — separate responsibilities
361−TCustomerValidator = class
362− function Validate(ACustomer: TCustomer): TValidationResult;
363−end;
364− 
365−TCustomerRepository = class(TInterfacedObject, ICustomerRepository)
366− function FindById(AId: Integer): TCustomer;
367− procedure Save(ACustomer: TCustomer);
368−end;
369− 
370−//❌ BAD — class doing it all
371−TCustomer = class
372− procedure Validate; //should be a Validator
373− procedure SaveToDb; //should be a Repository
374− procedure SendEmail; //should be a Service
375−end;
376−```
377− 
378−### O — Open/Closed Principle (OCP)
379− 
380−Classes should be **open for extension**, closed for modification. Use inheritance and interfaces:
381− 
382−```pascal
383−type
384− IReportExporter = interface
385− procedure Export(AReport: TReport);
386− end;
387− 
388− TPdfExporter = class(TInterfacedObject, IReportExporter)
389− procedure Export(AReport: TReport);
390− end;
391− 
392− TExcelExporter = class(TInterfacedObject, IReportExporter)
393− procedure Export(AReport: TReport);
394− end;
395−```
396− 
397−### L — Liskov Substitution Principle (LSP)
398− 
399−Subtypes must be replaceable with the base type without breaking behavior:
400− 
401−```pascal
402−//✅ GOOD — any ICustomerRepository works
403−procedure TCustomerService.LoadCustomer(ARepo: ICustomerRepository);
404−begin
405− //works with TFireDACCustomerRepo, TMemoryCustomerRepo, TMockCustomerRepo
406− FCustomer := ARepo.FindById(FCustomerId);
407−end;
408−```
409− 
410−### I — Interface Segregation Principle (ISP)
411− 
412−Small, cohesive interfaces, not "fat" interfaces:
413− 
414−```pascal
415−//✅ GOOD — segregated interfaces
416−type
417− IReadableRepository<T> = interface
418− function FindById(AId: Integer): T;
419− function FindAll: TObjectList<T>;
420− end;
421− 
422− IWritableRepository<T> = interface
423− procedure Save(AEntity: T);
424− procedure Delete(AId: Integer);
425− end;
426− 
427− ICustomerRepository = interface(IReadableRepository<TCustomer>)
428− ['{GUID}']
429− function FindByCpf(const ACpf: string): TCustomer;
430− end;
431−```
432− 
433−### D — Dependency Inversion Principle (DIP)
434− 
435−Depend on **abstractions** (interfaces), not concrete implementations. Use **constructor injection**:
436− 
437−```pascal
438−type
439− TOrderService = class
440− private
441− FOrderRepo: IOrderRepository;
442− FNotifier: INotificationService;
443− public
444− constructor Create(AOrderRepo: IOrderRepository; ANotifier: INotificationService);
445− procedure PlaceOrder(AOrder: TOrder);
446− end;
447− 
448−constructor TOrderService.Create(AOrderRepo: IOrderRepository; ANotifier: INotificationService);
449−begin
450− inherited Create;
451− FOrderRepo := AOrderRepo;
452− FNotifier := ANotifier;
453−end;
454−```
455− 
456−## Clean Code — Essential Rules
457− 
458−### 1. Short Methods
459− 
460−- Maximum **20 lines** per method (ideal: 5-10)
461−- If a method needs a comment explaining "what it does", it should be extracted into a method with a descriptive name
462− 
463−### 2. Self-Descriptive Names
464− 
465−```pascal
466−//❌ SPACIOUS
467−procedure Proc1(S: string; N: Integer);
468−function Calc(V: Double): Double;
469− 
470−// ✅ BOM
471−procedure SendNotificationEmail(const ARecipientEmail: string; ATemplateId: Integer);
472−function CalculateDiscountedPrice(AOriginalPrice: Double): Double;
473−```
474− 
475−### 3. Avoid Magic Numbers
476− 
477−```pascal
478−//❌ SPACIOUS
479−if ACustomer.Age > 18 then
480− 
481−// ✅ BOM
482−const
483− MINIMUM_AGE = 18;
484−// ...
485−if ACustomer.Age > MINIMUM_AGE then
486−```
487− 
488−### 4. Guard Clauses
489− 
490−```pascal
491−//❌ BAD — excessive nesting
492−procedure ProcessOrder(AOrder: TOrder);
493−begin
494− if Assigned(AOrder) then
495− begin
496− if AOrder.Items.Count > 0 then
497− begin
498− if AOrder.IsValid then
499− begin
500− //real logic here
501− end;
502− end;
503− end;
504−end;
505− 
506−//✅ BOM — guard clauses
507−procedure ProcessOrder(AOrder: TOrder);
508−begin
509− if not Assigned(AOrder) then
510− raise EArgumentNilException.Create('AOrder cannot be nil');
511− if AOrder.Items.Count = 0 then
512− raise EBusinessRuleException.Create('Order must have at least one item');
513− if not AOrder.IsValid then
514− raise EValidationException.Create('Order validation failed');
515− 
516− //real logic here — no nesting
517−end;
518−```
519− 
520−### 5. Focused and Typed Try/Except
521− 
522−```pascal
523−//❌ BAD — generic catch swallowing critical errors (Access Violation, OOM)
524−try
525− //large block of long code
526−except
527− on E: Exception do //Or worse: without declaring "on E:"
528− ShowMessage(E.Message);
529−end;
530− 
531−//✅ GOOD — specific exceptions and granular recovery
532−try
533− FConnection.Open;
534− PerformCriticalAction;
535−except
536− on E: EFDDBEngineException do
537− raise EDatabaseConnectionException.Create('Falha local no banco: ' + E.Message);
538− on E: EBusinessRuleException do
539− raise; //Pass the exception to the Controller to catch
540− on E: Exception do
541− begin
542− Logger.LogError('Critical unexpected failure', E);
543− raise; //NEVER hide pure root Exception exceptions without rethrowing!
544− end;
545−end;
546−```
547− 
548−### 6. Unit Organization
549− 
550−```pascal
551−unit MyApp.Domain.Customer.Entity;
552− 
553−interface
554− 
555−uses
556− System.SysUtils,
557− System.Classes,
558− System.Generics.Collections;
559− 
560−type
561− //1. Types, enums and records first
562− TCustomerStatus = (csActive, csInactive, csSuspended);
563− 
564− //2. Interfaces
565− ICustomer = interface
566− ['{GUID}']
567− function GetName: string;
568− property Name: string read GetName;
569− end;
570− 
571− //3. Classes
572− TCustomer = class(TInterfacedObject, ICustomer)
573− private
574− FId: Integer;
575− FName: string;
576− FStatus: TCustomerStatus;
577− function GetName: string;
578− public
579− //Constructor and Destructor first
580− constructor Create(const AName: string);
581− destructor Destroy; override;
582− 
583− //After public methods
584− function IsActive: Boolean;
585− procedure Activate;
586− procedure Deactivate;
587− 
588− //Properties last
589− property Id: Integer read FId write FId;
590− property Name: string read GetName;
591− property Status: TCustomerStatus read FStatus;
592− end;
593− 
594−implementation
595− 
596−{ TCustomer }
597− 
598−constructor TCustomer.Create(const AName: string);
599−begin
600− inherited Create;
601− if AName.Trim.IsEmpty then
602− raise EArgumentException.Create('Customer name cannot be empty');
603− FName := AName.Trim;
604− FStatus := csActive;
605−end;
606− 
607−//... other implementations
608−```
609− 
610−## Recommended Design Patterns
611− 
612−| Standard | Use in Delphi |
613−|--------|---------------|
614−| **Repository** | Abstracts data access via interface (FireDAC, REST, etc.) |
615−| **Service** | Contains business logic orchestrating repositories and other services |
616−| **Factory** | Creates instances of complex objects or with dependencies |
617−| **Observer** | Use `TNotifyEvent` or interfaces to decouple notifications |
618−| **Strategy** | Interfaces to vary algorithms (e.g. tax calculation) |
619−| **Unit of Work** | Manages database transactions |
620− 
621−## Anti-Patterns to Avoid
622− 
623−- ❌ **God class / God unit** — units with thousands of lines doing everything
624−- ❌ **Direct coupling to forms** — business logic in `OnClick` of buttons
625−- ❌ **Uses circular** — resolved by separating into layers (Domain, Infra, Application, Presentation)
626−- ❌ **Global variables** — use dependency injection
627−- ❌ **Hardcoded Strings** — use `resourcestring` or constants
628−- ❌ **Ignoring memory management** — always free unmanaged objects by reference
629−- ❌ **`with` statement** — avoid `with` as it reduces readability and makes debugging difficult
630−- ❌ **Testing in Banco Real** — attach DUnitX projects directly to `TFDConnection`, skipping Mocks/Fakes.
631− 
632−## Memory Management (Critical)
633− 
634−- **Watched Blocks:** The golden rule in Delphi: Whenever there is code calling `.Create` for instances of TObject Classes, the IMMEDIATELY subsequent line must be a `try`. NO intermediate lines of code!
635− 
636−```pascal
637−//✅ The Gold Standard for Disposable Objects
638−var LList: TStringList;
639−begin
640− LList := TStringList.Create;
12+## Crucial Directives (Memory Management)
13+- **Watched Blocks (Required):** EVERYTHING you instantiate with `.Create` (if it is `TObject` and does not have `Owner`) **MUST** have a `try..finally` on the IMMEDIATELY subsequent line.
14+ ```pascal
15+ Obj := TMyClass.Create;
64116 try
642− LList.Add('item');
643− // ...
17+ Obj.DoSomething;
64418 finally
645− LList.Free; //i FreeAndNil(LList)
19+ Obj.Free; //my FreeAndNil(Obj)
64620 end;
647−end;
21+ ```
22+- **DO NOT use** `with`.
23+- **DO NOT create** God Classes. Use SOLID Principles.
24+- Isolate visual components (FMX/VCL) from strict business rules. Do not access DBGrid or form edits in pure logical units.
25+- For dependency injection, pass abstractions in the constructor.
64826  
649−//✅ Objects with owner - VCL/FMX components
650−TMyComponent := TMyComponent.Create(Self); //Owner (Self) assumes release
27+## File Organization & Naming (PascalCase)
28+- Classes: Start with `T` (ex: `TCustomer`).
29+- Interfaces: Start with `I` (ex: `ICustomer`).
30+- Exceptions: Start with `E` (ex: `EValidationError`).
31+- Private attributes or fields: Start with `F` (ex: `FName`).
32+- Local variables: Start with `L` (ex: `LCustomer`).
33+- Parameters: Start with `A` (ex: `ACustomer`).
34+- Unit nomenclature: `NomeProjeto.Camada.Dominio.Funcionalidade.pas`
65135  
652−//✅ Garbage Collection com Interfaces (ARC)
653−//The object will be automatically cleaned up at the end of the scope, eliminating the need for try..free
654−var LService: IMyService;
655−begin
656− LService := TMyService.Create;
657− LService.DoSomething;
658−end;
659− 
660−//✅ Local variables: use L prefix
661−var LCustomer: TCustomer;
662−```
663− 
664−## Documentation
665− 
666−- Use **XMLDoc** for public methods and interfaces:
667− 
668−```pascal
669−///<summary>
670−///Locates a customer by the CPF entered.
671−///</summary>
672−///<param name="ACpf">Customer CPF (numbers only)</param>
673−///<returns>TCustomer instance or nil if not found</returns>
674−///<exception cref="EArgumentException">If ACpf is empty</exception>
675−function FindByCpf(const ACpf: string): TCustomer;
676−```
677− 
678−- Comments in **Portuguese** for Brazilian projects
679−- Don't comment obvious code — let the method name explain
680− 
681−## Layer Structure (Architecture)
682− 
683−```
684−src/
685−├── Domain/ ← Entidades, Value Objects, Interfaces de repositório
686−├── Application/ ← Services, Use Cases, DTOs
687−├── Infrastructure/ ← Implementações de repositório (FireDAC), APIs externas
688−└── Presentation/ ← Forms (VCL/FMX), ViewModels
689−tests/
690−└── Unit/ ← Projetos DUnitX e Fakes/Mocks isolados por contexto
691−```
692− 
693−> **Dependency rule:** `Presentation → Application → Domain ← Infrastructure`
694−> The Domain **never** depends on other layers. `tests` depend on `Application` and `Domain` but inject Fake implementations by copying `Infrastructure` alone.
695− 
696−---
697− 
698−## 🚫 AI Context Policy — What to Include and Exclude
699− 
700−> Full strategy documented in `docs/ai-ignore-strategy.md`.
701− 
702−### Files AI Must Always Use as Context
703− 
704−- `AGENTS.md` — universal rules
705−- `README.md` — project overview
706−- `.github/copilot-instructions.md` — Copilot pre-prompt
707−- `.claude/CLAUDE.md` — Claude master prompt
708−- `.claude/rules/**/*.md` — context-specific rules
709−- `.claude/skills/**/SKILL.md` — on-demand skills
710−- `.cursor/rules/**/*.md` — Cursor rules
711−- `.gemini/skills/**/SKILL.md` — Gemini skills
712−- `.kiro/steering/**/*.md` — Kiro steering docs
713−- `examples/**/*.pas` — good practice examples
714−- `docs/**/*.md` — documentation
715− 
716−### Files AI Must Never Use as Context
717− 
718−- Build artifacts: `*.dcu`, `*.exe`, `*.dll`, `*.bpl`, `*.dcp`, `*.map`, `*.res`
719−- IDE temporaries: `*.local`, `*.identcache`, `*.stat`, `__history/`, `__recovery/`
720−- Output directories: `Win32/`, `Win64/`, `Debug/`, `Release/`, `build/`, `dist/`
721−- Secrets: `*.key`, `*.pfx`, `*.p12`, `.env`, `.env.*`
722−- Noise: `*.log`, `*.dmp`, `*.bak`, `*.tmp`
723− 
724−See `.cursorignore`, `.gitignore` and `.vscode/settings.json` for the enforced patterns.
725− 
36+*(See the `AGENTS.md` global file and `rules/` folder for guidelines specific to frameworks such as FireDAC, Rest, Horse and Database).*
72637  

Also from Kynth Studios

Built for the same person as RuleStack

ToolDrift

What the AI coding tools changed last night

tooldrift.kynth.studio

StillShipping

Which agent tools have stopped shipping

stillshipping.kynth.studio

BlockDex

Search inside every shadcn registry

blockdex.kynth.studio

The studio list

One product, taken apart, once a month

Kynth Studios pulls one shipped product open every month — what it does, what it cost to build, what the pipeline behind it looks like, and what the numbers did. One email a month, nothing in between.

Double opt-in — we send one confirmation link and nothing else until you click it.

RuleStack

Built by

Kynth Studios

the studio behind ToolDrift, StillShipping and BlockDex

part of Toolproof, the measurement layer for AI agent tooling

Directory

Configs
Stacks
Compare formats
AGENTS.md vs CLAUDE.md
Cursor rules alternatives
Diff two configs
Best AGENTS.md examples
Best Cursor rules examples
What goes in a CLAUDE.md

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

© 2026 RuleStack. A Kynth Studios product. Changelog

RuleStack

The studio list

One product, taken apart, once a month

Kynth Studios pulls one shipped product open every month — what it does, what it cost to build, what the pipeline behind it looks like, and what the numbers did. One email a month, nothing in between.

Double opt-in — we send one confirmation link and nothing else until you click it.

RuleStack

Built by

Kynth Studios

the studio behind ToolDrift, StillShipping and BlockDex

part of Toolproof, the measurement layer for AI agent tooling

Directory

Configs
Stacks
Compare formats
AGENTS.md vs CLAUDE.md
Cursor rules alternatives
Diff two configs
Best AGENTS.md examples
Best Cursor rules examples
What goes in a CLAUDE.md

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

© 2026 RuleStack. A Kynth Studios product. Changelog

RuleStack

The studio list

One product, taken apart, once a month

Kynth Studios pulls one shipped product open every month — what it does, what it cost to build, what the pipeline behind it looks like, and what the numbers did. One email a month, nothing in between.

Double opt-in — we send one confirmation link and nothing else until you click it.

RuleStack

Built by

Kynth Studios

the studio behind ToolDrift, StillShipping and BlockDex

part of Toolproof, the measurement layer for AI agent tooling

Directory

Configs
Stacks
Compare formats
AGENTS.md vs CLAUDE.md
Cursor rules alternatives
Diff two configs
Best AGENTS.md examples
Best Cursor rules examples
What goes in a CLAUDE.md

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

© 2026 RuleStack. A Kynth Studios product. Changelog

RuleStack