# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## What this is ROAGEST is a **Visual FoxPro 9** desktop application (Romanian-language) for **gestiune de stocuri și mărfuri** — goods/inventory management: purchases (`achiziție`, NIR — *notă intrare recepție*), sales, warehouse transfers, stock (`stoc`), consumption vouchers (`bon consum`), inventory counts (`inventar`), price changes (`schimbare preț`), and cash-register (`casă de marcat`, e500/mp500) integration. It backs onto an **Oracle** database (`gcS` schema, default `CONTAFIN`) reached through the shared `goExecutor`/`goConn` SQL pass-through objects. It is one member of the larger "ROA" suite built by ROA Romfast SRL (ROAACNPRO, ROAIMOB, ROACONT, ROACASA, ROADEF, etc.) and lives alongside its siblings under `D:\ROA`. The code, comments, menus, and changelog are all in Romanian — match that language when editing user-facing strings, comments, and changelog entries. **Architecturally, ROAGEST is older-generation than ROAACNPRO/ROAIMOB**: those apps instantiate `oApp` as a subclass of the shared `RoaApp` framework class (`COMUN/programe/roa.prg`) with an ordered `initializeaza*` method pipeline. ROAGEST does **not** use `RoaApp` at all — `COMUN/programe/roa.prg` exists in this repo (vendored, shared with the other apps) but is unreferenced. Instead, `Programe/roagest.prg` is a long, monolithic startup script that manually chains `SET PATH`/`SET CLASSLIB ... ADDITIVE`/`SET PROCEDURE ... ADDITIVE` statements and instantiates `goApp = CREATEOBJECT("wzApplication")` — the classic VFP "Application Wizard" base class (defined in `COMUN/clase/appwiz.vcx`). Don't assume the `RoaApp`/`initializeaza*` conventions documented for ROAACNPRO/ROAIMOB apply here. ## Build, run, version control - **Build/run requires the Visual FoxPro 9 IDE on Windows.** There is no command-line build. Open `roagest.pjx` in the VFP IDE and use *Project > Build* to produce `roagest.exe`. The startup program is `Programe/roagest.prg`. - **`.prg` files are source; `.fxp`/`.FXP` are compiled, `.BAK` are backups.** Edit the `.prg`. The `.scx/.sct` (forms), `.vcx/.vct` (class libraries), `.frx/.frt` (reports), and `.mnx/.mnt`/`.mpr` (menus) are VFP binary/generated artifacts — **edit them in the VFP IDE, not by hand.** `.mpr`/`.mpx` are GENMENU-generated from `.mnx`; never hand-edit them. - **SVN remains the "live" source of truth**, especially for `COMUN/` — use `svn`, not `git`, for the authoritative history. A **git** repo now runs in parallel (see "Version control: git alongside SVN" below). - **`config.fpw`** sets the runtime environment (`CODEPAGE=1252`, `EXCLUSIVE=OFF`, `SAFETY=OFF`, `MULTILOCKS=ON`, `TALK=OFF`). Don't enable `SAFETY` — the code relies on silent overwrite. `Programe/roagest.prg` re-asserts most of these plus `SET DATE TO DMY`, `SET DECIMALS TO 4`, `SET EXACT ON`. - `roagest.exe` refuses to start unless its own filename matches `gcNumeProgram = 'ROAGEST'` (`IF !LIKE(gcNumeProgram + '*', ...)` near the top of `roagest.prg`) — a guard against running a renamed/copied executable. - The compiler error log is `roagest.ERR`; the runtime log is `log.txt`. `roagest.Stats` and `versiune_db.txt` (format `YYYY_MM_DD_NN`, e.g. `2026_01_21_02`) track build/DB-schema stamps checked against the update server on launch (`COMUN/programe/oupdate.prg`, `wwcodeupdate.prg`). - `Programe/cont2000.prg` is a near-duplicate of `roagest.prg` (same startup pattern, older `CONT2000` naming) still present in the tree — treat it as legacy/reference, not the active entry point, unless you confirm otherwise from `roagest.pjx`'s main-file setting. ## Version control: git alongside SVN Git rulează în paralel cu SVN-ul legacy, nu îl înlocuiește. SVN rămâne sursa "vie" pentru `COMUN/`, sincronizat manual către git; nu rula comenzi `svn` din git și nu presupune că git-ul e la zi cu ultimele modificări SVN dacă nu a fost sincronizat explicit. - Repo-ul principal (rădăcina acestui folder) e propriul lui `.git`, cu remote `git@gitea.romfast.ro:romfast/roagest.git`. `.gitignore` exclude `COMUN/` (gestionat separat, vezi mai jos), `.svn/`, artefactele VFP compilate (`*.fxp`, `*.bak`, `*.mpr`, `*.exe`, …) și fișierele Windows uzuale. - `COMUN/` are propriul `.git` separat, cu remote `git@gitea.romfast.ro:romfast/comun.git` — **același repo partajat de toate aplicațiile ROA** (ROAACNPRO, ROAIMOB, etc.). O modificare împinsă acolo afectează toate proiectele. Nu face `push --force` peste `comun.git` fără aprobare explicită — ar șterge istoric comun tuturor proiectelor. - Căutarea în cod VFP binar (`.vcx`/`.scx`) pentru acest proiect folosește `vcx2txt.ps1` parametrizat pentru ROAGEST (vezi secțiunea de mai jos) — cache separat, `D:\ROA\_vfp_textcache\roagest`, nu-l amesteca cu cache-urile altor proiecte. ## Searching code inside `.vcx`/`.scx` (binary) libraries Most class/form code lives **inside binaries** (`.vcx`+`.vct`, `.scx`+`.sct`, …), not in `.prg`, so plain grep can't read it cleanly. To search method/procedure bodies, convert the binaries to their TEXT form first and grep the text, using the shared `foxbin2prg` tool already built at `D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE`: ```powershell & 'D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1' -Project 'D:\ROA\ROAGEST\roagest.pjx' -ProjectRoot 'D:\ROA\ROAGEST' -CacheRoot 'D:\ROA\_vfp_textcache\roagest' -Types vcx,scx,frx,mnx ``` This reads the file list straight from `roagest.pjx`, so it only converts the `.vcx`/`.scx`/`.frx`/`.mnx` this project actually references — not all of `COMUN\` (most of which is unused by any one app). It's incremental and safe to re-run after IDE edits. Output lands in `D:\ROA\_vfp_textcache\roagest\` as `.vc2`/`.sc2`/`.fr2`/`.mn2` text mirrors — `Grep` those. For `.vcx`/`.scx`, code edits no longer require the VFP IDE — the flow is now: 1. Refresh the cache (`vcx2txt.ps1` above), especially if a VFP IDE session ran since the last refresh (IDE changes make the cache stale). 2. Edit the `.vc2`/`.sc2` text directly (position-sensitive format — don't reflow lines; properties are alphabetized). 3. Review the diff on the text file like any other source change. 4. Write back with `txt2vcx.ps1` (`D:\ROA\UTIL\foxbin2prg\txt2vcx.ps1 -TextFile -ProjectRoot 'D:\ROA\ROAGEST' -CacheRoot 'D:\ROA\_vfp_textcache\roagest'`) — it regenerates and recompiles the binary in a staging folder, fidelity-checks it against the edited text, then copies it into the project only if that check passes. `.mnx`/`.frx` stay **read-only** in this flow (menus still need GENMENU in the IDE; reports are too fragile to round-trip) — edit those in the VFP IDE as before. Targets under `COMUN\` need `-AllowComun` plus explicit approval, since a change there affects every ROA app. See `D:\ROA\UTIL\foxbin2prg\CLAUDE.md` for full details and `COMUN\docs\flux-editare-vfp-text.md` for the shared per-round workflow (baseline backups, review patches, fidelity check) plus the per-project parameters (including ROAGEST's). ## The COMUN shared framework `COMUN/` is **shared, framework-level code used by every ROA app** — it is not specific to ROAGEST. Treat it as a vendored library: - A change in `COMUN/` affects all ROA applications. Prefer making app-specific changes in this repo's top-level `Programe/`, `Clase/`, `Ferestre/`, `Meniuri/`, `Rapoarte/` directories. Only touch `COMUN/` when the fix genuinely belongs to the shared framework. - Unusually for this app, **most of the actual "gestiune" business logic lives in `COMUN/programe/`, not in this repo's own `Programe/`.** ROAGEST's own `Programe/` folder has only ~24 files (`roagest.prg`, `gestiuni.prg`, `cont2000.prg`, `oimportdinxml.prg`, `ofactureaza.prg`, `exportare.prg`, `fisa_ob_inventar.prg`, `update_nomenclator.prg`, `suma_in_vorbe.prg`, `actualizari.prg`, `cumplun-furn.prg`, `inchidere_k.prg`, `ovariabile_globale.prg`, `shutdown.prg`), while the core stock/article/movement procedures — `oproceduri_stocuri.prg`, `oproceduri_articole.prg`, `oproceduri_rulaje.prg`, `oproceduri_casademarcat.prg` (+ `_e500`/`_mp500` cash-register variants), `oproceduri_facturare.prg`, `oproceduri_obinv.prg` (fixed-asset-in-use items), `anaf_efactura.prg` (ANAF e-Factura), `osecurity.prg`, `oproceduri_configurare.prg`, `oproceduri_listari.prg`, `oproceduri_retete.prg`, `orapoarte.prg` — all resolve from `COMUN/programe/` via `SET PATH`. Likewise most class libraries used (`onomenclatoare`, `stocuri.vcx`, `rulaje.vcx`, `ointroduceri*`, `oinventar`, `orapoarte_gestiuni`, `bon_fisc`, `onom_articole`, `onom_retete`, `ferestre_oracle`, `configurare.vcx`, `serii_numere.vcx`, …) live in `COMUN/clase/`, not this repo's `Clase/`. - ROAGEST's **own** `Clase/` folder is small: `gestiuni.vcx`, `oavize.vcx`, `oimportxml.vcx`, `orapoarte_gestiuni.vcx`, `ovizrul.vcx`, `atentie.vcx`. Its own `Ferestre/` is also small: `fundal.scx` (shell form), `accesindivid.scx`, `frm_conversii.scx`, `frm_schimbare_pret_tva.scx`. The bulk of forms actually used are `COMUN\ferestre\*` (e.g. login is `COMUN\ferestre\frm_login.scx`). - `SET PATH` (see `Programe/roagest.prg` ~line 109) makes `COMUN\CLASE`, `COMUN\FERESTRE`, `COMUN\PROGRAME`, `COMUN\GRAFICE`, `COMUN\RAPOARTE`, `COMUN\MENIURI`, and the `COMUN\UTILE\*` helper libraries (GridExtras, ctl32, hpdf/ReportOutput, web, Excel) resolvable by bare filename, plus a sibling `..\COMUNROA\` directory (built from `gcAppPath`'s grandparent). So `SET PROCEDURE TO email.prg` resolves to `COMUN\PROGRAME\email.prg`. ## Application architecture Startup flow (`Programe/roagest.prg`, procedural — no `oApp`/`RoaApp` object wraps it): 1. Verifies the running exe is actually named `ROAGEST*`; sets `SET CENTURY/DELETED/DATE/EXACT/...` environment options. 2. Computes `gcAppPath` (own folder) and `gcDirMare`/`dirgen` (suite root, one level up — e.g. `D:\ROA\`), builds the long `SET PATH TO` string across its own folders + `COMUN\*` + `..\COMUNROA\`, then issues **dozens of ordered** `SET CLASSLIB ... ADDITIVE` and `SET PROCEDURE ... ADDITIVE` statements (order matters: later `ADDITIVE` registrations can shadow earlier same-named procedures/classes). 3. Parses the launch parameter string (`tparam`, semicolon-delimited: `host;user;password;idutil;idprogram;...;an;luna;schema;idfirma`) when launched by the central ROA launcher; otherwise falls back to hardcoded dev defaults (`JCSSERVER`/`CONTAFIN_ORACLE`). 4. Sets up cross-cutting globals: `goLog`/`poLog` (`Log_Mesaje.prg`), `goLocale` (Romanian by default, `glTraducere = .F.` — translation path largely dormant), `goExecutor`/`goConn` (Oracle SQL pass-through), `goExport`, `goMyXMLHTTP` (remote error reporting), and an optional `goKeepAlive` timer (avoids ODBC idle timeouts). 5. `NUMEPROGRAM = 'ROA - Gestiuni'`, `_program = 'gest'`; reads the actual version string from the built `.exe`'s file version resource. 6. Registers `ON SHUTDOWN ShutDown()` / `ON ERROR ErrorHandler(...)`, instantiates `goApp = CREATEOBJECT("wzApplication")`, sets `goApp.cStartupMenu` to `Meniuri\roagest.mpr` and `goApp.cStartupForm` to `COMUN\ferestre\frm_login.scx`, then `goApp.SHOW` — this is the VFP event loop entry (AppWizard's `Show`/`Run` machinery), analogous to `READ EVENTS` in the newer apps. 7. `ErrorHandler` posts errors to a remote endpoint via `goMyXMLHTTP.postError(...)` (host read from `settings.ini`'s `[errors] host` key) in addition to showing `AMESSAGEBOX`. `Cleanup()`/`ShutDown()` release class libs, procedures, and the menu stack on exit. ### Globals convention Same `g`/`gc`/`gn`/`gl` Hungarian-ish prefixing as the rest of the suite (`g` = global, `gc`/`gn`/`gl` = char/numeric/logical, `m.` = memory-variable scoping), declared `PUBLIC`/`PRIVATE` directly in `roagest.prg` rather than promoted by a framework object: - `goApp` (AppWizard app object), `goConn`/`goExecutor` (Oracle connection + SQL executor), `goLog`/`poLog` (logger), `goLocale`, `goExport`, `goCalendar`, `goFirma`. - `gcS` = Oracle schema (default `CONTAFIN`), `gnIdFirma`, `gnAn`/`gnLuna` (working year/month), `gcAppPath` (this app's folder), `gcDirMare`/`dirgen` (suite root, e.g. `D:\ROA\`), `gcSecurityPath`/`gcSecurityFile` (`DIRGEN + 'Security\ROA_SECURITY.TXT'`), `gcGeneralIniFile`/`gcSettingsFile` (`DIRGEN + 'settings.ini'`). - Legacy holdovers from the pre-Oracle (`CONT2000`) codebase are still declared even though mostly unused now: `nror[65000]`, `RTVA[22,2]`, `SER_PERM`/`SER_PERI`/`VERSIUNE` (commented out), old disk-serial license-check functions (`decodare1`, `HEXDEC`, `DECTOBIN`, the commented-out `PORNIRE`/`verif_ser_perm`) — dead code kept for reference, not active. ### Data layer - Backend is **Oracle**, reached via `goConn`/`goExecutor` (created from the `DECABAZA` classlib, same pattern as the sibling apps) — run queries with `SQLEXEC()`/the executor wrapper; results come back as VFP cursors. - Domain tables/views follow Romanian/domain naming: `stoc`, `rulaje`/`rull` (stock movements), `act` (documents/NIR), `articole`/nomenclator, `gestiuni` (warehouses/locations), `casa de marcat` bon fiscal tables. Look in `COMUN/programe/oproceduri_stocuri.prg`, `oproceduri_articole.prg`, and `oproceduri_rulaje.prg` for the canonical query/view names (e.g. `viz_stocuri` filters on `an`, `luna`, `id_sucursala`, `id_gestiune`). - `Initializari/` holds XML templates for cash-register integrations (`roagest_bon.xml(.tmpl)`, `roagest_mp500.xml(.tmpl)`, `euro500t.txt(.tmpl)`, `euro500t_erori.xml(.tmpl)`). - `Locale/` is a full VFP database (`locale.dbc` + `.dbf`/`.cdx`) for the (largely dormant) translation feature, not just an .ini. ## Domain quick reference - **No app-specific `.h` include** defines domain constants the way `roaacnpro.h` does for ROAACNPRO — `Include/CONT2000.H` is just a historical comment (a class-tree diagram from the old `CONT2000` codebase), and `Include/foxpro.h` is the stock VFP header. Domain behavior (document types, movement signs, VAT handling) is expressed directly in procedure logic in `COMUN/programe/oproceduri_*.prg`, not centralized constants — expect to trace behavior through those procedures rather than a single defines file. - **`Rapoarte/*.frx`** (24 report layouts in this repo, more resolved from `COMUN\RAPOARTE`) name the real workflows: `rap_nirtransfer_achi` (NIR/transfer receiving), `rap_centralizator_intrari`/`_intrari2`, `rap_centralizator_iesiri`/`_iesiri2` (in/out summaries), `rap_fisa_magazie_fifo` (FIFO stock card), `rap_gest_val_subgrupe`/`_gestc` (valued stock by subgroup), `rap_vechime_stocuri` (stock aging), `rap_marfuri_lista_centr`/`_desf`/`_valoric` (goods lists), `rap_vanzari_comp_cant`/`_val`/`_web` (sales comparisons), `rap_instiintaripret` (price-change notices), `rap_inchidere_k`, `rap_stoc_obinv` (inventory-use objects), `rap_rul_consum_lucrari_articole`/`_centralizator_consum_lucrari` (consumption vouchers). - **`Meniuri/`** menu names map to the app's top-level operations: `achi*` (achiziții/purchases), `vanz*` (vânzări/sales), `consum*` (bon consum), `transfer*` (stock transfers), `config*` (configurare), `casademarcat`/`casamarcat` (fiscal cash registers), `obinvent` (obiecte de inventar), `stoc`, `rulaje`, `list*`/`rapoarte` (reports), `roagest.mnx`/`.mpr` (the root startup menu, referenced by `goApp.cStartupMenu`). - **`todo.txt`** is an informal running work list (Romanian, `ok`/`OK`-prefixed = done, otherwise pending) — recent items concern store inventory (`inventar magazin`), FIFO stock cards, and VAT-rate handling during the 19%→21% transition; useful as a quick pulse on active/recent pain points but not authoritative documentation. - **VAT/TVA** is time-sensitive here too: recent changelog entries (v2.11.0–2.11.2) explicitly prepare the app for the 21%/11% rates effective 2025-08-01 while still supporting 19%/9%/5% for prior periods — the same "rate by document period, not 'current' rate" caution as the other ROA apps applies. - **Cash register / fiscal integration**: `oproceduri_casademarcat.prg`, `oproceduri_casa_marcat_e500.prg`, `oproceduri_casa_marcat_mp500.prg` (in `COMUN/programe/`) integrate specific fiscal printer/cash-register protocols (E500, MP500); `Initializari/roagest_bon.xml`/`roagest_mp500.xml` are their config templates. - **ANAF e-Factura / SAFT**: `COMUN/programe/anaf_efactura.prg` provides e-invoicing against ANAF, shared with sibling apps. ## Changelog & release convention `changelog_roagest.txt` is the user-facing release log (188KB, going back to v1.0.x). **Newest entry goes at the top**, in this exact HTML-comment block format (Romanian, `DD/MM/YYYY`): ``` ``` Tags in use: `:nou:` (new feature), `:modificare:` (change), `:eroare:` (bug fix), and occasionally `:adaugare:` (addition) — match this exact tag vocabulary (a lone historical `:modfiicare:` typo exists; don't repeat it). Bump the `MAJOR.MINOR.PATCH` version (currently `2.11.5`) when you add an entry. The app checks for updates on startup (`COMUN/programe/oupdate.prg`, `wwcodeupdate.prg`) against `versiune_db.txt`'s schema stamp; the runtime reads its own version from the built `.exe`'s file version resource. ## Mod de lucru: delegare către subagenți + review înainte de commit Preferințele lui Marius pentru sesiunile pe acest proiect: - **Orchestrare pe misiuni lungi**: niciodată un singur subagent care acumulează context pe multe sarcini înlănțuite — sesiunea principală orchestrează subagenți proaspeți per sarcină (prag: max ~200–250k tokens per subagent, apoi handoff + agent nou), cu handoff compact pe disc; regula comună tuturor proiectelor ROA: `COMUN\docs\orchestrare-subagenti.md`. - **Delegare**: modificările de cod de volum/rutină (aplicarea unei propuneri din `docs/propuneri_*.md`, editări pe cache-ul text + write-back, actualizări de documentație, rulări de teste) se deleagă către **subagenți Sonnet care lucrează în background** (team agents — Agent tool cu `model: sonnet`, lane-uri paralele unde e posibil), iar sesiunea principală doar orchestrează și monitorizează: împarte planul pe lane-uri, transmite constatările între agenți, verifică rezultatele (diff, teste, fidelity) și intervine direct doar la deblocări (procese agățate), decizii și verificări. - **Fără commit fără review**: nu da commit din proprie inițiativă pe modificări de cod — Marius vrea întâi să **vadă diff-ul**. Pentru binarele VFP (`.vcx`/`.scx`), diff-ul lizibil se face pe forma text: regenerează textul din binarul vechi (HEAD din git) cu `vcx2txt.ps1 -Source` și compară-l cu textul editat din cache (`git diff --no-index`). Commit doar după ce Marius confirmă pe diff. ## Skill routing When the user's request matches an available skill, invoke it via the Skill tool. When in doubt, invoke the skill. Key routing rules: - Product ideas/brainstorming → invoke /office-hours - Strategy/scope → invoke /plan-ceo-review - Architecture → invoke /plan-eng-review - Design system/plan review → invoke /design-consultation or /plan-design-review - Full review pipeline → invoke /autoplan - Bugs/errors → invoke /investigate - QA/testing site behavior → invoke /qa or /qa-only - Code review/diff check → invoke /review - Visual polish → invoke /design-review - Ship/deploy/PR → invoke /ship or /land-and-deploy - Save progress → invoke /context-save - Resume context → invoke /context-restore ## Project insights (docs/) `docs/` holds short, concrete notes discovered while working on real tasks — hidden flows, gotchas, key procedures/packages, relevant tables — that go beyond what this file covers. See `docs/README.md` for the index. **Proactively offer to update `docs/` whenever you uncover a non-obvious project insight while fixing a bug or investigating a flow** (don't wait to be asked), so future sessions can reuse it instead of re-investigating from scratch. Keep entries concise and factual — no restating what's obvious from reading the code.