sync SVN r18041

This commit is contained in:
2026-08-23 11:08:56 +03:00
parent 79b08470be
commit 0027a28961
19 changed files with 369 additions and 592 deletions

58
docs/README.md Normal file
View File

@@ -0,0 +1,58 @@
# COMUN\docs — index
Documentatie comuna tuturor produselor ROA. Cititorul e un agent: fiecare fisier tine **regula +
strictul de context care o face aplicabila + comanda de verificare**. Fara "de ce", fara istoric,
fara studii de caz.
**Se citeste primul: `reguli_lucru.md`** — regulile de livrare + lista de declansatoare ("cand
atingi zona X, citeste fisierul Y"). Restul se deschid doar la declansator.
## Cand citesti fiecare
| Fisier | Cand |
|---|---|
| `reguli_lucru.md` | intotdeauna, la inceput de sesiune |
| `orchestrare-subagenti.md` | cand delegi, cand verifici ce intoarce un subagent, la predarea contextului |
| `monitorizare-context.md` | instalarea hook-urilor de prag de context si de revizie a docs |
| `fluxul_svn_git.md` | orice commit / `svn update` / `roa_sync`; ce e interzis pe `main` in COMUN |
| `scripturi-uzuale.md` | exista deja un script pentru sarcina asta? (roa_sync, curatenie, livrare, diagnostice) |
| **VFP** | |
| `cautare_vcx_vct.md` | cauti cod in `.vcx`/`.scx`/`.frx`/`.mnx` |
| `flux-editare-vfp-text.md` | editezi `.vc2`/`.sc2` + write-back; **invariantele si `*p:`/`*m:`** |
| `conventie_encoding_cp1252.md` | fisierul editat are diacritice (cp1250, nu cp1252) |
| `inventar-comun.md` | inainte de cod nou: exista deja o functie/clasa comuna? |
| `conventie_ux_formulare.md` | adaugi/rearanjezi controale pe formular |
| `capcana_grid_controlsource.md` | grid needitabil pe formular cu 2+ grid-uri |
| `capcana_grid_preferinte_utilizator.md` | adaugi o coloana intr-un grid deja livrat |
| `conventie_go_recno.md` | `GO` pe un `Recno()` capturat |
| `conventie_null_vfp.md` | garzi pe valori NULL din Oracle |
| `conventie_goexecutor_alter_table.md` | `ALTER TABLE` pe cursorul de la `oExecute()` |
| **Testare** | |
| `depanare_testare_vfp.md` | rulare headless, depanare bug runtime, capcane VFP |
| `testare-ui-vfp.md` | test cu formular real + screenshots (harness UI) |
| **Oracle** | |
| `conventie_mediu_oracle.md` | te conectezi la dev/test, alegi schema, rulezi un script de pachet |
| `scripturi-migrare-db.md` | modifici schema (tabele/view-uri/pachete); compatibilitate 10.2 |
| `publicare-scripturi-db.md` | publici scripturile catre clienti |
| `oracle_export.md` | reexporti sursa unui pachet PL/SQL |
| `depanare-pack-update.md` | actualizarea ROA nu se finalizeaza la un client |
| `depanare-spatiu-oracle.md` | spatiu plin la un client |
| **Domeniu** | |
| `flux-modificare-stergere-nota-jurnal.md` | modificare/stergere nota; ce face `PACK_CONTAFIN` |
| `tipuri_documente_facturare.md` | `VANZARI.TIP` si seturile de contare `ID_SET` |
| `sold-neexigibil-reportat-jc2007-jv2007.md` | interogari pe sold TVA neexigibil |
| `email-thunderbird.md` | citirea mailurilor de pe conturile romfast |
`onboarding\` — proceduri rulate o singura data per proiect (inrolare in fluxul git-text,
prompturi de configurare). Nu se citesc in sesiunile de lucru.
`*.pck` — exporturi de referinta ale pachetelor PL/SQL, pentru grep tintit; nu se citesc intregi.
`cercetare\` — note de cercetare pe subiecte incheiate.
## Cand adaugi ceva aici
Doar reutilizabil (80/20): flux ascuns, capcana platita, procedura/tabela cheie. Cateva randuri.
Un subiect are **un singur proprietar** — celelalte fisiere primesc o trimitere de un rand, nu o
copie. Scrie **ASCII**, fara diacritice. Adauga si randul in tabelul de mai sus, plus
declansatorul in `reguli_lucru.md` punctul 7 daca regula se aplica la atingerea unei zone de cod —
fara declansator, regula nu e gasita la timp.

View File

@@ -1,183 +1,75 @@
# Căutare în codul din librăriile/formele VFP (`.vcx`/`.vct`, `.scx`/`.sct`, ...)
# Cautare in codul din librariile/formele VFP (.vcx/.vct, .scx/.sct, ...)
Partajat între proiectele ROA* (companion narativ la `PROMPT_cautare_vfp.md` din acest folder —
varianta "prompt de copiat" — acest fișier e ghidul de referință complet, cu exemple).
Căutare de cod-sursă (proceduri, metode, parametri) care **nu** stă în `.prg`, ci în interiorul
binarelor VFP: librării de clase (`.vcx`+`.vct`), forme (`.scx`+`.sct`), rapoarte (`.frx`+`.frt`),
meniuri (`.mnx`+`.mnt`), baze de date (`.dbc`+`.dct`).
Partajat intre proiectele ROA*. Cod-sursa (proceduri, metode, parametri) care **nu** sta in
`.prg`, ci in binarele VFP: librarii de clase (`.vcx`+`.vct`), forme (`.scx`+`.sct`), rapoarte
(`.frx`+`.frt`), meniuri (`.mnx`+`.mnt`), baze de date (`.dbc`+`.dct`).
## De ce e nevoie de asta
Un `.vcx` e o **tabelă DBF**: codul metodelor stă în câmpuri memo în `.vct`. `grep` direct pe
`.vct` găsește textul dar ca binar (octeți `\0` între linii), fără numere de linie și greu de
citit. Soluția: convertim binarul în reprezentarea lui **TEXT** (`.vc2`, `.sc2`, …) — PRG-style
lizibil, metode sortate alfabetic — și căutăm în text cu `grep`/`Grep`.
Un `.vcx` e o tabela DBF: codul metodelor sta in campuri memo in `.vct`. `grep` direct pe `.vct`
gaseste textul dar ca binar (octeti `\0` intre linii), fara numere de linie si greu de citit.
Solutia: se converteste binarul in text (`.vc2`, `.sc2`, ...) si se cauta cu `Grep`.
> **Regula de aur:** textul generat e **doar pentru citire/căutare**, CU O EXCEPȚIE: pentru
> `.vcx`/`.scx` se poate și edita pe text, cu write-back în binar (`txt2vcx.ps1`) — vezi
> `PROMPT_cautare_vfp.md` pasul 3 (ordine obligatorie, encoding, fidelity check). Pentru
> `.frx`/`.mnx`/`.dbc` nu există write-back — modificările se fac tot în **IDE-ul VFP**.
## Flux curent (proiecte migrate): in-arbore
## Unelte disponibile (verificate)
Migrate: ROACONT, COMUN, ROAGEST, ROAAUTO, ROAIMOB, ROAACNPRO, ROAFACTURARE, ROACONTRACTE
(prezenta `roa_sync.bat` in radacina proiectului = migrat).
| Unealtă | Cale | Rol | Recomandare |
|---|---|---|---|
| **FoxBin2Prg** | `D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE` | Binar VFP ⇄ text bidirecțional (`.vc2/.sc2/.fr2/.mn2/.dc2/.lb2`) | **De folosit.** Fidel, include corpul metodelor, parametri, comentarii |
| vcx2prg | `D:\ROA\UTIL\vcx2prg\x2prg.prg` | Doar `.vcx` → `.prg` compilabil | Alternativă mai veche, doar clase, necesită IDE VFP deschis |
| prgtovcx | `D:\ROA\UTIL\prgtovcx\prgtovcx.PRG` | Invers: `.prg` → `.vcx` | **Nu** pentru căutare (direcție opusă) |
Textul `.??2` sta langa binar. La inceput de sesiune si inainte de orice `git commit`:
FoxBin2Prg e prima alegere: rulează din linia de comandă fără IDE deschis (EXE compilat), acoperă
toate tipurile de container, text mai fidel decât vcx2prg.
> Dacă `FoxBin2Prg.EXE` lipsește: deschide `D:\ROA\UTIL\foxbin2prg\foxbin2prg.pj2` în VFP 9 și
> *Build > Build Executable*. Lângă EXE trebuie să existe `filename_caps.exe` și `props*.txt`
> (deja în folder).
## Mod recomandat: scriptul `vcx2txt.ps1`
`D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1` copiază binarul + memo-ul într-un **cache** care oglindește
structura proiectului (nu murdărește arborele SVN), rulează FoxBin2Prg, păstrează doar textul.
**Incremental** (sare peste ce e deja la zi).
```powershell
# DOAR fișierele proiectului curent (recomandat, rapid) -> cache text propriu
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
-Project '<RADACINA_PROIECT>\<proiect>.pjx' -ProjectRoot '<RADACINA_PROIECT>' `
-CacheRoot 'D:\ROA\_vfp_textcache\<nume_proiect>'
# include și rapoartele (.frx) și meniurile (.mnx)
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
-Project '<RADACINA_PROIECT>\<proiect>.pjx' -ProjectRoot '<RADACINA_PROIECT>' `
-CacheRoot 'D:\ROA\_vfp_textcache\<nume_proiect>' -Types vcx,scx,frx,mnx
# conversie punctuală a unui fișier/folder (chiar dacă NU e în proiect, ex. o clasă din COMUN)
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Source '<RADACINA_PROIECT>\COMUN\clase\caut.vcx'
# rebuild curat (șterge cache-ul întâi) / forțează reconversia
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
-Project '<RADACINA_PROIECT>\<proiect>.pjx' -ProjectRoot '<RADACINA_PROIECT>' `
-CacheRoot 'D:\ROA\_vfp_textcache\<nume_proiect>' -Clean
```
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\git_sync.ps1 -ProjectRoot <root>
```
Exemplu (ROAAUTO):
Apoi cauta direct cu `Grep` in `.??2` din arbore (`PROCEDURE do_salvare`, etc.), citand
`fisier:linie`.
```powershell
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
-Project D:\ROA\ROAAUTO\roaauto.pjx -ProjectRoot D:\ROA\ROAAUTO `
-CacheRoot D:\ROA\_vfp_textcache\roaauto
```
## Indexul de simboluri: vfp_symbols.ps1
> Cache-ul trebuie să stea **în afara** folderului `D:\ROA\UTIL\foxbin2prg`: `ReCreate_FoxBin2Prg.prg`
> face `Prg2Bin` recursiv pe tot folderul uneltei și ar reconverti `.??2`-urile din cache în binare
> rătăcite.
Rezultatul ajunge în cache, cu aceeași structură de directoare ca proiectul (ex.:
`roaauto\Clase\odevize.vc2`, `roaauto\comun\clase\_frm_base.vc2`). Apoi:
```bash
grep -rn "PROCEDURE do_calcul_tarife" "D:\ROA\_vfp_textcache\<nume_proiect>"
grep -rln "factura_salvare" "D:\ROA\_vfp_textcache\<nume_proiect>" # ce clase ating subiectul
```
Flux tipic: rulează scriptul o dată (populează cache-ul), apoi caută cu `Grep` în cache. La
sesiuni următoare rescrie doar ce s-a schimbat (incremental). Pentru o librărie din `COMUN\` care
nu e în proiect, convertește-o punctual cu `-Source`.
## Indexul de simboluri: `vfp_symbols.ps1`
`grep` spune *unde* e textul, nu *în ce metodă*. Într-un `.vc2` asta contează: fișierele au uzual
zeci de mii de linii, din care ~2/3 sunt proprietăți și metadata (nu cod), iar antetul clasei poate
fi cu mii de linii deasupra potrivirii. `D:\ROA\UTIL\foxbin2prg\vfp_symbols.ps1` reține intervalul
de linii al fiecărei clase/metode/proceduri — din cache-ul text **și** din `.prg`-urile proiectului
— și etichetează rezultatele.
`grep`/`Grep` spune *unde* e textul, nu *in ce metoda*. Intr-un `.vc2` cu zeci de mii de linii
(~2/3 proprietati/metadata, nu cod) si 15 clase care au fiecare `Init`/`Show`/`do_adauga`, fara
interval e usor sa nimeresti metoda gresita.
```powershell
$s = 'D:\ROA\UTIL\foxbin2prg\vfp_symbols.ps1'
$c = @('-CacheRoot', 'D:\ROA\_vfp_textcache\<nume_proiect>', '-ProjectRoot', '<RADACINA_PROIECT>')
$c = @('-CacheRoot', '<root>', '-ProjectRoot', '<root>')
# căutare etichetată cu clasa.metoda; -CodeOnly taie potrivirile din metadata/proprietăți
powershell -ExecutionPolicy Bypass -File $s @c -Grep '<expresie>' -CodeOnly
powershell -ExecutionPolicy Bypass -File $s @c -Where '<fisier>.vc2:<linie>' # cine deține linia
powershell -ExecutionPolicy Bypass -File $s @c -Find '<nume>' # unde e DEFINIT
powershell -ExecutionPolicy Bypass -File $s @c -Class '<nume_clasa>' # moștenire + metode
powershell -ExecutionPolicy Bypass -File $s @c -Grep '<expresie>' -CodeOnly # etichetat clasa.metoda, doar cod
powershell -ExecutionPolicy Bypass -File $s @c -Where '<fisier>.vc2:<linie>' # cine detine linia
powershell -ExecutionPolicy Bypass -File $s @c -Find '<nume>' # unde e DEFINIT
powershell -ExecutionPolicy Bypass -File $s @c -Class '<nume_clasa>' # mostenire + metode
```
Exemplu (ROAACNPRO — parametrii impliciți ai scriptului țintesc deja acest proiect):
**`-Where`/`-Class` sunt OBLIGATORII inainte de o editare cu `txt2vcx.ps1`** - dau intervalul
exact al metodei. Indexul se reconstruieste din text cand textul e mai nou: ruleaza `git_sync.ps1`
inainte, altfel nu vede modificari facute in IDE si neconvertite.
```
> vfp_symbols.ps1 -Grep 'calcul_cheiaj' -CodeOnly
clase\oacnpro.vc2:14937: [frm_tranzit.do_executa] llSucces = calcul_cheiaj(m.lcVyeIds)
> vfp_symbols.ps1 -Class oApp
oApp (roaacnpro.prg:88) -> RoaApp (roa.prg:1) -> Custom (clasă de bază VFP)
```
Limite: nu rezolva apelurile indirecte (`EVALUATE`, `SET CLASSLIB`) - da candidati, nu
certitudine. Clasele de baza VFP (`form`, `custom`) apar neindexate (n-au sursa in proiect).
Copiile vechi de `.prg` din subfoldere sunt excluse implicit prin `-ExcludePrg`; da
`-ExcludePrg ''` ca sa vezi tot.
Când merită în locul unui `grep` direct:
- **înainte de o editare cu `txt2vcx.ps1`** — `-Where`/`-Class` dau intervalul exact al metodei.
Într-un `.vc2` cu 15 clase, `Init`, `Show`, `do_adauga`, `do_executa2` există în aproape fiecare;
fără interval e ușor să nimerești metoda cu același nume din altă clasă;
- **rezultate multe** — `-CodeOnly` arată doar codul (pe `goExecutor` în ROAACNPRO: 1401 potriviri
de cod din 1505, restul metadata);
- **„definit sau doar apelat?"** — `-Find` dă doar definiția, `grep` dă tot;
- **moștenire** — `-Class` arată lanțul cu fișier:linie, deci se vede dacă o metodă e suprascrisă
local sau vine din `COMUN`.
Indexul (`_symbols.tsv`, în rădăcina cache-ului) se reconstruiește singur când cache-ul e mai nou
(~4 s pentru ~200 de fișiere); e regenerabil, se poate șterge oricând. Rulează întâi `vcx2txt.ps1`:
indexul e derivat din cache, deci nu poate ști de modificări făcute în IDE și neconvertite.
Limite: nu rezolvă apelurile indirecte (`EVALUATE`, `SET CLASSLIB`) — dă candidații, nu
certitudinea. Clasele de bază VFP (`form`, `custom`) apar ca neindexate: normal, n-au sursă în
proiect. Copiile vechi de `.prg` din subfoldere (ex. `COMUN\programe\roa\`) sunt excluse implicit
prin `-ExcludePrg`; dă `-ExcludePrg ''` ca să vezi tot.
## Alternativă manuală (fără script)
FoxBin2Prg scrie textul **lângă sursă**. Ca să nu murdărești folderul de clase al proiectului,
copiază perechea binar+memo într-un folder temporar și convertește acolo:
```powershell
# .vcx -> .vc2 (cType gol = extensia decide direcția BIN2PRG)
Copy-Item D:\ROA\<proiect>\Clase\odevize.vcx, D:\ROA\<proiect>\Clase\odevize.vct D:\tmp\
& 'D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE' 'D:\tmp\odevize.vcx' '' '' '' '1' '0' '1'
# => D:\tmp\odevize.vc2
```
Poziții parametri: `fișier, cType, cTextName, lGenText, cDontShowErrors=1, cDebug=0,
cDontShowProgress=1`. **Lasă `cType` gol** — extensia (`.vcx`) determină direcția. (Nu da explicit
`"BIN2PRG"` pentru un singur fișier: în acel mod EXE-ul așteaptă un *director*.)
Detalii complete de parametri: `D:\ROA\UTIL\foxbin2prg\docs\FoxBin2Prg_Run.md`.
## Soluție rapidă „murdară" (un singur fișier, fără conversie)
Pentru „există metoda X undeva în librărie?", `grep` merge direct pe `.vct` (îl vede ca binar, dar
găsește potrivirile):
```bash
grep -c "PROCEDURE" "D:\ROA\<proiect>\Clase\odevize.VCT"
grep -a -o "PROCEDURE [a-zA-Z0-9_]*" "D:\ROA\<proiect>\Clase\odevize.VCT"
```
Bun pentru „da/nu" și nume de metode; pentru corp/context, folosește conversia în text.
## Corespondență extensii binar → text
## Corespondenta extensii binar -> text
| Container | Binar (+memo) | Text |
|---|---|---|
| Librărie clase | `.vcx` + `.vct` | `.vc2` |
| Formă | `.scx` + `.sct` | `.sc2` |
| Librarie clase | `.vcx` + `.vct` | `.vc2` |
| Forma | `.scx` + `.sct` | `.sc2` |
| Raport | `.frx` + `.frt` | `.fr2` |
| Etichetă | `.lbx` + `.lbt` | `.lb2` |
| Eticheta | `.lbx` + `.lbt` | `.lb2` |
| Meniu | `.mnx` + `.mnt` | `.mn2` |
| Bază de date | `.dbc` + `.dct` | `.dc2` |
| Baza de date | `.dbc` + `.dct` | `.dc2` |
## Note
## Proiecte NEmigrate (cache extern)
- Codul aplicației stă mai ales în `Clase\*.vcx`; multe `.vcx`-uri sunt în `COMUN\` (framework
partajat între toate aplicațiile ROA — vezi `CLAUDE.md` per proiect).
- Cache-ul text e regenerabil, în afara arborelui SVN/git al proiectului — poate fi șters oricând.
- Conversia **nu** necesită IDE-ul VFP deschis (folosește EXE-ul compilat).
- Vezi și [conventie_encoding_cp1252.md](conventie_encoding_cp1252.md) — capcană de encoding la
editarea `.sc2`/`.vc2` (nu doar la căutare).
```
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Project <pjx> -ProjectRoot <root> -CacheRoot <cache>
```
`-CacheRoot` trebuie sa stea **in afara** folderului `foxbin2prg`: `ReCreate_FoxBin2Prg.prg` face
`Prg2Bin` recursiv pe tot folderul uneltei si ar reconverti `.??2`-urile in binare parazitare.
## Editare si write-back
Vezi `flux-editare-vfp-text.md`. Regula de aur: `.frx`/`.mnx`/`.lbx`/`.pjx`/`.dbc`/`.dbf` sunt
read-only (editare doar in IDE-ul VFP); write-back suportat doar pentru `.vcx`/`.scx`.

View File

@@ -1,101 +1,57 @@
# Capcană: corupere diacritice la editarea `.sc2`/`.vc2`
# Capcana: corupere diacritice la editarea .sc2/.vc2
Partajat între proiectele ROA* — capcana ține de formatul `.sc2`/`.vc2` produs de FoxBin2Prg,
nu de un proiect anume.
Comun tuturor proiectelor ROA* - tine de formatul .sc2/.vc2 (FoxBin2Prg), nu de un proiect anume.
## De ce se întâmplă
## Faptul
Fișierele `.sc2`/`.vc2` sunt **cp1250** (Windows-1250, Europa Centrală), nu UTF-8 — deși
antetul FoxBin2Prg declară `CPID="1252"`. Eticheta din antet nu corespunde conținutului:
controalele care poartă text cu diacritice au `FontCharSet = 238` (Europa de Est), adică VFP
le randează tot ca cp1250. Diferența nu e cosmetică — un `ă` real scris prin cp1252 nu are
echivalent în acel codepage și s-ar pierde; scris prin cp1250 (encoding-ul real al fișierului)
e pur și simplu octetul `0xE3`, corect și stabil.
Fisierele .sc2/.vc2 sunt cp1250 (Europa Centrala), nu UTF-8, desi antetul FoxBin2Prg declara
CPID="1252" - eticheta din antet nu e adevarul despre encoding. Controalele cu text diacritic
au FontCharSet = 238.
Dacă un editor/tool citește fișierul ca UTF-8, fiecare byte >= 0x80 (diacritic) devine invalid
ca secvență UTF-8 și e înlocuit cu U+FFFD. Dacă tool-ul apoi **salvează tot ca UTF-8**, acel
U+FFFD e scris ca 3 octeți (`0xEF 0xBF 0xBD`) — care, citiți înapoi ca cp1250 (cum face
FoxBin2Prg la write-back), apar ca `�`. Caracterul original e **ireversibil pierdut**
(recuperabil DOAR din altă sursă: git history, backup).
## Tabelul de octeti (cp1250 real -> aparenta daca decodezi gresit ca cp1252)
Octeții diacriticelor din codebase-ul ROA, cu adevărul (cp1250) și aparența dacă îi decodezi
greșit ca cp1252:
| Literă românească | Byte | Aparență dacă decodezi ca cp1252 |
| Litera | Byte | Aparenta cp1252 gresita |
|---|---|---|
| ă | `0xE3` | ã (a-tilde) |
| Ă | `0xC3` | Ã |
| î | `0xEE` | î (identic — zonă comună cp1250/cp1252) |
| Î | `0xCE` | Î (identic — zonă comună cp1250/cp1252) |
| â | `0xE2` | â (identic — zonă comună cp1250/cp1252) |
| ț | `0xFE` | þ (thorn minuscul) |
| Ș (majusculă) | `0xAA` | ª (ordinal masculin) |
| ș (minusculă) | `0xBA` | º (ordinal feminin) |
| a cu caciula minuscul | 0xE3 | a-tilde |
| A cu caciula majuscul | 0xC3 | A-tilde |
| i cu caciula minuscul | 0xEE | identic (zona comuna cp1250/cp1252) |
| I cu caciula majuscul | 0xCE | identic (zona comuna cp1250/cp1252) |
| a circumflex | 0xE2 | identic (zona comuna cp1250/cp1252) |
| t cu virgula minuscul | 0xFE | thorn minuscul |
| S cu virgula majuscul | 0xAA | ordinal masculin |
| s cu virgula minuscul | 0xBA | ordinal feminin |
Decodate cp1250 (encoding-ul real), aceste litere sunt diacritice românești normale — exact
ce apare în formular când fișierul e sănătos. Par "gunoi"/typo (`ã`, `þ`, `ª`, `º`) **doar
dacă le decodezi cu codepage-ul greșit** — nu le "corecta" fără să verifici encoding-ul real.
Nu "corecta" un s-cu-virgula crezand ca e typo - e litera corecta in cp1250.
## Cum se verifică dacă un fișier `.sc2`/`.vc2` e corupt
## Regula operationala
Verificarea se face **pe octeți**, nu pe text decodat: un codepage single-byte (1250 sau 1252)
mapează fiecare octet la un caracter, deci nu produce niciodată U+FFFD — o căutare de
`[char]0xFFFD` în textul decodat nu găsește nimic nici pe un fișier stricat. Ce se caută e
secvența de trei octeți pe care a lăsat-o tool-ul care a stricat fișierul:
Orice scriere cu un tool care nu pastreaza octetii nativ (Edit/Write) corupe TOATE caracterele
>= 0x80 din TOT fisierul (0xBA -> EF BF BD), chiar la o singura linie schimbata, si se repeta
la FIECARE scriere. Nu re-encoda niciodata fisierul intreg: lucreaza pe octeti
([IO.File]::ReadAllBytes/WriteAllBytes cu GetEncoding(1250)) sau scrie strict ASCII in
continutul nou. Editeaza tot ce ai de editat, verifica, repara o singura data DUPA ultima
scriere.
```powershell
$b = [System.IO.File]::ReadAllBytes("<path>.vc2")
$n = 0
for ($i = 0; $i -lt $b.Length - 2; $i++) {
if ($b[$i] -eq 0xEF -and $b[$i+1] -eq 0xBF -and $b[$i+2] -eq 0xBD) { $n++; $i += 2 }
}
"EF BF BD (U+FFFD) x $n" # orice valoare > 0 = fisier stricat
```
Echivalentul din Bash, util și pentru censul complet înainte/după orice editare (vezi
`reguli_lucru.md`, punctul 7):
## Verificare (cens de octeti)
```bash
od -An -tx1 <path>.vc2 | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c
od -An -tx1 <fisier> | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c
```
Censul **crește** la stricare — un octet cp1250 devine trei octeți de U+FFFD — deci nu urmări
doar scăderile. Decodat cp1250, `EF BF BD` apare ca `ďż˝` în caption.
La stricare censul CRESTE (un octet devine trei) - nu urmari doar scaderile. Cauta explicit
secventa `EF BF BD`, nu tiparul generic `C3`/`C4`/`C5`/`C8` (acela apare si in UTF-8 legitim
din cod).
## Cum se repară
## Reparare
1. **Nu edita orbește peste corupere** — caracterul original e deja pierdut din fișierul curent.
2. Dacă corupera s-a întâmplat într-o sesiune anterioară necomisă (HEAD-ul git încă e curat):
recuperează originalul convertind binarul din HEAD în text:
```bash
git show HEAD:<cale>.vcx > /tmp/head.vcx
git show HEAD:<cale>.vct > /tmp/head.vct # (sau .VCT, dupa caz)
powershell -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Source /tmp/head.vcx -CacheRoot /tmp/head_out
```
Dacă și HEAD e deja corupt (corupera a fost comisă), caută ultima versiune curată cu
`git cat-file blob <commit>:<cale>` (din Bash, niciodată cu `>` din PowerShell 5.1 — adaugă
BOM și re-encodează) sau `svn cat <fișier>` — ambele surse independente de encoding-ul
curent al fișierului.
Apoi decodează ambele fișiere (versiunea curată + curent corupt) ca cp1250 și compară linie
cu linie (PowerShell, nu `diff`/Bash direct — nu decodează cp1250 corect la afișare, deși
detectează totuși diferența de octeți).
3. Reconstruiește fișierul text pornind de la versiunea curată, reaplicând DOAR modificările
intenționate din sesiunea curentă (nu invers — nu cârpi fișierul corupt caracter cu
caracter).
4. Scrie rezultatul înapoi ca bytes cp1250
(`[System.Text.Encoding]::GetEncoding(1250).GetBytes(...)`), NU ca string UTF-8/`Out-File`
implicit.
5. Rulează write-back (`txt2vcx.ps1 -Force`) și verifică fidelity check = zero diferențe.
`EF BF BD` nu spune ce caracter s-a pierdut (toate diacriticele devin la fel) - inlocuirea
oarba cu 0xBA strica alte litere din alte pozitii. Ia octetul corect per pozitie din
`svn cat <fisier>` sau `git cat-file blob <commit>:<cale>`, din Bash, niciodata cu `>` din
PowerShell 5.1 (adauga BOM si re-encodeaza). Scrie inapoi ca bytes cp1250 explicit, apoi
`txt2vcx.ps1` + fidelity check.
## Cum se evită pe viitor
Cazul simplu (s-a pierdut doar 0xBA), inlocuire punctuala pe octet:
Când editezi `.sc2`/`.vc2` cu tool-uri text (Read/Edit/Write), verifică întâi dacă fișierul
conține diacritice (`ă`, `ț`, `Ș`, `ș`, `î`, `â` etc.) — dacă da, **orice rescrie completă
trebuie făcută la nivel de octeți cu encoding cp1250 explicit**, nu presupunând UTF-8.
Editările punctuale (Edit tool, string replace) sunt sigure DOAR dacă tool-ul păstrează restul
fișierului byte-identic (nu rescrie tot fișierul reîncodat).
## Vezi și
`PROMPT_cautare_vfp.md` din acest folder, pasul 3.c — menționează riscul pe scurt; acest fișier
e detalierea completă (tabel de caractere, pași de recuperare din git).
```bash
perl -e 'binmode(STDIN);binmode(STDOUT);local $/;$_=<STDIN>;s/\xEF\xBF\xBD/\xBA/g;print' < f > f.tmp
```

View File

@@ -1,31 +1,24 @@
# Capcană: `ALTER TABLE` pe cursorul întors de `goExecutor.oExecute()`
# Capcana: ALTER TABLE pe cursorul intors de goExecutor.oExecute()
Partajat între proiectele ROA* — `goExecutor` (clasa `oExecutor`, definită în
`COMUN/programe/oproceduri_comune.prg`, metoda `oExecute`) e utilitarul standard pentru
interogări SQL pass-through (`SQLExec`) către Oracle, folosit peste tot în codul ROA*.
Comun tuturor proiectelor ROA*.
## Ce nu funcționează
## Ce nu functioneaza
```foxpro
lnSucces = goExecutor.oExecute(lcSql, lcCursor)
...
ALTER TABLE (lcCursor) ADD COLUMN coloananoua L && <- pică
ALTER TABLE (lcCursor) ADD COLUMN coloananoua L && <- pica
```
Cursorul întors de `oExecute()` poate refuza comenzi DDL ulterioare, cu erori în lanț
(descoperite empiric, în această ordine):
Simptome intalnite, in aceasta ordine: `Function is not supported on remote tables.` (ALTER
TABLE direct pe cursorul original) / `Alias name is already in use.` (rematerializare cu
sursa si tinta acelasi nume) / `Invalid operation for the cursor.` (ALTER TABLE pe alias
scratch diferit ca tinta).
1. `Function is not supported on remote tables.` — pe `ALTER TABLE` direct pe cursorul original.
2. Chiar și după rematerializare (`SELECT * FROM (cursor) INTO CURSOR (acelasi_nume) READWRITE`)
→ `Alias name is already in use.` (sursa și ținta nu pot avea același nume).
3. Cu alias scratch diferit ca țintă → tot `Invalid operation for the cursor.` pe `ALTER TABLE`,
chiar dacă țintă ar trebui să fie deja un cursor local obișnuit.
## Ce functioneaza
## Ce funcționează
**Nu folosi `ALTER TABLE` deloc pe rezultatul unui `oExecute()`.** Include coloanele
suplimentare direct în `SELECT`-ul de rematerializare, ca expresii literale alături de `*`
(VFP suportă `SELECT *, expr AS coloana FROM ...`):
Nu folosi `ALTER TABLE` deloc pe rezultatul unui `oExecute()`. Include coloanele suplimentare
direct in `SELECT`-ul de rematerializare, ca expresii literale alaturi de `*`:
```foxpro
lcCursorRaw = lcCursor + '_raw'
@@ -45,11 +38,6 @@ USE IN (lcCursorRaw)
* de-aici incolo doar REPLACE (date), NICIODATA ALTER TABLE (structura) pe (lcCursor)
```
După acest pas, cursorul (`lcCursor`) e un cursor local obișnuit — `ALTER TABLE` funcționează
normal pe el DUPĂ ACEEA (ex. într-o altă funcție care primește cursorul deja gata construit),
doar comanda imediat următoare unui `oExecute()` e restricționată.
## Vezi și
Exemplu complet aplicat: ROAAUTO, `Programe/oproceduri_autopass.prg`,
`autopass_cursor_comenzi()`/`autopass_cursor_operatii()`.
Dupa acest pas cursorul (`lcCursor`) e un cursor local obisnuit - `ALTER TABLE` functioneaza
normal pe el DUPA ACEEA (ex. intr-o alta functie care primeste cursorul deja gata construit),
doar comanda imediat urmatoare unui `oExecute()` e restrictionata.

View File

@@ -48,11 +48,18 @@ select text from all_source
## 4. Conectare
Client: `D:\ROA\instantclient_19_18\sqlplus.exe` (`TNS_ADMIN` deja setat spre acelasi folder).
Alias TNS: `ROA_CENTRAL` -> `10.0.20.121:1521`, `SERVICE_NAME=ROA` (`tnsnames.ora` din acelasi
folder).
```
& 'D:\ROA\instantclient_19_18\sqlplus.exe' -L -S 'MARIUSM_AUTO/ROMFASTSOFT@ROA_CENTRAL' '@fisier.sql'
```
Fisierul `.sql` se scrie in **ASCII**. SQL trimis prin pipe din PowerShell e spart de BOM.
Fisierul `.sql` se scrie in **ASCII**. SQL trimis prin pipe din PowerShell e spart de BOM
(`SP2-0734: unknown command beginning "...select..."` - BOM UTF-16 sparge parserul).
Parola nu e versionata in git - in `COMUN\docs\local\oracle.md` (ignorat de git, exista in SVN).
## 5. Ce inseamna "se ruleaza un script de pachet"

View File

@@ -1,53 +1,36 @@
# Convenție UX pentru formulare VFP (preferința lui Marius, valabilă pe toate proiectele ROA*)
# Conventie UX pentru formulare VFP
Partajat între proiectele ROA* — `COMUN\` e clonat/sincronizat în fiecare aplicație ROA, e locul
corect pentru o convenție de design care nu ține de un singur proiect.
Comun tuturor proiectelor ROA*.
## Ce înseamnă in practică, pe proprietăți VFP
## Layout
- **Fiecare grup funcțional pe rândul lui**, nu înghesuit pe același `Top` cu altul fără
legătură (ex: perioadă / statistici / configurare, pe rânduri separate).
- **Spațiere vizibilă între grupuri, strânsă în interiorul unui grup** — butoane din aceeași
acțiune la 6-10px unele de altele; gap de 20-30px față de următorul grup funcțional.
- **Butoanele secundare/de configurare aliniate la marginea din dreapta a containerului**, nu
lipite imediat după textbox-ul pe care îl controlează — altfel nu se disting ca acțiune
separată de câmpul de input.
- **Acțiunea principală + oprirea ei alăturate** (ex. Transmite + Renunță), nu împrăștiate în
altă parte a rândului.
- **Un singur rând de acțiuni cât se poate** — un rând orizontal in loc de rânduri noi
dedesubt; formele rămân compacte pe verticală.
- **Caption-uri scurte, sentence case, nu ALL CAPS** — ex. "Transmite" nu "TRANSMITE". ALL
CAPS/text lung pe un buton citește ca zgomot, nu ca ierarhie.
- **Culoare = semnal, nu decor** — doar pentru acțiuni cu semnificație clară (verde =
pozitiv/transmite, roșu = oprire/pericol, albastru = navigare/link extern); restul butoanelor
rămân stilul implicit din `_baza.vcx`.
- Fiecare grup functional pe randul lui, nu inghesuit pe acelasi Top cu altul fara legatura
(ex: perioada / statistici / configurare, pe randuri separate).
- Spatiere vizibila intre grupuri, stransa in interiorul unui grup: butoane din aceeasi actiune
la 6-10px unele de altele; gap de 20-30px fata de urmatorul grup functional.
- Butoanele secundare/de configurare aliniate la marginea din dreapta a containerului, nu
lipite imediat dupa textbox-ul pe care il controleaza - altfel nu se disting ca actiune
separata de campul de input.
- Actiunea principala + oprirea ei alaturate (ex. Transmite + Renunta), nu imprastiate in alta
parte a randului.
- Un singur rand de actiuni cat se poate - un rand orizontal in loc de randuri noi dedesubt;
formele raman compacte pe verticala.
- Caption-uri scurte, sentence case, nu ALL CAPS - ex. "Transmite" nu "TRANSMITE".
- Culoare = semnal, nu decor - doar pentru actiuni cu semnificatie clara (verde =
pozitiv/transmite, rosu = oprire/pericol, albastru = navigare/link extern); restul
butoanelor raman stilul implicit din `_baza.vcx`.
## Clase de controale (confirmat de Marius, 24.07.2026, pe frm_verif_partener_anaf ROACONT)
- **Intotdeauna controale din `_baza.vcx`, nu controale native VFP** — orice grid, label,
- Intotdeauna controale din `_baza.vcx`, nu controale native VFP - orice grid, label,
textbox, checkbox etc. dintr-un formular nou se bazeaza pe clasa corespunzatoare din
`COMUN\clase\_baza.vcx`, nu pe clasa nativa Visual FoxPro. Clasele din `_baza.vcx` au
fontul default **Arial 10** — nu se suprascrie FontName pe controale (explicit: fara
Arial Narrow).
- **Butoanele de inchidere/confirmare stau in bara de titlu**, din `cmd_butoane.vcx` —
modelul Renunt/Termin (clasa de forma `frm_termin_renunt` din `_frm_child.vcx` le aduce
deja). Nu se dubleaza aceste actiuni cu butoane in corpul formei.
- **Actiunile care au corespondent `but_*` in `cmd_butoane.vcx`** (Nou/Adauga, Modifica,
Salveaza, Sterge, Verifica etc.) folosesc CU PREDILECTIE clasa dedicata `but_*`
respectiva — nu se improvizeaza un buton generic pentru o actiune care are deja clasa ei.
- **Doar actiunile FARA corespondent `but_*`** primesc butoane pe clasele `cmd_*` din
`cmd_butoane.vcx` (ex. `cmd_executa`) — nu clase improvizate si nu CommandButton nativ.
## Vocabular
Funcțional, compact, aerisit, minimalist, grupat, ușor de înțeles de utilizatori, modern —
asta e reperul calitativ pentru orice formular nou sau refacere de layout, pe orice
aplicație ROA*.
## Vezi și
- `PROMPT_cautare_vfp.md` din acest folder — cum se caută/editează cod în binarele VFP text-cache
(relevant când aplici aceste reguli prin fluxul `.sc2`/`.vc2` + write-back).
- `conventie_encoding_cp1252.md` din acest folder — capcana de corupere a diacriticelor la
editarea `.sc2`/`.vc2`; relevantă ori de câte ori editezi text-cache-ul unui formular/librărie
pentru a aplica aceste reguli de UX.
`COMUN\clase\_baza.vcx`. Fontul default e Arial 10 - nu se suprascrie FontName pe controale
(explicit: fara Arial Narrow).
- Butoanele de inchidere/confirmare stau in bara de titlu, din `cmd_butoane.vcx` - modelul
Renunt/Termin (clasa `frm_termin_renunt` din `_frm_child.vcx` le aduce deja). Nu se
dubleaza aceste actiuni cu butoane in corpul formei.
- Actiunile care au corespondent `but_*` in `cmd_butoane.vcx` (Nou/Adauga, Modifica,
Salveaza, Sterge, Verifica etc.) folosesc CU PREDILECTIE clasa dedicata `but_*` respectiva -
nu se improvizeaza un buton generic pentru o actiune care are deja clasa ei.
- Doar actiunile FARA corespondent `but_*` primesc butoane pe clasele `cmd_*` din
`cmd_butoane.vcx` (ex. `cmd_executa`) - nu clase improvizate si nu CommandButton nativ.

View File

@@ -62,30 +62,17 @@ Fisierul se poate citi si fara acces la desktopul serverului, prin `UTL_FILE` pe
`DMPDIR` (`fopen(...,'R',32767)` + `get_line` in bucla; tine ultimele N linii intr-un tablou —
partea utila e la sfarsit).
### Caz: nu orice esec de script e o problema de SQL (SIGMA, 03.08.2026)
### Un esec de script raportat nu inseamna neaparat o problema de SQL in script
`ff_2026_07_29_02_COMUN_TVA11.SQL` a picat pe `MARCU` cu `ORA-01653: unable to extend table
SYS.INFO ... in tablespace SYSTEM` (din `SYS.PINFO`/`SYS.AUTH_PACK`, recursiv). Tablespace-ul
`SYSTEM` era plin: autoextensibil, dar cu `maxbytes` atins la 600 MB, ~2 MB liberi. **Orice**
script ar fi picat identic — `AUTH_PACK` scrie in `SYS.INFO` la fiecare conectare. Cand eroarea nu
priveste obiectele scriptului, verifica intai spatiul.
Ce a contat, pentru data viitoare:
- **`maxbytes` mic nu e o limita XE.** Cele 11 GB ale XE sunt pe *date utilizator*; un plafon mic pe
`SYSTEM.DBF` e o setare de instalare. Se ridica din `contafin_oracle` (are `ALTER DATABASE`):
`alter database datafile '<cale>\SYSTEM.DBF' autoextend on next 50M maxsize 2000M;`
- **Spatiul pe discul serverului se verifica fara RDP**, cu `sys.ExecuteScriptOS` (vezi mai jos) —
`Get-WmiObject Win32_LogicalDisk -Filter "DriveType=3"`, iesire in `DMPDIR`, citita cu `UTL_FILE`.
Job asincron, dar raspunde in cateva secunde.
- **`SYS.INFO` e tabel ROA, nu obiect de dictionar** (log de login scris de `PINFO`, ~7 randuri per
conectare, +16-17k randuri/luna, nimic din baza nu-l citeste). Se poate goli, **dar numai ca
`SYSDBA`**: privilegiile `ANY` (`DROP ANY TABLE`, `DELETE ANY TABLE`) nu se aplica pe obiectele
din schema `SYS` cat timp `O7_DICTIONARY_ACCESSIBILITY=FALSE`, deci din `contafin_oracle` iese
`ORA-01031`.
- Restul lui `SYSTEM` era dictionar Oracle (`IDL_UB1$`, `SOURCE$`, `IDL_UB2$`, `ARGUMENT$` ~207 MB) —
de neatins fara export/import. `AUD$`/`FGA_LOG$` erau goale. Recyclebin-ul si bloat-ul de scheduler
stateau in `ROA`/`SYSAUX`, nu in `SYSTEM`.
Eroarea Oracle poate veni din obiecte cu totul straine de ce modifica scriptul (ex.
`ORA-01653: unable to extend table SYS.INFO ... in tablespace SYSTEM`, ridicata din
`SYS.PINFO`/`AUTH_PACK` la conectare, nu din scriptul insusi) - orice script ar fi picat identic.
Cand mesajul de eroare nu priveste obiectele pe care scriptul chiar le atinge, verifica intai
spatiul (`maxbytes` pe tablespace-ul din mesaj nu e o limita XE - cele 11 GB XE sunt pe date
utilizator, plafonul mic e o setare de instalare, se ridica din `contafin_oracle` cu
`alter database datafile '<cale>\<TS>.DBF' autoextend on next 50M maxsize 2000M;`). Spatiul pe
discul serverului se verifica fara RDP cu `sys.ExecuteScriptOS` (vezi mai jos, sectiunea "Comenzi
OS pe serverul de baze de date").
## Descarcarea (UpdateApp)

View File

@@ -28,18 +28,14 @@ $p.WaitForExit(120000); if (!$p.HasExited) { $p.Kill() }
- `-A` ignora config.fpw implicit, `-T` sare peste splash; **ambele obligatorii** - fara `-T`
procesul ramane pe ecranul de intampinare (simptom identic cu o eroare de compilare). `-c<cale>`
explicit (lipit de flag) e preluat si cu `-A`.
- **SAFETY**: sub `-A` porneste ON - primul `STRTOFILE` peste un log existent (sau `COMPILE` peste
un `.err`/`.fxp` existent) scoate dialogul modal "overwrite?" si procesul pare agatat. Pune
`SET SAFETY OFF` ca PRIMA linie din script si/sau `SAFETY=OFF`+`RESOURCE=OFF` intr-un config.fpw
propriu pasat cu `-c`. Verificare: logheaza `SET("SAFETY")`/`SET("RESOURCE")` la start.
- **SAFETY**: sub `-A` porneste ON - vezi sectiunea 7 pentru capcana completa si remediu.
- In script: logare cu STRTOFILE (nu WAIT WINDOW / debugger - nu exista consola);
`ON ERROR DO <handler> WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()` care logheaza si
continua (mimeaza ErrorHandler); `QUIT` obligatoriu la final.
- `LINENO()` din handler e relativ la inceputul metodei: linia in `.vc2` = linia raportata +
linia `PROCEDURE`.
- Nu rula cu IDE-ul sau exe-ul aplicatiei deschis (lock pe binare); sterge `.fxp`-ul vechi dupa
editarea scriptului - altfel VFP ruleaza codul vechi din `.fxp` fara niciun semn (testul poate
trece fals; se prinde doar cand lipseste din log o linie scrisa doar de codul nou).
- Nu rula cu IDE-ul sau exe-ul aplicatiei deschis (lock pe binare). Sterge `.fxp`-ul vechi dupa
editarea scriptului - vezi sectiunea 7 pentru simptomul complet de `.FXP`/`.ERR` stale.
- Forme modale: `Show(1)` blocheaza. Replica in script doar liniile relevante din Show, sau
seteaza `WindowType = 0`.
@@ -134,9 +130,12 @@ Cand un bug apare "de azi", compara cu clasa veche fara sa atingi SVN:
## 7. Capcane la SCRIEREA scriptului de test
- **`SET SAFETY OFF` in primele linii, INAINTE de orice `STRTOFILE`/`CREATE CURSOR`** (plus
`SET TALK OFF`). Fara el VFP deschide dialogul de confirmare la suprascriere, iar headless
dialogul blocheaza procesul pana la timeout. Suitele existente il au deja - capcana apare la
- **`SET SAFETY OFF` in primele linii, INAINTE de orice `STRTOFILE`/`CREATE CURSOR`/`COMPILE`**
(plus `SET TALK OFF`). Sub `-A` SAFETY porneste ON: primul `STRTOFILE` peste un log existent, sau
`COMPILE` peste un `.err`/`.fxp` existent, scoate dialogul modal "overwrite?" care blocheaza
procesul pana la timeout (proces viu, pare agatat). Alternativa/completare: `SAFETY=OFF`+
`RESOURCE=OFF` intr-un config.fpw propriu pasat cu `-c`. Verificare: logheaza
`SET("SAFETY")`/`SET("RESOURCE")` la start. Suitele existente il au deja - capcana apare la
scripturile ad-hoc, scrise repede pentru o masuratoare.
- **`DEFINE CLASS ... ENDDEFINE` nu poate sta la mijlocul programului principal.** Toate liniile
de DUPA `ENDDEFINE` dau "Statement is not in a procedure" (vezi `<script>.ERR`); scriptul se

View File

@@ -1,7 +1,8 @@
# Flux editare .vcx/.scx pe text (comun proiectelor VFP)
Textul .vc2/.sc2 e sursa de editare; write-back in binar cu `txt2vcx.ps1`, fara VFP IDE.
Detalii complete: `D:\ROA\UTIL\foxbin2prg\CLAUDE.md`. Parametrii per proiect: sectiunea de mai jos.
Detalii complete: `D:\ROA\UTIL\foxbin2prg\CLAUDE.md`. Parametrii per proiect (nemigrate):
`cautare_vcx_vct.md`.
**Proiecte migrate (ROACONT, COMUN, …): flux in-arbore.** Textul .??2 sta langa binare, il
improspateaza `git_sync.ps1 -ProjectRoot <root>` (nu cache extern) — la inceput de sesiune si
@@ -20,18 +21,57 @@ fals `roundtrip text1 != text2`. Ruleaza atunci cu lista rebazata:
'utile\foxcharts\foxcharts.vcx','utile\web\_webview.vcx')` - si apeleaza scriptul cu `&`, nu cu
`powershell -File` (acolo lista nu se leaga ca array).
## Parametri per proiect (nemigrate, cache extern)
## Invariante — se verifica la FIECARE editare, inainte de write-back
- **ROAGEST**: `-Project 'D:\ROA\ROAGEST\roagest.pjx' -ProjectRoot 'D:\ROA\ROAGEST'
-CacheRoot 'D:\ROA\_vfp_textcache\roagest'`; patch-uri de review in
`docs/diff_runda<N>_<subiect>.patch`.
1. **Membru nou de clasa (proprietate SAU metoda) are intrare in `*<DefinedPropArrayMethod>`**:
`*p: nume` / `*m: nume`. Sectiunea "Membri noi de clasa" mai jos.
2. **Ordinea alfabetica FoxBin2Prg**: `_` vine DUPA litere, nu inainte (ASCII). Ordinea canonica se
citeste din `<staging>\verify\*.vc2`, nu se deduce.
3. **CRLF, zero LF izolati**:
`perl -e 'local $/; open F,"<:raw",$ARGV[0]; $d=<F>; $crlf=()=$d=~/\r\n/g; $lf=()=$d=~/\n/g; print $lf-$crlf' <fisier>`
trebuie sa dea 0.
4. **Cens de octeti >= 0x80 identic** cu cel de dinainte de editare:
`od -An -tx1 <fisier> | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c`
(detalii: `conventie_encoding_cp1252.md`).
**Nici fidelity-check-ul, nici `-DryRun` nu acopera punctele 1, 3 si 4** — trec cu OK peste toate
trei. Sunt verificari separate, de facut de mana.
## Membri noi de clasa: `*p:` / `*m:`
Orice proprietate sau metoda NOUA cere, pe langa valoarea din `*<PropValue>` / corpul `PROCEDURE`,
o intrare in blocul `*<DefinedPropArrayMethod>` al clasei: `*p: nume` pentru proprietate, `*m: nume`
pentru metoda. Override-urile de metode mostenite (Init, Show, hook-uri) NU au nevoie de `*m:`.
Fara acea intrare, esecul e tacut in patru pasi:
1. textul se scrie si `txt2vcx.ps1` **trece fidelity-check-ul** — fidelity compara text-sursa cu
text-regenerat, deci nu are cum sa observe lipsa; binarul primeste valoarea/corpul ca text;
2. VFP nu materializeaza membrul pe obiect: `PEMSTATUS(o,'nume',5)` da `.F.`, iar accesul cade cu
eroarea 1734 "Property ... is not found" (proprietate) sau "Data type mismatch" la
`Createobject` (metoda). Dovedit in ambele sensuri pe o clasa de proba izolata;
3. **prima salvare din IDE-ul VFP peste acel binar sterge tacit membrul** — la metode raman doar
corpurile `PROCEDURE` orfane, la proprietati dispare si valoarea;
4. urmatorul `git_sync` regenereaza textul din binarul deja ciuntit, deci pierderea intra si in
`.??2`, si in backup-urile de runda.
Pasul 3 loveste si definitii `*m:` **deja existente si corecte** (patit pe ROAGEST:
`import_adauga_factura.recalc_tva`, `import_nota.do_adauga/do_copie/do_reface`; simptom: crash la
`Createobject` cu "Data type mismatch" raportat la linia apelanta). Deci dupa ORICE sesiune IDE pe
o clasa atinsa: `git_sync` + compara lista `*p:`/`*m:` cu starea de dinainte.
Verificare inainte de write-back: `grep -n '\*[pm]: <nume>' <fisier>.vc2`.
Pozitia in fisier nu e libera — FoxBin2Prg regenereaza membrul la pozitia lui alfabetica din
`*<DefinedPropArrayMethod>` (cu `_` dupa litere); o intrare sau o metoda scrisa in alta parte pica
fidelity-check-ul. Sursa de adevar pentru ordine si pozitie: textul din `<staging>\verify\*.vc2`.
## Pasii unei runde
0. Refresh cache (obligatoriu dupa orice sesiune IDE — staleness pe mtime):
`vcx2txt.ps1 -Project <pjx> -ProjectRoot <root> -CacheRoot <cache> -Types vcx,scx`
1. Baseline: `Copy-Item <f>.vc2 <f>.vc2.pre_runda<N>.bak` (in cache; la runde succesive
necomise, diff-ul fata de HEAD ar amesteca rundele).
0. Refresh text (obligatoriu la inceput de sesiune si dupa orice sesiune IDE — staleness pe
mtime): `git_sync.ps1 -ProjectRoot <root>` (proiecte nemigrate: `vcx2txt.ps1 -Project <pjx>
-ProjectRoot <root> -CacheRoot <cache> -Types vcx,scx`).
1. Baseline: `Copy-Item <f>.vc2 <f>.vc2.pre_runda<N>.bak` (langa binar, in arbore; la runde
succesive necomise, diff-ul fata de HEAD ar amesteca rundele).
2. Editare byte-safe: PowerShell `[IO.File]::ReadAllText/WriteAllText(..., GetEncoding(1252))` -
doar pentru round-trip pe octeti, NU pentru retastat literal diacritice (antetul zice
`CPID="1252"`, dar octetii diacriticelor sunt de fapt cp1250: `conventie_encoding_cp1252.md`).
@@ -56,7 +96,8 @@ fals `roundtrip text1 != text2`. Ruleaza atunci cu lista rebazata:
(`Test-ExclusiveAccess` pe `.vcx`+`.vct`) si refuza cu mesaj clar daca e lock. NU conteaza
existenta altor instante `vfp9` — utilizatorul poate lucra in paralel in alt proiect VFP —
si NU se omoara procese: cand lock-ul exista, se cere utilizatorului sa inchida sesiunea.
5. Write-back: `txt2vcx.ps1 -TextFile <vc2> -ProjectRoot <root> -CacheRoot <cache>`
5. Write-back: `txt2vcx.ps1 -TextFile <vc2> -ProjectRoot <root>` (`-CacheRoot` implicit =
`-ProjectRoot`; pentru proiecte nemigrate cu cache separat, paseaza-l explicit)
(+ `-AllowComun` pentru tinte COMUN — afecteaza toate aplicatiile ROA, deci schimbarea in sine
se propune explicit, dar write-back-ul local nu asteapta aprobarea; nimic nu pleaca la celelalte
aplicatii pana la commit+push).
@@ -75,29 +116,6 @@ fals `roundtrip text1 != text2`. Ruleaza atunci cu lista rebazata:
- `.mnx`/`.frx` raman read-only (GENMENU in IDE / round-trip fragil).
- Linii complet goale in metode pica fidelity doar pe whitespace; fix: preia `verify\*.vc2`
din staging peste cache si reia write-back-ul.
- Metoda noua de clasa cere `*m: nume` in `*<DefinedPropArrayMethod>`; fara ea, prima salvare
din IDE o arunca tacut, iar refresh-ul urmator absoarbe pierderea in cache (si in .bak-uri).
Override-urile de metode de baza (Init, Show, hook-uri) nu au nevoie de `*m:`.
- **Proprietate noua de clasa cere identic `*p: nume` in `*<DefinedPropArrayMethod>`** — nu doar
valoarea in `*<PropValue>`. Fara `*p:`, valoarea se scrie in text, **trece fidelity-check-ul**
(fidelity compara doar text-sursa cu text-regenerat) si ajunge in binar ca text, dar VFP nu o
materializeaza pe obiect: `PEMSTATUS(o,'nume',5)` da `.F.` si orice acces cade cu eroarea 1734
"Property ... is not found". Dovedit in ambele sensuri pe o clasa de proba izolata (cu `*p:` ->
`.T.`, fara -> `.F.`).
- **FoxBin2Prg sorteaza alfabetic cu `_` DUPA literele obisnuite**, nu in ordine ASCII brut (unde
`'_' (0x5F) < 'v' (0x76)` pe litere mici). O intrare `*p:`/`*m:` scrisa de mana in ordine "ASCII
corecta" pica fidelity-check-ul; ordinea canonica se citeste din textul regenerat in
`<staging>\verify\*.vc2` (vezi punctul de mai jos despre pozitia metodelor noi — se aplica identic
proprietatilor).
- FoxBin2Prg NU pastreaza pozitia in text a unei metode noi: o regenereaza la pozitia
alfabetica din `*<DefinedPropArrayMethod>`. O metoda scrisa in alta parte a fisierului
face fidelity-check-ul sa pice. Sursa de adevar pentru relocare e textul regenerat din
`<staging>\verify\` - muta metoda unde apare acolo si reia write-back-ul.
- Salvarea din VFP IDE peste un binar scris de txt2vcx poate PIERDE si definitii `*m:` deja
existente, desi corpurile PROCEDURE raman (patit pe ROAGEST: `import_adauga_factura.recalc_tva`,
`import_nota.do_adauga/do_copie/do_reface`); simptom: crash la Createobject cu
"Data type mismatch" raportat la linia apelanta. Dupa orice sesiune IDE pe clasa: refresh
cache + compara lista `*m:` cu starea de dinainte.
- Nu folosi *Project > Build* ca sa recompilezi un binar vizat: rebuild-ul recompileaza toate
`.vcx`/`.vct` din proiect si le rescrie antetul (timestamp compilare) si posibil p-code-ul
intern si la librarii neatinse efectiv, aparand fals ca "modificate" in diff — de aici

View File

@@ -163,3 +163,21 @@ noua are pretul de achizitie 0, respectiv daca toate liniile facturii au fost st
sus.
- Documentele care nu sunt facturi de vanzare nu sunt atinse de aceasta ramura - pagina de articole
nu apare si scrierea in `VANZARI_DETALII` nu se declanseaza (garda: `Reccount('tvanz') = 1`).
## Ce e strict necesar de stiut despre PACK_CONTAFIN
Pachetul central de **scriere a documentelor** - clientul VFP populeaza tabelele temporare
`ACT_TEMP`/`RUL_TEMP` (prin `oscrie_in_fisiere`-ul din COMUN), apoi pachetul distribuie:
- `SCRIE_IN_FISIERE` - orchestratorul (apelat per document).
- `SCRIE_IN_ACT` - `ACT_TEMP` -> `ACT` (notele contabile).
- `SCRIE_IN_RUL` - `RUL_TEMP` -> `RUL` (miscarile de stoc); completeaza `COD`, `DATAORA`, `ID_FACT`
(min. `id_fact` fara conturi 5xx), `ID_SUCURSALA`, `DATAIN`/`DATAOUT` din `dataact`, optional
`ID_RUL_AUX` pe furnizor (optiunea de firma `RULAJFURNIZOR`). **Scrie exact ce e in RUL_TEMP - nu
deriva rulaje din ACT**, deci filtrarea liniilor de rulaj se face in clientul VFP.
- `SCRIE_IN_RUL_OBINV` / `SCRIE_IN_STOC` / `SCRIE_IN_STOC_OBINV` - variantele pentru obiecte de
inventar si actualizarea stocului.
- `VERIFICA_NOTE_CONTABILE`, `SCRIE_JC_2007`/`SCRIE_JV_2007` (jurnale TVA),
`SCRIE_IN_BALANTA(_PARTENERI)`, `sterge_document`, `finalizeaza_document_*`.
- Stare de sesiune prin settere/gettere (`SET_COD`/`GET_COD`, `SET_IDFACT`, `SET_ID_SUCURSALA`, ...)
+ `PACK_SESIUNE` (an/luna, optiuni firma).

View File

@@ -1,8 +1,15 @@
# Inventar COMUN - functii/clase reutilizabile (ROAGEST)
Scop: reutilizare comune la plan/code-review (ex. cursor2lista() in loc de Scan manual pe cursor).
Consulta acest fisier la plan (inainte de cod/obiecte noi) si la code-review (Scan manual pt.
liste, MESSAGEBOX direct, SQLEXEC direct, buton cu Click suprascris in loc de `caction`, export/
listare construite manual in loc de `goExport.export2*`/FoxyPreview, dialog de alegere nomenclator
din SELECT+grid in loc de `caut_*`).
Generat prin grep pe COMUN/programe/*.prg + cache text D:\ROA\_vfp_textcache\roagest. Numerele =
nr. aparitii grep in proiect (indiciu cat de "canonic" e functia).
nr. aparitii grep **in ROAGEST** (indiciu cat de "canonic" e functia) - dar `COMUN\` e partajat de
8 produse ROA si lista de functii/clase de mai jos e valabila pentru toate; doar cifrele de uz sunt
masurate pe ROAGEST.
## 1. Functii comune - COMUN\programe\oproceduri_comune.prg (clasa Oracle/executor + utilitare)
@@ -285,30 +292,7 @@ Proprietate cheie comuna: `pcobj` (leaga containerul de camp/proprietate din obi
- Fisiere `.vc2`/`.sc2`: TAB-uri semnificative, proprietatile in blocul `*<PropValue>` sunt
alfabetizate - orice editare manuala trebuie sa respecte formatul (vezi CLAUDE.md, flux editare text).
## 7. Ce am lasat pe dinafara (intentionat)
- `proceduri_comune.prg` (varianta veche) - acoperita in nota sect. 1 (2 functii unice folosite,
restul dublate/moarte); functiile ei unice cu 0 aparitii (caut_nume_politica,
make_sectii_utilizator, recompune_optiuni, cere*/compara*, debug_*_eventtracking, ...) - omise.
- `oproceduri_comune_imob.prg` - varianta specifica ROAIMOB, nu ROAGEST.
- `xdate.prg` - script procedural (incarca cursoarele xsets/xrequest/xnote la DO), nu expune functii.
- Metoda `getUserRepPath` din oExportConfig - complet comentata (moarta); varianta activa e functia
libera omonima din `proceduri_rapoarte.prg` (cod diferit).
- Clase de nomenclatoare mari (`onomenclatoare.vcx`, `onom_articole.vcx`, `stocuri.vcx`, `rulaje.vcx`,
`ointroduceri*.vcx`, `oinventar.vcx`) - business logic gestiune, prea voluminos pt. acest inventar
(candidat pt. inventar separat per-flux, daca devine necesar).
- Clasele de configurare/serii (`configurare.vcx`, `serii_numere.vcx`, `ferestre_oracle.vcx`,
`bon_fisc.vcx`) si utilitarele (`GridExtras`, `ctl32`, `hpdf`) - neinventariate, uz rar in
fluxurile curente (`excelxml.vcx` e acoperita la sect. 3).
- Functiile din `COMUN\programe` fara nicio aparitie prin grep in ROAGEST (posibil doar alte
aplicatii ROA) - omise.
## 8. Cum se foloseste
- **La plan**: inainte de cod/obiecte noi, scaneaza acest fisier + un grep tintit
(`grep -rn "<nume_functie_candidata>" COMUN/programe D:\ROA\_vfp_textcache\roagest`) ca sa
confirmi ca nu exista deja o comuna echivalenta.
- **La code-review**: daca un diff introduce Scan manual pt. liste, MESSAGEBOX direct, SQLEXEC
direct, un buton cu Click suprascris in loc de `caction`, export Excel/listare construite manual
in loc de `goExport.export2*`/FoxyPreview, sau un dialog de alegere nomenclator din SELECT+grid
in loc de `caut_*` (ocautare.prg), semnaleaza comuna corespunzatoare din tabelele de mai sus.
La un grep tintit fara rezultat aici (`grep -rn "<nume_functie_candidata>" COMUN/programe
D:\ROA\_vfp_textcache\roagest`), functia poate exista tot in `COMUN\` dar sub alt nume istoric
(vezi duplicatele din nota sect. 1) sau in clasele mari de business (nomenclatoare, stocuri,
rulaje, introduceri, inventar) - neinventariate aici, prea voluminoase.

View File

@@ -77,8 +77,9 @@ ALTE OPȚIUNI: -Force (reconvertește tot), -Clean (șterge cache-ul întâi).
PAS 3 — modificare de cod în .vcx/.scx (flux write-back pe text). Ordinea e obligatorie:
a. Investighează pe cache, propune modificarea și AȘTEAPTĂ ACORDUL pe abordare înainte să
editezi ceva.
a. Investighează pe cache. Ordinea write-back/aprobare/commit urmează `reguli_lucru.md`
(write-back-ul și testele se fac imediat, fără să aștepți răspunsul; aprobarea
condiționează COMMIT-ul, nu write-back-ul).
b. Refresh cache (PAS 1) dacă a rulat vreo sesiune de IDE de la ultimul refresh (staleness-ul
se verifică pe mtime și txt2vcx refuză corect scrierea peste modificări nevăzute). Înainte
de write-back închide COMPLET VFP IDE și exe-ul aplicației — procesele reziduale țin lock

View File

@@ -1,43 +1,34 @@
# Export surse Oracle (PACK_CONTAFIN & co.) — cum se face
# Export surse Oracle (PACK_CONTAFIN & co.) - cum se face
`PACK_CONTAFIN.pck` din acest folder este exportul sursei pachetului PL/SQL `PACK_CONTAFIN`.
Claude Code își face singur exportul/reîmprospătarea — nu mai e nevoie de export manual din
Claude Code isi face singur exportul/reimprospatarea - nu mai e nevoie de export manual din
PL/SQL Developer.
## Conexiune
- Client: `D:\ROA\instantclient_19_18\sqlplus.exe` (`TNS_ADMIN` deja setat spre același folder).
- Alias TNS: `ROA_CENTRAL` → `10.0.20.121:1521`, `SERVICE_NAME=ROA` (vezi `tnsnames.ora`).
- Schema/utilizator: `MARIUSM_AUTO` (schema de dezvoltare a lui Marius).
- **Schema de lucru pentru verificari: `MARIUSM_AUTO` pe `ROA_CENTRAL`** - nu `ACN` sau altele.
- **Parola nu e versionată în git** — în `COMUN\docs\local\oracle.md` (ignorat de git, există în SVN).
Conectare, alias TNS, schema (`MARIUSM_AUTO` pe `ROA_CENTRAL`) si capcana BOM la SQL prin pipe:
vezi `conventie_mediu_oracle.md` sectiunea 4. Aici doar ce e specific exportului:
`PACK_CONTAFIN` există în schemele `MARIUSM_AUTO` (dev) și `ACN`, plus sinonim `PUBLIC`.
Exportul de referință se face din `MARIUSM_AUTO`.
`PACK_CONTAFIN` exista in schemele `MARIUSM_AUTO` (dev) si `ACN`, plus sinonim `PUBLIC`. Exportul
de referinta se face din `MARIUSM_AUTO`.
Înainte de a lua o sursă de acolo ca referință pentru o modificare, verifică că `MARIUSM_AUTO` are
toate scripturile aplicate — procedura e în `scripturi-migrare-db.md`, secțiunea
"Sursa de referință pentru DDL".
## Gotcha sqlplus pe Windows/PowerShell
Nu trimite SQL prin pipe din PowerShell (`'select...' | sqlplus`) — BOM-ul UTF-16 sparge parserul
(`SP2-0734: unknown command beginning "select..."`). Scrie un fișier `.sql` cu encoding **ASCII**
și rulează-l cu `@fisier.sql`.
Inainte de a lua o sursa de acolo ca referinta pentru o modificare, verifica ca `MARIUSM_AUTO` are
toate scripturile aplicate - procedura si regula "sursa de referinta pentru DDL e MARIUSM_AUTO, nu
productia" sunt in `scripturi-migrare-db.md`, sectiunea "Sursa de referinta pentru DDL".
## Comanda de export (re-generare .pck)
> **`linesize` prea mic corupe tăcut sursa.** SQL\*Plus face **wrap** la coloana `linesize`, deci o
> linie de cod mai lungă e ruptă în două — inclusiv **prin mijlocul unui identificator**. Fișierul
> pare întreg, `diff` față de el nu arată nimic, dar recompilarea lui dă erori la linii care n-au
> nicio legătură cu ce ai modificat (`ORA-00920`, `PLS-*`). `PACK_FACTURARE` are linii de peste
> **1000** de caractere, iar un export la `linesize 400` i-a rupt 8. Folosește `linesize 32767` și
> verifică după export că nicio linie nu atinge exact valoarea `linesize`.
> **`linesize` prea mic corupe tacut sursa.** SQL*Plus face **wrap** la coloana `linesize`, deci o
> linie de cod mai lunga e rupta in doua - inclusiv **prin mijlocul unui identificator**. Fisierul
> pare intreg, `diff` fata de el nu arata nimic, dar recompilarea lui da erori la linii care n-au
> nicio legatura cu ce ai modificat (`ORA-00920`, `PLS-*`). `PACK_FACTURARE` are linii de peste
> **1000** de caractere, iar un export la `linesize 400` i-a rupt 8. Foloseste `linesize 32767` si
> verifica dupa export ca nicio linie nu atinge exact valoarea `linesize`.
>
> **Exportul e bun pentru CITIT, nu ca bază pentru un script de migrare.** Pentru un script de
> pachet, pleacă de la ultimul script aplicat din `SCRIPTURI_CLAR` (fișier real, care n-a trecut
> niciodată printr-un spool) și confirmă că e la zi comparându-l cu exportul **ignorând spațiul
> alb** — așa wrap-ul nu mai contează:
> **Exportul e bun pentru CITIT, nu ca baza pentru un script de migrare.** Pentru un script de
> pachet, pleaca de la ultimul script aplicat din `SCRIPTURI_CLAR` (fisier real, care n-a trecut
> niciodata printr-un spool) si confirma ca e la zi comparandu-l cu exportul **ignorand spatiul
> alb** - asa wrap-ul nu mai conteaza:
> `tr -d ' \t\r\n' < fisier | md5sum` pe ambele.
```sql
@@ -56,23 +47,5 @@ exit
& 'D:\ROA\instantclient_19_18\sqlplus.exe' -L -S 'MARIUSM_AUTO/<parola>@ROA_CENTRAL' '@export_pack.sql'
```
Același tipar merge pentru orice alt pachet/procedură (`PACK_SESIUNE`, `PACK_PRETURI`, …) sau
Acelasi tipar merge pentru orice alt pachet/procedura (`PACK_SESIUNE`, `PACK_PRETURI`, ...) sau
pentru DDL de tabele/view-uri (`all_tab_columns`, `dbms_metadata.get_ddl`).
## Ce e strict necesar de știut despre PACK_CONTAFIN
Pachetul central de **scriere a documentelor** — clientul VFP populează tabelele temporare
`ACT_TEMP`/`RUL_TEMP` (prin `oscrie_in_fisiere`-ul din COMUN), apoi pachetul distribuie:
- `SCRIE_IN_FISIERE` — orchestratorul (apelat per document).
- `SCRIE_IN_ACT` — `ACT_TEMP` → `ACT` (notele contabile).
- `SCRIE_IN_RUL` — `RUL_TEMP` → `RUL` (mișcările de stoc); completează `COD`, `DATAORA`, `ID_FACT`
(min. `id_fact` fără conturi 5xx), `ID_SUCURSALA`, `DATAIN`/`DATAOUT` din `dataact`, opțional
`ID_RUL_AUX` pe furnizor (opțiunea de firmă `RULAJFURNIZOR`). **Scrie exact ce e în RUL_TEMP — nu
derivă rulaje din ACT**, deci filtrarea liniilor de rulaj se face în clientul VFP.
- `SCRIE_IN_RUL_OBINV` / `SCRIE_IN_STOC` / `SCRIE_IN_STOC_OBINV` — variantele pentru obiecte de
inventar și actualizarea stocului.
- `VERIFICA_NOTE_CONTABILE`, `SCRIE_JC_2007`/`SCRIE_JV_2007` (jurnale TVA),
`SCRIE_IN_BALANTA(_PARTENERI)`, `sterge_document`, `finalizeaza_document_*`.
- Stare de sesiune prin settere/gettere (`SET_COD`/`GET_COD`, `SET_IDFACT`, `SET_ID_SUCURSALA`, …)
+ `PACK_SESIUNE` (an/lună, opțiuni firmă).

View File

@@ -4,44 +4,8 @@ Regula (valabila in toate proiectele ROA/VFP): un singur subagent care duce o mi
(iteratii de teste, investigatii, mai multe sarcini inlantuite) acumuleaza context urias —
calitate degradata, cost mare. Nu se lucreaza asa.
## REGULA ZERO: predarea contextului e OBLIGATORIE, nu optionala
Se aplica **identic sesiunii principale si oricarui subagent**. Nu e o recomandare de eficienta,
e o conditie de corectitudine: un context supraincarcat pierde tacut decizii deja luate si reia
investigatii deja platite.
**Declansatoare — la oricare dintre ele, predarea porneste imediat:**
1. contextul propriu a trecut de **~50% din fereastra** (orchestrator) sau de **~200-250k tokens**
(subagent);
2. harness-ul anunta compactare automata (`PreCompact`) — **prea tarziu ca sa mai amani, dar nu
prea tarziu ca sa scrii fisierul**; scrie handoff-ul inainte sa raspunzi orice altceva;
3. utilizatorul semnaleaza ca s-a atins limita;
4. s-a terminat un bloc de lucru — indiferent cat context a mai ramas.
**Procedura, in ordine, fara exceptii:**
1. **Opreste lucrul.** Nu incepe o sarcina noua, nu porni o rulare noua. Daca esti in mijlocul unei
editari, du-o pana la o stare **consistenta pe disc** (text si binare sincronizate) si atat.
2. **Scrie handoff-ul pe disc** (`docs\handoff_<subiect>.md`). Nu in mesaj, nu in raport — **pe
disc**. Un mesaj catre orchestrator se pierde; fisierul nu.
3. **Confirma in doua randuri** ce ai lasat in urma si daca ceva e intr-o stare periculoasa
(fisier editat fara write-back, tranzactie deschisa, proces ramas viu, date de test consumate).
4. **Opreste-te.** Blocul urmator il ia un agent proaspat. "Mai am putin" nu e motiv de amanare —
exact acolo se pierd lucrurile.
**Obligatia e a fiecaruia, nu doar a orchestratorului.** Un subagent care simte ca se apropie de
prag **anunta singur** si cere predarea; nu asteapta sa fie oprit. Un orchestrator care se apropie
de prag isi scrie propriul handoff si preda orchestrarea unei sesiuni noi — regula nu are portita
pentru "eu doar coordonez".
**Ce intra obligatoriu in handoff**: inventarul livrabilelor cu `fisier:linie`; ce e terminat si ce
nu; **daca write-back-ul e facut** pentru fiecare fisier atins; comanda exacta de rulare a testelor
si unde scriu logurile; ce s-a stabilit deja (ca sa nu se reia); ce e interzis; starea datelor de
test consumate; capcanele de mediu platite. Fara analize noi — doar stare.
Doua lectii platite scump, amandoua din aceeasi cauza — un agent tinut peste prag (`s5-nivel2`
533k, `s2d-modifica-gestiuni` 434k). Predarea e aproape gratuita: raportul e oricum deja scris.
Predarea contextului la prag (REGULA ZERO, declansatoare, procedura, ce intra in handoff) e
regula globala din `~/.claude/CLAUDE.md`, se aplica identic sesiunii principale si subagentilor.
## Cum se lucreaza
@@ -69,6 +33,27 @@ Doua lectii platite scump, amandoua din aceeasi cauza — un agent tinut peste p
Sonnet; ORCHESTRATORUL subagentilor (cel care imparte, monitorizeaza, deblocheaza,
decide) -> Opus (sau sesiunea principala). Commit doar dupa review-ul diff-ului de
catre om (vezi reguli_lucru.md).
- Un agent tinut peste prag costa scump: doua cazuri platite, aceeasi cauza (`s5-nivel2` 533k,
`s2d-modifica-gestiuni` 434k tokens) — predarea la timp e aproape gratuita, raportul e oricum
deja scris.
## Verificarea a ce se intoarce
Pentru executie delegarea merge, pentru concluzii nu:
- **citeste contractul functiei apelate, nu-l presupune.** Un raport care descrie corect
structura codului poate gresi sensul: ex. `goExecutor.oExecute` intoarce succes/insucces
(`CT_SUCCES`/`CT_INSUCCES`), NU numarul de randuri — o garda `If lnSucces > 0` citita ca
"are randuri" a produs un bug inexistent, raportat ca blocant. Deschide functia.
- **fix ingust, nu supra-constructie.** Cand premisa se corecteaza, corectia se restrange:
mecanismele noi introduse "ca sa fie sigur" diverg de la codul-sablon si blocheaza
refolosirea lui in alta parte.
- **"zero cazuri in date" nu dovedeste nimic** pe scheme cu date de test; raspunsul vine din
cod. Si invers: o potrivire de cifre pe 1-2 documente nu e o regula.
- **cere raportul sa separe "testat" de "analizat static"**, si ce n-a putut fi acoperit. Un
agent care nu e intrebat explicit va prezenta amandoua la fel.
- **spune-i ca poate infirma briefingul.** Altfel implementeaza corectia ceruta chiar cand a
descoperit ca nu e nevoie de ea.
## Semne ca ai gresit impartirea
@@ -97,8 +82,8 @@ diagnostic, fixuri aplicate direct in loc de delegate.
care intoarce da/nu, nu continutul din care ai deduce singur.
- **Nu aplica fixuri direct** decat sub ~5 linii si doar daca ai deja contextul in sesiune.
- **Prag si pe orchestrator**: la ~50% din fereastra, scrie handoff-ul si reia orchestrarea
dintr-o sesiune noua. Handoff-ul e deja pe disc - exact pentru asta exista. Vezi **Regula zero**
de la inceputul fisierului: obligatia e aceeasi ca pentru subagenti, fara portita pentru
dintr-o sesiune noua. Handoff-ul e deja pe disc - exact pentru asta exista. Vezi REGULA ZERO din
`~/.claude/CLAUDE.md`: obligatia e aceeasi ca pentru subagenti, fara portita pentru
"eu doar coordonez".
## Model de lucru: backlog de story-uri mici, context mic per story

View File

@@ -18,9 +18,7 @@
comentariu se scrie acolo unde explica o **ramura** sau un **filtru** care nu se citeste singur,
ca sa se inteleaga codul; unde codul e limpede, nu se comenteaza. O linie de regula, 2-3 doar
pentru metode cu contract nebanal (parametri, cursor asteptat/lasat deschis, pozitionare la
iesire), 4-5 in antetul unui script de migrare (ce e obiectul si ce contract are). Istoricul
modificarilor sta DOAR in ANTETUL fisierului (niciodata inline) — la fel in `.prg`, in `.sql`
si in PL/SQL Oracle.
iesire), 4-5 in antetul unui script de migrare (ce e obiectul si ce contract are).
INTERZIS in comentariu: nume de agent ("claude"), referinte la planuri, stories, propuneri,
decizii, etape sau erori (`docs/plan_*.md`, `docs/propuneri_*.md`, "#6", "S4", "M2", "T3",
"dec.6", "runda27", "E7", "D-H2"), trimiteri la rapoartele din `docs/` ("vezi raportul,
@@ -29,10 +27,11 @@
date si autori pe cod nou.
Comentarii vechi in stil jurnal nu se rescriu din oficiu — doar cand blocul e oricum atins
sau la cerere explicita.
Antet: o singura intrare CUMULATIVA per functionalitate (`*!* DD.MM.YYYY` / `*!* autor` /
`*!* ce face, 1-2 fraze`) — la revenire se rescrie intrarea, nu se adauga alta; autorul e cine
semneaza livrarea (ex. `marius.mutu`), niciodata agent. Doar comportamentul final — fara
revizii/runde/patch-uri/corectii. La rezolvari de erori: fara comentarii.
Istoricul modificarilor sta DOAR in antetul fisierului (niciodata inline, la fel in `.prg`,
`.sql` si PL/SQL Oracle): o singura intrare CUMULATIVA per functionalitate (`*!* DD.MM.YYYY` /
`*!* autor` / `*!* ce face, 1-2 fraze`) — la revenire se rescrie intrarea, nu se adauga alta;
autorul e cine semneaza livrarea (ex. `marius.mutu`), niciodata agent. Doar comportamentul
final — fara revizii/runde/patch-uri/corectii. La rezolvari de erori: fara comentarii.
Explicatiile merg in docs/ sau in mesajul de commit, nu in cod.
Changelog (`changelog_<aplicatie>.txt`): strictul necesar, pe limba utilizatorului, non-tehnic
— 1-3 fraze/intrare, fara detalii de implementare, fara enumerarea locurilor atinse. Cat timp
@@ -59,54 +58,25 @@
6. Delegare: implementarile, testele, verificarile si cercetarile se dau unor subagenti Sonnet in
background (lane-uri paralele); sesiunea principala doar orchestreaza si verifica, ca sa nu i
se umple contextul. Misiuni lungi: subagenti proaspeti per sarcina (max ~200-250k
tokens/subagent), nu unul singur cu context acumulat; handoff compact pe disc:
`orchestrare-subagenti.md`.
**Verificarea a ce se intoarce** — pentru executie delegarea merge, pentru concluzii nu:
- **citeste contractul functiei apelate, nu-l presupune.** Un raport care descrie corect
structura codului poate gresi sensul: ex. `goExecutor.oExecute` intoarce succes/insucces
(`CT_SUCCES`/`CT_INSUCCES`), NU numarul de randuri — o garda `If lnSucces > 0` citita ca
"are randuri" a produs un bug inexistent, raportat ca blocant. Deschide functia.
- **fix ingust, nu supra-constructie.** Cand premisa se corecteaza, corectia se restrange:
mecanismele noi introduse "ca sa fie sigur" diverg de la codul-sablon si blocheaza
refolosirea lui in alta parte.
- **"zero cazuri in date" nu dovedeste nimic** pe scheme cu date de test; raspunsul vine din
cod. Si invers: o potrivire de cifre pe 1-2 documente nu e o regula.
- **cere raportul sa separe "testat" de "analizat static"**, si ce n-a putut fi acoperit. Un
agent care nu e intrebat explicit va prezenta amandoua la fel.
- **spune-i ca poate infirma briefingul.** Altfel implementeaza corectia ceruta chiar cand a
descoperit ca nu e nevoie de ea.
tokens/subagent), nu unul singur cu context acumulat; handoff compact pe disc. Verificarea a
ce se intoarce si modelul de lucru (backlog de story-uri mici): `orchestrare-subagenti.md`.
7. Conventii obligatorii, de citit cand atingi zona respectiva:
- editezi fisiere `.vc2`/`.sc2`, dar si `.prg` (ex. `programe\ocautare.prg`, unde `s`-urile cu
virgula din `masina`/`si contul`/`transa` sunt octetul `0xBA`) -> `conventie_encoding_cp1252.md`.
Antetul FoxBin2Prg declara `CPID="1252"`, dar octetii diacriticelor sunt de fapt **cp1250**
(`0xE3`=a cu caciula, `0xFE`=t cu virgula, `0xAA`=S majuscul cu virgula, `0xBA`=s minuscul cu
virgula) - nu trata eticheta din antet ca adevarul despre encoding. Orice write cu un tool ce
nu pastreaza octetii nativ (Edit/Write) corupe caracterele >= 0x80 din TOT fisierul (`0xBA` ->
`EF BF BD`), chiar la o singura linie schimbata, si o repeta la FIECARE scriere - **nu
re-encoda niciodata fisierul: lucreaza pe octeti (`byte[]`) sau scrie strict ASCII in
continutul nou**; editeaza tot ce ai de editat, verifica byte-level si repara o singura data
DUPA ultima scriere.
Cens obligatoriu **inainte SI dupa** fiecare editare, care trebuie sa ramana identic:
`od -An -tx1 <fisier> | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c`. Atentie
la sens: la stricare censul **CRESTE**, nu scade - un octet cp1250 devine 3 octeti `EF BF BD`
(U+FFFD) la o re-encodare UTF-8 gresita; cauta explicit secventa `EF BF BD`, nu doar tiparul
generic de mojibake `C3`/`C4`/`C5`/`C8` + octet de continuare (acela da fals-pozitiv pe text
UTF-8 legitim sau pe comentarii intr-o alta limba, deja intalnite in cod). Verificare veche
(orice octet >=0x80, utila cand cauti pozitia exacta): `perl -ne 'print "$.\n" if
/[\x80-\xFF]/' <fisier>`; reparare (pt. `0xBA`): `perl -e
'binmode(STDIN);binmode(STDOUT);local $/;$_=<STDIN>;s/\xEF\xBF\xBD/\xBA/g;print' < f > f.tmp`.
`EF BF BD` nu spune ce caracter s-a pierdut - toate diacriticele devin la fel; ia octetul corect
per pozitie din `svn cat <fisier>` (necorupt) sau din git history (`git cat-file blob
<commit>:<cale>`, **din Bash, niciodata cu `>` din PowerShell 5.1** - adauga BOM si
re-encodeaza) inainte sa inlocuiesti - o inlocuire oarba cu `0xBA` strica `a`/`t` cu caciula
(`0xE3`, `0xFE`) din alte fisiere;
- editezi `.vc2`/`.sc2` sau `.prg` cu diacritice (ex. `programe\ocautare.prg`) -> fisierele
sunt **cp1250** desi antetul FoxBin2Prg declara `CPID="1252"`; Edit/Write corup TOT fisierul
(nu doar linia atinsa) la fiecare scriere - scrie continut nou strict ASCII. Cens obligatoriu
**inainte SI dupa** fiecare editare (la stricare CRESTE, nu scade):
`od -An -tx1 <fisier> | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c`. Tabel
de octeti si reparare -> `conventie_encoding_cp1252.md`;
- adaugi o PROPRIETATE sau o METODA noua intr-o clasa `.vc2`/`.sc2` -> `flux-editare-vfp-text.md`,
sectiunea "Membri noi de clasa": fara intrarea `*p:`/`*m:` in `*<DefinedPropArrayMethod>`
membrul trece fidelity-check-ul, dar VFP nu-l vede si prima salvare din IDE il sterge tacut;
- adaugi/rearanjezi controale pe formulare sau coloane in grid -> `conventie_ux_formulare.md`;
- grid needitabil pe formular cu 2+ grid-uri -> `capcana_grid_controlsource.md`;
- adaugi o coloana intr-un grid deja livrat (ordinea din clasa e neutralizata de
preferintele salvate per utilizator) -> `capcana_grid_preferinte_utilizator.md`;
- `GO` pe un `Recno()` capturat/primit ca parametru -> `conventie_go_recno.md`;
- `ALTER TABLE` pe cursorul intors de `goExecutor.oExecute()` -> `conventie_goexecutor_alter_table.md`;
- testare UI / prin MCP -> `testare-ui-vfp.md`, `testare-vfp-mcp.md`;
- testare UI -> `testare-ui-vfp.md`;
- te conectezi la Oracle pe dev/test, alegi schema sau rulezi un script de pachet ->
`conventie_mediu_oracle.md`;
- garzi pe valori NULL din Oracle -> `conventie_null_vfp.md`;

View File

@@ -2,8 +2,7 @@
Harness reutilizabil pentru teste care afiseaza un formular REAL (cu dependinte dummy, fara
Oracle), executa actiuni si valideaza vizual prin capturi. Valabil pentru toate proiectele VFP
din suita ROA. Alternativa la `testare-vfp-mcp.md` (care porneste programul principal intreg);
capcanele generale de rulare headless (`-A -T`, SAFETY, script agatat) sunt in
din suita ROA. Capcanele generale de rulare headless (`-A -T`, SAFETY, script agatat) sunt in
`depanare_testare_vfp.md`.
Fisiere in `COMUN\utile\Teste\`: `vfp_ui_harness.ps1` (orchestrator generic, parametrizat),
@@ -85,10 +84,9 @@ Doua non-dovezi, ca sa nu se piarda timp pe ele:
## Capcane / deblocari
a. **`SET SAFETY OFF` + `SET TALK OFF` inaintea primului `STRTOFILE`.** Cu SAFETY ON, scrierea
log-ului existent scoate un dialog modal care blocheaza rularea (proces viu, "instanta
moarta"). Cu TALK ON, `SUM`/`CALCULATE` isi echo-eaza rezultatele peste formular in
screenshots.
a. **`SET SAFETY OFF` + `SET TALK OFF` inaintea primului `STRTOFILE`** - capcana completa in
`depanare_testare_vfp.md` sectiunea 7. Specific UI: cu TALK ON, `SUM`/`CALCULATE` isi
echo-eaza rezultatele peste formular in screenshots.
b. **Lansarea orchestratorului**: prin tool cu timeout implicit (~120s) e omorat inainte de
final. Ruleaza-l in background + asteapta `done.txt`, sau timeout 300-600s. NU porni VFP
separat de orchestrator - si-l lanseaza singur.
@@ -209,6 +207,6 @@ s. **Dialoguri native care nu apar in log si nu sunt prinse de `ON ERROR`/mock-u
tintite pe handle (`BM_CLICK` pe buton Cancel/Anulare, altfel `WM_COMMAND IDCANCEL` ->
ESCAPE ca mesaj `WM_KEYDOWN`/`WM_KEYUP` -> `WM_CLOSE`); pe dialogurile proprii VFP owner-drawn
(butoane desenate, nu HWND-uri reale) dismiss-ul poate esua cinstit — captura PNG + dump text
raman oricum de incredere, indiferent de rezultatul dismiss-ului. Sterge intotdeauna `.fxp`-ul
vechi inainte de FIECARE rulare (watchdog-ul o face singur la lansare) — altfel VFP ruleaza
tacut codul compilat vechi si rulari "identice" dau rezultate diferite, fara nicio urma in log.
raman oricum de incredere, indiferent de rezultatul dismiss-ului. Watchdog-ul sterge singur
`.fxp`-ul vechi la lansare - capcana completa (de ce e obligatoriu) in `depanare_testare_vfp.md`
sectiunea 7.

View File

@@ -1,40 +0,0 @@
# Testare automata VFP prin IDE + MCP (windows-mcp)
Valabil pentru toate proiectele VFP din suita ROA; exemplele de mai jos sunt pe ROAGEST —
inlocuieste caile, numele programului principal si titlul ferestrei pentru alt proiect.
Pentru verificare vizuala dupa modificari pe `.vc2`/`.sc2`, nu se porneste `roagest.exe`
(ar cere rebuild complet — vezi `COMUN\docs\flux-editare-vfp-text.md`), ci se lanseaza `vfp9.exe`
interpretat peste `Programe\roagest.prg`:
```powershell
Start-Process -FilePath "C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe" `
-ArgumentList '-c"D:\ROA\ROAGEST\config.fpw"','D:\ROA\ROAGEST\Programe\roagest.prg' `
-WorkingDirectory "D:\ROA\ROAGEST"
```
- Gate-ul de pornire (`gcNumeProgram = 'ROAGEST'` in `roagest.prg`) verifica
`JUSTSTEM(SYS(16,0))` — numele programului de la nivelul 0 al stivei, nu numele procesului
`.exe`. Rulat interpretat, `SYS(16,0)` = `roagest.prg`, deci gate-ul trece.
- Fereastra rezultata are titlul `ROA - Gestiuni` (setat din `NUMEPROGRAM`).
## Capcana: focus furat de terminal
Daca sesiunea Claude Code afiseaza output in timp ce comanda de lansare ruleaza, fereastra
terminalului/IDE-ului ramane in prim-plan si VFP porneste in fundal — `Screenshot`/`Snapshot`
din `windows-mcp` pot raporta "No windows found" desi procesul si fereastra exista (verificabil
cu `Get-Process vfp9 | Select MainWindowTitle`).
Fix: inainte de screenshot, adu explicit fereastra in prim-plan dupa titlu:
```
mcp__windows-mcp__App mode=switch name="ROA - Gestiuni"
```
apoi `Screenshot`. Nu te baza pe enumerarea implicita de ferestre a `windows-mcp` cand ai lansat
procesul chiar in runda curenta de comenzi.
## Curatare dupa test
Proces de omorat la final: `mcp__windows-mcp__Process mode=kill pid=<pid>` (gasit prin
`mode=list name=vfp9` sau `Get-Process vfp9`).