Initial: flux text FoxBin2Prg (git urmareste .??2 in-arbore, binarele VFP git-ignored)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
127
docs/PROMPT_cautare_vfp.md
Normal file
127
docs/PROMPT_cautare_vfp.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# Prompt: căutare și editare în cod VFP (foxbin2prg) — reutilizabil în orice proiect Visual FoxPro
|
||||
|
||||
Acest fișier conține un **prompt gata de copiat** pentru Claude Code (sau alt agent), care
|
||||
configurează și folosește sistemul `foxbin2prg` ca să poată **căuta** cod-sursă aflat **în interiorul
|
||||
fișierelor binare VFP** (`.vcx/.vct`, `.scx/.sct`, `.frx/.frt`, `.mnx/.mnt`, `.dbc/.dct`) într-un
|
||||
proiect nou — și, pentru `.vcx`/`.scx`, să poată și **modifica** acel cod direct pe text, cu
|
||||
write-back în binar (`txt2vcx.ps1`), fără trecere prin IDE-ul VFP.
|
||||
|
||||
Unealta e partajată și stă la `D:\ROA\UTIL\foxbin2prg\` — nu trebuie copiată per proiect. Doar
|
||||
spui agentului care e proiectul curent (folderul + fișierul `.pjx`).
|
||||
|
||||
---
|
||||
|
||||
## Cum se folosește
|
||||
|
||||
1. Deschide proiectul VFP în Claude Code.
|
||||
2. Copiază blocul de mai jos în prompt.
|
||||
3. Înlocuiește cele **3 valori** marcate `<<...>>` cu datele proiectului tău:
|
||||
- `<<RADACINA_PROIECT>>` = folderul rădăcină al proiectului (ex. `D:\ROA\ROAGEST`)
|
||||
- `<<FISIER_PJX>>` = calea către `.pjx` (ex. `D:\ROA\ROAGEST\roagest.pjx`)
|
||||
- `<<NUME_PROIECT>>` = etichetă scurtă pentru folderul de cache (ex. `roagest`)
|
||||
|
||||
---
|
||||
|
||||
## ▼▼▼ PROMPT DE COPIAT ▼▼▼
|
||||
|
||||
```
|
||||
Acest proiect este o aplicație Visual FoxPro 9. O mare parte din cod (proceduri, metode,
|
||||
parametri) NU stă în fișiere .prg, ci în interiorul fișierelor binare VFP: librării de clase
|
||||
(.vcx+.vct), forme (.scx+.sct), rapoarte (.frx+.frt), meniuri (.mnx+.mnt). Un grep direct pe
|
||||
acestea nu e lizibil (sunt tabele DBF cu memo binar).
|
||||
|
||||
Ca să poți căuta în acel cod, folosește unealta partajată foxbin2prg, care convertește binarele
|
||||
în reprezentarea lor TEXT (.vc2/.sc2/.fr2/.mn2/.dc2) într-un cache, și apoi caută în cache.
|
||||
|
||||
PARAMETRII PROIECTULUI CURENT:
|
||||
- Rădăcină proiect: <<RADACINA_PROIECT>>
|
||||
- Fișier proiect (.pjx): <<FISIER_PJX>>
|
||||
- Cache text: D:\ROA\_vfp_textcache\<<NUME_PROIECT>>
|
||||
|
||||
REGULA DE AUR: cache-ul text e sursa pentru CĂUTARE (toate tipurile de binar) și, DOAR pentru
|
||||
.vcx/.scx, și pentru EDITARE cu write-back (txt2vcx.ps1, vezi PAS 3). Pentru .frx/.mnx/.dbc
|
||||
textul rămâne doar pentru citire — modificările la ele se fac în IDE-ul VFP, pe binar.
|
||||
|
||||
PAS 1 — populează cache-ul text (la începutul sesiunii, sau după ce s-a modificat ceva în IDE).
|
||||
Rulează în PowerShell (e incremental — sare peste ce e deja la zi):
|
||||
|
||||
& 'D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1' -Project '<<FISIER_PJX>>' -ProjectRoot '<<RADACINA_PROIECT>>' -CacheRoot 'D:\ROA\_vfp_textcache\<<NUME_PROIECT>>'
|
||||
|
||||
(Folosește un -CacheRoot distinct per proiect ca să nu amesteci cache-urile. Implicit scriptul
|
||||
convertește doar .vcx și .scx; pentru a include și rapoarte/meniuri adaugă: -Types vcx,scx,frx,mnx)
|
||||
|
||||
Dacă scriptul se plânge că lipsește FoxBin2Prg.EXE, trebuie compilat o singură dată: deschide
|
||||
'D:\ROA\UTIL\foxbin2prg\foxbin2prg.pj2' în VFP 9 și Build > Build Executable. Anunță-mă să fac asta.
|
||||
|
||||
PAS 2 — caută în cache cu unealta Grep (NU în binarele originale):
|
||||
|
||||
Grep pe folderul 'D:\ROA\_vfp_textcache\<<NUME_PROIECT>>' pentru numele de metodă/procedură/variabilă căutat.
|
||||
Ex.: caută "PROCEDURE do_salvare" sau numele tabelei/cursorului implicat.
|
||||
|
||||
CONVERSIE PUNCTUALĂ (un fișier sau folder care NU e în proiect, ex. o librărie din COMUN):
|
||||
|
||||
& 'D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1' -Source 'CALE\catre\librarie.vcx' -CacheRoot 'D:\ROA\_vfp_textcache\<<NUME_PROIECT>>'
|
||||
|
||||
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.
|
||||
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
|
||||
pe binare.
|
||||
c. Editează .vc2/.sc2 BYTE-SAFE: formatul e position-sensitive (nu reformata/reflow linii),
|
||||
proprietățile sunt alfabetizate (una nouă se inserează la locul ei alfabetic). Headerul
|
||||
CPID="1252" poate minți despre codepage-ul real al diacriticelor — citește/scrie fișierul
|
||||
ca bytes (PowerShell), conținutul NOU doar ASCII; nu folosi unelte care re-encodează.
|
||||
d. Write-back:
|
||||
|
||||
& 'D:\ROA\UTIL\foxbin2prg\txt2vcx.ps1' -TextFile 'D:\ROA\_vfp_textcache\<<NUME_PROIECT>>\Clase\lib.vc2' -ProjectRoot '<<RADACINA_PROIECT>>' -CacheRoot 'D:\ROA\_vfp_textcache\<<NUME_PROIECT>>'
|
||||
|
||||
Regenerează + compilează binarul în staging, verifică fidelitatea (roundtrip byte-identic
|
||||
față de textul editat) și abia apoi copiază binarul în proiect; la orice eșec proiectul
|
||||
rămâne neatins. Ținte sub COMUN\ cer flag-ul -AllowComun ȘI aprobare explicită — o
|
||||
modificare acolo afectează toate aplicațiile ROA.
|
||||
e. Diff lizibil pentru review: extrage binarul vechi din git (git show HEAD:cale > temp, atât
|
||||
.vcx cât și .vct), regenerează-i textul cu vcx2txt.ps1 -Source într-un folder temporar și
|
||||
compară cu cache-ul editat: git diff --no-index. COMMIT DOAR după ce omul confirmă pe diff
|
||||
și testează în IDE.
|
||||
|
||||
EXCEPȚII: pentru .mnx (GENMENU) și .frx (fragile la round-trip) nu există write-back — scrie
|
||||
propunerea de modificare într-un fișier docs/propuneri_<subiect>.md (cod + unde se inserează),
|
||||
iar aplicarea se face manual în IDE-ul VFP.
|
||||
|
||||
FLUX TIPIC: la prima sesiune rulează PAS 1 o dată, apoi caută cu Grep în cache (PAS 2). La
|
||||
sesiunile următoare rescrie doar ce s-a schimbat. Când citești codul unei metode, dă referințe
|
||||
fișier:linie din cache.
|
||||
```
|
||||
|
||||
## ▲▲▲ SFÂRȘIT PROMPT ▲▲▲
|
||||
|
||||
---
|
||||
|
||||
## Note pentru adaptare
|
||||
|
||||
- `<<NUME_PROIECT>>` îl poți pune orice etichetă scurtă (ex. `roagest`), doar ca numele
|
||||
folderului de cache să fie unic per proiect.
|
||||
- Ține cache-ul în `D:\ROA\_vfp_textcache\`, adică **în afara** folderului `foxbin2prg`. Motiv:
|
||||
`ReCreate_FoxBin2Prg.prg` face `Prg2Bin` recursiv pe tot folderul tool-ului și ar reconverti
|
||||
`.??2`-urile din orice cache aflat sub el înapoi în binare parazitare.
|
||||
- Scriptul citește lista de fișiere direct din `.pjx`, deci convertește **doar** ce folosește
|
||||
efectiv proiectul (rapid), nu tot `COMUN\`.
|
||||
- Cache-ul (`D:\ROA\_vfp_textcache\<proiect>`) e regenerabil și e în afara arborelui de versionare
|
||||
al proiectului (și în afara clonei foxbin2prg) — poate fi șters oricând.
|
||||
- Conversia NU necesită IDE-ul VFP deschis (folosește `FoxBin2Prg.EXE` compilat).
|
||||
- Fără backup-uri `.bak` lângă binarele din proiect — git e mecanismul de restore; `txt2vcx.ps1`
|
||||
ține o copie de siguranță doar în folderul temp al rulării.
|
||||
- Editările de volum se pot delega la subagenți (Sonnet, în background) — sesiunea principală
|
||||
orchestrează, verifică diff/fidelity și intervine doar la deblocări și decizii.
|
||||
- Detalii complete despre write-back (guard-uri, encoding, dialoguri VFP modale la text corupt,
|
||||
testul de regresie `test_roundtrip.ps1`): `D:\ROA\UTIL\foxbin2prg\CLAUDE.md`.
|
||||
- Exemplu funcțional, rodat pe ROAGEST: `D:\ROA\ROAGEST\docs\flux-editare-vfp-text.md` și
|
||||
`D:\ROA\ROAGEST\docs\CLAUDE.md` (modul de lucru complet, cu review pe diff înainte de commit).
|
||||
- Ghid complet doar-căutare (varianta ROAACNPRO, cu exemple): `D:\ROA\ROAACNPRO\docs\cautare_vcx_vct.md`.
|
||||
- Tabel corespondență binar → text: `.vcx`→`.vc2`, `.scx`→`.sc2`, `.frx`→`.fr2`, `.mnx`→`.mn2`,
|
||||
`.dbc`→`.dc2`, `.lbx`→`.lb2`.
|
||||
139
docs/cautare_vcx_vct.md
Normal file
139
docs/cautare_vcx_vct.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# Căutare în codul din librăriile/formele VFP (`.vcx`/`.vct`, `.scx`/`.sct`, ...)
|
||||
|
||||
Partajat între proiectele ROA* (companion narativ la `PROMPT_cautare_vfp.md` din acest folder,
|
||||
care e varianta "prompt de copiat" — acest fișier e ghidul de referință complet, cu exemple).
|
||||
|
||||
Cum se caută cod-sursă (proceduri, metode, parametri) care **nu** stă în fișiere `.prg`, ci
|
||||
în interiorul fișierelor binare VFP: librării 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` este de fapt o **tabelă DBF**: codul metodelor stă în câmpuri memo în `.vct`. Un
|
||||
`grep` direct pe `.vct` *găsește* textul, dar îl vede ca fișier binar (octeți `\0` între linii),
|
||||
fără numere de linie utile și greu de citit. Soluția: convertim binarul în reprezentarea lui
|
||||
**TEXT** (`.vc2`, `.sc2`, …) — un PRG-style lizibil, cu metode sortate alfabetic — și căutăm
|
||||
în text cu `grep`/`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 pentru fluxul complet (ordine obligatorie, encoding,
|
||||
> fidelity check). Pentru `.frx`/`.mnx`/`.dbc` nu există write-back — modificările se fac tot
|
||||
> în **IDE-ul VFP**.
|
||||
|
||||
## Unelte disponibile (verificate)
|
||||
|
||||
| Unealtă | Cale | Rol | Recomandare |
|
||||
|---|---|---|---|
|
||||
| **FoxBin2Prg** | `D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE` | Binar VFP ⇄ text bidirecțional (`.vc2/.sc2/.fr2/.mn2/.dc2/.lb2`) | **De folosit.** Complet, fidel, include corpul metodelor, parametri, comentarii |
|
||||
| vcx2prg | `D:\ROA\UTIL\vcx2prg\x2prg.prg` | Doar `.vcx` → `.prg` *compilabil* | Alternativă; mai vechi, doar clase, necesită IDE VFP deschis pentru a rula forma |
|
||||
| prgtovcx | `D:\ROA\UTIL\prgtovcx\prgtovcx.PRG` | Invers: `.prg` → `.vcx` | **Nu** pentru căutare (e direcția opusă) |
|
||||
|
||||
FoxBin2Prg e prima alegere: rulează din linia de comandă fără IDE deschis (EXE compilat), acoperă
|
||||
toate tipurile de container, și produce text mult mai fidel decât vcx2prg.
|
||||
|
||||
> Dacă `FoxBin2Prg.EXE` lipsește, se compilează o singură dată: deschide
|
||||
> `D:\ROA\UTIL\foxbin2prg\foxbin2prg.pj2` în VFP 9 și *Build > Build Executable*. Lângă EXE trebuie
|
||||
> să existe `filename_caps.exe` și fișierele `props*.txt` (sunt deja în folder).
|
||||
|
||||
## Mod recomandat: scriptul `vcx2txt.ps1`
|
||||
|
||||
`D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1` automatizează tot: copiază binarul + memo-ul într-un
|
||||
**cache** care oglindește structura proiectului (ca să nu murdărească arborele SVN), rulează
|
||||
FoxBin2Prg, păstrează doar fișierul text. E **incremental** (sare peste ce e deja la zi).
|
||||
|
||||
Parametrizează scriptul cu proiectul curent și un cache separat per proiect (nu amesteca
|
||||
cache-urile mai multor proiecte ROA):
|
||||
|
||||
```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\UTIL\foxbin2prg\_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\UTIL\foxbin2prg\_textcache_<nume_proiect>' -Types vcx,scx,frx,mnx
|
||||
|
||||
# conversie punctuală a unui fișier sau 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\UTIL\foxbin2prg\_textcache_<nume_proiect>' -Clean
|
||||
```
|
||||
|
||||
Exemplu concret (ROAAUTO):
|
||||
|
||||
```powershell
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
||||
-Project D:\ROA\ROAAUTO\roaauto.pjx -ProjectRoot D:\ROA\ROAAUTO `
|
||||
-CacheRoot D:\ROA\UTIL\foxbin2prg\_textcache_roaauto
|
||||
```
|
||||
|
||||
Rezultatul ajunge în cache-ul indicat, cu aceeași structură de directoare ca proiectul (ex.:
|
||||
`_textcache_roaauto\Clase\odevize.vc2`, `_textcache_roaauto\comun\clase\_frm_base.vc2`). Apoi:
|
||||
|
||||
```bash
|
||||
# cu unealta Grep (preferat) sau grep:
|
||||
grep -rn "PROCEDURE do_calcul_tarife" "D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>"
|
||||
grep -rln "factura_salvare" "D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>" # ce clase ating subiectul
|
||||
```
|
||||
|
||||
Flux tipic pentru o problemă: rulează scriptul cu parametrii de mai sus o dată (populează
|
||||
cache-ul), apoi caută cu `Grep` în cache. La sesiuni următoare rescrie doar ce s-a schimbat
|
||||
(incremental). Dacă ai nevoie de o librărie din `COMUN\` care nu e în proiect, convertește-o
|
||||
punctual cu `-Source`.
|
||||
|
||||
## 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țiile parametrilor folosite: `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 o verificare rapidă „există metoda X undeva în librărie?", `grep` merge direct pe `.vct`
|
||||
(o 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 citit corpul/contextul, folosește conversia în text.
|
||||
|
||||
## Corespondență extensii binar → text
|
||||
|
||||
| Container | Binar (+memo) | Text |
|
||||
|---|---|---|
|
||||
| Librărie clase | `.vcx` + `.vct` | `.vc2` |
|
||||
| Formă | `.scx` + `.sct` | `.sc2` |
|
||||
| Raport | `.frx` + `.frt` | `.fr2` |
|
||||
| Etichetă | `.lbx` + `.lbt` | `.lb2` |
|
||||
| Meniu | `.mnx` + `.mnt` | `.mn2` |
|
||||
| Bază de date | `.dbc` + `.dct` | `.dc2` |
|
||||
|
||||
## Note
|
||||
|
||||
- Codul aplicației stă mai ales în `Clase\*.vcx`; o mare parte din `.vcx`-uri sunt în
|
||||
`COMUN\` (framework partajat între toate aplicațiile ROA — vezi `CLAUDE.md` per proiect).
|
||||
- Cache-ul text e regenerabil și e î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).
|
||||
82
docs/conventie_encoding_cp1252.md
Normal file
82
docs/conventie_encoding_cp1252.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Capcană: corupere diacritice la editarea `.sc2`/`.vc2` (encoding cp1252)
|
||||
|
||||
Partajat între proiectele ROA* (similar cu `PROMPT_cautare_vfp.md` din acest folder) — capcana
|
||||
ține de formatul `.sc2`/`.vc2` produs de FoxBin2Prg, nu de un proiect anume.
|
||||
|
||||
Descoperit de 2 ori în aceeași sesiune (2026-07-10, în ROAAUTO): odată în
|
||||
`COMUN/clase/cmd_butoane.vc2` (clasa `cmd_select_adv`), odată în `Clase/ofundal_dev.vc2`
|
||||
(meniul principal) — de fiecare dată un agent anterior a editat text-cache-ul cu un tool care
|
||||
nu scrie cp1252 nativ, și a corupt TOATE caracterele cu diacritice din fișier, nu doar linia
|
||||
pe care voia s-o schimbe.
|
||||
|
||||
## De ce se întâmplă
|
||||
|
||||
Fișierele `.sc2`/`.vc2` generate de FoxBin2Prg sunt **cp1252 (Windows-1252)**, nu UTF-8
|
||||
(vezi antetul fiecărui fișier: `CPID="1252"`). Dacă un editor/tool citește fișierul ca UTF-8
|
||||
(sau alt encoding), fiecare byte >= 0x80 (diacritic) devine invalid ca secvență UTF-8 și e
|
||||
înlocuit cu caracterul de replacement U+FFFD. Dacă apoi tool-ul **salvează rezultatul tot ca
|
||||
UTF-8**, acel U+FFFD e scris ca 3 octeți UTF-8 (`0xEF 0xBF 0xBD`) — care, citiți înapoi ca
|
||||
cp1252 (cum face FoxBin2Prg la write-back), apar ca `�`. Rezultatul: caracterul original e
|
||||
**ireversibil pierdut** (nu mai există în fișier sub nicio formă) — recuperabil DOAR din altă
|
||||
sursă (git history, backup).
|
||||
|
||||
Codebase-ul ROA folosește un hack vechi de "reciclare" a unor caractere cp1252 needependente
|
||||
de Ș/ă/ț (care nu au echivalent direct în cp1252) pentru diacritice românești:
|
||||
|
||||
| Literă românească | Caracter folosit (cp1252) | Byte |
|
||||
|---|---|---|
|
||||
| ă | ã (a-tilde) | `0xE3` |
|
||||
| Ă | Ã | `0xC3` |
|
||||
| ț | þ (thorn minuscul) | `0xFE` |
|
||||
| Ș (majusculă) | ª (ordinal masculin) | `0xAA` |
|
||||
| ș (minusculă) | º (ordinal feminin) | `0xBA` |
|
||||
| î, â | î, â (existente nativ în cp1252) | `0xEE`, `0xE2` |
|
||||
|
||||
Aceste caractere par "gunoi"/typo la prima vedere într-un editor UTF-8 (`ã`, `þ`, `ª`, `º`) —
|
||||
**sunt corecte, nu le "corecta" fără să verifici encoding-ul.**
|
||||
|
||||
## Cum se verifică dacă un fișier `.sc2`/`.vc2` e corupt
|
||||
|
||||
```powershell
|
||||
$bytes = [System.IO.File]::ReadAllBytes("<path>.vc2")
|
||||
$text = [System.Text.Encoding]::GetEncoding(1252).GetString($bytes)
|
||||
$text -split "`r`n" | Select-String ([char]0xFFFD) # cauta caracterul de replacement
|
||||
```
|
||||
|
||||
Dacă apare `�` (sau `$text` conține U+FFFD) în output — fișierul are corupere de encoding.
|
||||
|
||||
## Cum se repară
|
||||
|
||||
1. **Nu edita orbește peste corupere** — caracterul original e deja pierdut din fișierul
|
||||
curent.
|
||||
2. Dacă fișierul e sub control de versiune (git) și corupera s-a întâmplat **într-o sesiune
|
||||
anterioară necomisă** (deci HEAD-ul git încă are versiunea curată): recuperează originalul
|
||||
convertind binarul din HEAD în text și comparând:
|
||||
```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
|
||||
```
|
||||
apoi decodează ambele fișiere (HEAD curat + curent corupt) ca cp1252 și compară linie cu
|
||||
linie (PowerShell, nu `diff` direct — `diff`/Bash nu decodează cp1252 corect pentru afișare,
|
||||
deși detectează totuși diferența de octeți).
|
||||
3. Reconstruiește fișierul text pornind de la versiunea HEAD (curată), și reaplică DOAR
|
||||
modificările intenționate din sesiunea curentă peste ea (nu invers — nu încerca să "cârpești"
|
||||
fișierul corupt caracter cu caracter, e mai sigur să repornești de la baza curată).
|
||||
4. Scrie rezultatul înapoi ca bytes cp1252 (`[System.Text.Encoding]::GetEncoding(1252).GetBytes(...)`),
|
||||
NU ca string UTF-8/`Out-File` implicit (care scrie UTF-8 sau UTF-16 după caz).
|
||||
5. Rulează write-back (`txt2vcx.ps1 -Force`) și verifică fidelity check = zero diferențe.
|
||||
|
||||
## Cum se evită pe viitor
|
||||
|
||||
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ă a
|
||||
fișierului trebuie făcută la nivel de octeți cu encoding cp1252 explicit**, nu presupunând
|
||||
UTF-8 implicit. 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ă deja riscul ("Headerul
|
||||
CPID="1252" poate minți...") pe scurt; acest fișier e detalierea completă (tabel de caractere,
|
||||
pași de recuperare din git).
|
||||
65
docs/conventie_goexecutor_alter_table.md
Normal file
65
docs/conventie_goexecutor_alter_table.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Capcană: `ALTER TABLE` pe cursorul întors 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*.
|
||||
|
||||
## Ce nu funcționează
|
||||
|
||||
```foxpro
|
||||
lnSucces = goExecutor.oExecute(lcSql, lcCursor)
|
||||
...
|
||||
ALTER TABLE (lcCursor) ADD COLUMN coloananoua L && <- pică
|
||||
```
|
||||
|
||||
Cursorul întors de `oExecute()` (rezultatul unui `SQLExec`) poate refuza comenzi DDL
|
||||
ulterioare, cu erori în lanț (descoperite empiric, în această ordine, în ROAAUTO
|
||||
`autopass_cursor_comenzi`/`autopass_cursor_operatii`):
|
||||
|
||||
1. `Function is not supported on remote tables.` — pe `ALTER TABLE` direct pe cursorul
|
||||
original.
|
||||
2. Chiar și după o încercare de rematerializare (`SELECT * FROM (cursor) INTO CURSOR
|
||||
(acelasi_nume) READWRITE`) → `Alias name is already in use.` (sursa și ținta nu pot
|
||||
avea același nume într-un `SELECT...INTO CURSOR`).
|
||||
3. Cu un alias scratch diferit ca țintă (`SELECT * FROM (cursor) INTO CURSOR
|
||||
(nume_final_diferit_de_sursa) READWRITE`) → tot `Invalid operation for the cursor.` pe
|
||||
`ALTER TABLE`, chiar dacă acum cursorul final teoretic ar trebui să fie unul local
|
||||
obișnuit.
|
||||
|
||||
Nu există niciun alt loc în codul ROA* care să facă `ALTER TABLE` imediat după
|
||||
`goExecutor.oExecute()` — deci acest pattern nu avea niciun precedent testat înainte de
|
||||
funcțiile AUTOPASS.
|
||||
|
||||
## 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 ...`):
|
||||
|
||||
```foxpro
|
||||
lcCursorRaw = lcCursor + '_raw'
|
||||
IF USED(lcCursorRaw)
|
||||
USE IN (lcCursorRaw)
|
||||
ENDIF
|
||||
|
||||
lnSucces = goExecutor.oExecute(lcSql, lcCursorRaw)
|
||||
IF lnSucces < 0
|
||||
* tratare eroare, RETURN
|
||||
ENDIF
|
||||
|
||||
SELECT *, .F. AS coloananoua, SPACE(100) AS altacoloana ;
|
||||
FROM (lcCursorRaw) INTO CURSOR (lcCursor) READWRITE
|
||||
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. dintr-o altă funcție care primește cursorul deja gata construit,
|
||||
nu direct rezultatul unui `oExecute`), 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()`.
|
||||
48
docs/conventie_ux_formulare.md
Normal file
48
docs/conventie_ux_formulare.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# Convenție UX pentru formulare VFP (preferința lui Marius, valabilă pe toate proiectele ROA*)
|
||||
|
||||
Partajat între proiectele ROA* (similar cu `PROMPT_cautare_vfp.md`, `prompt_project_insights_docs.md`
|
||||
din acest folder) — pentru că `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.
|
||||
|
||||
Origine: confirmat de Marius pe `frm_autopass.scx` (ROAAUTO) după o rundă de regrupare vizuală
|
||||
(2026-07-10) — "imi place designul acesta" pe layout-ul cu rânduri clar separate pe funcție,
|
||||
butoane grupate la margini, fără elemente lipite unele de altele.
|
||||
|
||||
## Ce înseamnă in practică, pe proprietăți VFP
|
||||
|
||||
- **Fiecare grup funcțional pe rândul lui** — nu înghesui controale fără legătură directă pe
|
||||
același `Top`. Ex: rândul de perioadă (date + Actualizează) separat de rândul de
|
||||
statistici (Declarabile/Transmise/Blocate), separat de panoul de configurare.
|
||||
- **Spațiere vizibilă între grupuri, strânsă în interiorul unui grup** — butoane din
|
||||
aceeași acțiune (ex. Validează dry-run → Transmite → Renunță) la 6-10px unele de altele;
|
||||
gap de 20-30px față de următorul grup funcțional (ex. Selectează tot vs. grupul
|
||||
Validare/Transmitere vs. Actualizează statusuri).
|
||||
- **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 vizual ca
|
||||
acțiune separată de câmpul de input.
|
||||
- **Acțiunea principală + oprirea ei alăturate** — un buton de tip "Renunță/Oprește" trebuie
|
||||
poziționat lângă acțiunea pe care o anulează (ex. Transmite + Renunță), nu împrăștiat în
|
||||
altă parte a rândului.
|
||||
- **Un singur rând de acțiuni cât se poate** — dacă mai multe grupuri de butoane încap pe
|
||||
lățimea formei, preferă un singur rând orizontal în loc să adaugi rânduri noi dedesubt;
|
||||
păstrează formele compacte pe verticală.
|
||||
- **Caption-uri scurte, sentence case, nu ALL CAPS** — ex. "Transmite" nu "TRANSMITE";
|
||||
"Dashboard AutoPass" nu "Deschide dashboard AUTOPASS". ALL CAPS/text lung pe un buton
|
||||
citește ca zgomot, nu ca ierarhie.
|
||||
- **Culoare = semnal, nu decor** — folosește culoare distinctă doar pentru acțiuni cu
|
||||
semnificație clară (verde = acțiune pozitivă/transmite, roșu = oprire/pericol, albastru =
|
||||
navigare/deschidere link extern); restul butoanelor rămân stilul implicit din `_baza.vcx`.
|
||||
|
||||
## Vocabular
|
||||
|
||||
Funcțional, compact, aerisit, minimalist, grupat, ușor de înțeles de utilizatori, aer aerisit,
|
||||
modern — asta e reperul calitativ pentru orice formular nou sau refacere de layout, dincolo de
|
||||
regulile mecanice de mai sus, 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).
|
||||
- Capcana de encoding cp1252 la editarea `.sc2`/`.vc2` (corupere diacritice) — documentată în
|
||||
proiectul unde a fost descoperită (ROAAUTO `docs/conventie_encoding_cp1252.md`); relevantă ori
|
||||
de câte ori editezi text-cache-ul unui formular/librărie pentru a aplica aceste reguli de UX.
|
||||
106
docs/depanare_testare_vfp.md
Normal file
106
docs/depanare_testare_vfp.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# Depanare si testare VFP fara IDE (headless)
|
||||
|
||||
Metoda folosita la depanarea erorii "Property CNRCRT is not found" (ROACONT 2.11.61,
|
||||
15.07.2026) - reutilizabila pentru orice bug runtime VFP. Complementara cu
|
||||
`flux-editare-vfp-text.md` (editare .vcx/.scx pe text) si `cautare_vcx_vct.md` (cautare).
|
||||
|
||||
## 0. Reguli de lucru
|
||||
|
||||
Vezi `reguli_lucru.md` (diff ca fisier + aprobare inainte de write-back, comentarii
|
||||
max o linie, modificari minime).
|
||||
|
||||
## Fisiere de testare (foloseste-le la orice depanare/testare viitoare)
|
||||
|
||||
- `COMUN\utile\Teste\test_init_env_auto.prg` - initializare completa de mediu FARA
|
||||
interactiune (parametri: host, schema, parola; implicit CENTRAL / MARIUSM_AUTO).
|
||||
Echivalentul headless al `COMUN\programe\test_init_env.prg` (care ramane varianta
|
||||
interactiva, cu INPUTBOX si meniu de lansare formulare).
|
||||
- `COMUN\utile\Teste\test_repro_cnrcrt_footer.prg` - exemplu complet de harness:
|
||||
init mediu -> replicare flux (cursoarele din modificanote) -> instantiere forma reala ->
|
||||
executie pas cu pas cu logare -> verdict OK/BUG. Copiaza-i structura pentru bug-uri noi.
|
||||
- `COMUN\utile\Teste\teste_roacont.prg` si `COMUN\utile\Teste\test.prg` - teste ad hoc istorice.
|
||||
- Mediu de test standard: server `CENTRAL`, schema `MARIUSM_AUTO`, parola schemei
|
||||
`ROMFASTSOFT`; utilizator de aplicatie "MARIUS M" / parola "123" (unde e nevoie de login).
|
||||
|
||||
## 1. Citirea log-ului aplicatiei (log.txt in radacina proiectului)
|
||||
|
||||
`ErrorHandler` (roacont.prg) scrie pentru fiecare eroare: `nErrror`, `cMethod`,
|
||||
`line` (0 daca exe-ul e compilat fara debug info) si stack-ul complet.
|
||||
|
||||
Semantica ON ERROR (esentiala la interpretare):
|
||||
- Dupa ce handlerul face RETURN, executia CONTINUA de la linia urmatoare din metoda
|
||||
care a crapat. O singura cauza produce deci CASCADE de erori.
|
||||
- Tipar clasic: eroare pe linia `WITH <expr>` => urmatoarele linii `.prop = ...` dau
|
||||
1940 "Expression is not valid outside of WITH/ENDWITH", apoi `ENDWITH` da
|
||||
1939 "WITH/ENDWITH mismatch". PRIMA eroare din secventa e cea reala; restul e zgomot.
|
||||
- Erorile din interiorul TRY/CATCH nu ajung in log (inghitite). Un CATCH gol poate
|
||||
ascunde ani de zile un defect latent, care "explodeaza" cand codul din jur se repara
|
||||
(exact cazul typo-ului oMinHeaderHeight din cusfonthandler).
|
||||
- In stack, liniile "ON..." sunt dispatch-uri (ON ERROR / READ EVENTS), nu metode reale.
|
||||
|
||||
## 2. Rulare headless a scripturilor VFP
|
||||
|
||||
Sablonul unui script de diagnostic (vezi `utile\Teste\test_repro_cnrcrt_footer.prg`):
|
||||
- logare in fisier cu STRTOFILE (nu WAIT WINDOW / debugger - nu exista consola);
|
||||
- `ON ERROR DO <handler> WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()` care logheaza
|
||||
si continua - mimeaza comportamentul ErrorHandler din aplicatie;
|
||||
- `QUIT` obligatoriu la final (altfel ramane vfp9.exe agatat);
|
||||
- lansare din PowerShell cu timeout:
|
||||
`$p = Start-Process 'C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe' -ArgumentList '-A','-T','"D:\...\script.prg" PARAM' -PassThru; $p.WaitForExit(120000); if (!$p.HasExited) { $p.Kill() }`
|
||||
- `-A` ignora config, `-T` fara ecran de start; parametrul dupa .prg ajunge in LPARAMETERS.
|
||||
- LINENO() din handler e relativ la inceputul metodei (utile pentru localizare in .vc2:
|
||||
linia din metoda = linia raportata + linia PROCEDURE din .vc2).
|
||||
|
||||
Precautii: nu rula cu VFP IDE sau exe-ul aplicatiei deschis (lock pe binare);
|
||||
sterge .fxp-ul vechi de langa .prg daca ai editat scriptul intre rulari.
|
||||
|
||||
## 3. Mediu complet cu Oracle, fara interactiune
|
||||
|
||||
`utile\Teste\test_init_env_auto.prg` = varianta neinteractiva a
|
||||
`programe\test_init_env.prg` (fara INPUTBOX/xmenu): primeste host/schema/parola ca
|
||||
parametri, seteaza PATH/CLASSLIB/PROCEDURE ca roacont.prg, instantiaza
|
||||
goConn/goExecutor/goApp/goLog, incarca goFirma/goCalendar/optiuni si pachetele de
|
||||
sesiune Oracle. Dupa apel poti instantia forme reale (`CREATEOBJECT('frm_xxx', ...)`)
|
||||
si apela metodele lor punctual, cu cursoarele pregatite ca in fluxul real.
|
||||
|
||||
Pentru forme care se deschid modal (Show(1) blocheaza), nu apela Show: replica in
|
||||
script doar liniile relevante din Show (attach, calcule) si logheaza starea intre ele.
|
||||
|
||||
## 4. Bisectia versiunilor de clase (regresii)
|
||||
|
||||
Cand un bug apare "de azi", compara comportamentul cu clasa veche fara a atinge SVN:
|
||||
1. `git show <rev_vechi>:clase/fisier.vcx > temp\fisier.vcx` (+ .vct identic);
|
||||
2. convertit la text pentru diff: `vcx2txt.ps1 -Source temp\fisier.vcx -CacheRoot temp\txt`;
|
||||
3. in scriptul de test, `SET CLASSLIB TO temp\fisier.vcx ADDITIVE` (varianta veche)
|
||||
vs. cea din COMUN (varianta noua) - A/B pe acelasi flux;
|
||||
4. cand difera rezultatul, cauza e in diff-ul acelei clase (sau intr-un defect latent
|
||||
pe care noul cod il activeaza - vezi capcanele de mai jos).
|
||||
|
||||
## 5. Capcane VFP descoperite (de verificat la bug-uri asemanatoare)
|
||||
|
||||
- `SELECT ... INTO CURSOR` NU mosteneste indecsii cursorului sursa. Orice
|
||||
`Seek(..., 'cursor', 'tag')` pe copie crapa. `update_jtva_coloane` creeaza
|
||||
`INDEX ON id_jtva_coloana TAG id_jtva`; daca ii copiezi rezultatul, recreeaza indexul.
|
||||
- Un grid isi pierde TOATE coloanele (ColumnCount devine 0, fara nicio eroare in log)
|
||||
daca un ControlSource crapa la re-evaluare in timp ce coloanele sunt atinse
|
||||
programatic (ex. FontName/FontSize per coloana in cusfonthandler.ApplyFontToGrid,
|
||||
la Init-ul formei prin _frmbase.SetFont). Simptome tipice in aval:
|
||||
`_grdfooter.attachtogrid` copiaza 0 coloane, apoi `calctotal` da
|
||||
"Property <cColWithLabel> is not found" la `Getpem(This, This.cColWithLabel)`.
|
||||
- ControlSource-uri cu campuri inexistente in RecordSource sunt tolerate la afisare,
|
||||
dar orice expresie care ARUNCA eroare la evaluare (Seek pe tag lipsa, functie
|
||||
nedefinita) declanseaza comportamentul de mai sus.
|
||||
- Fix-ul unui typo intr-o clasa partajata poate activa defecte latente in aval
|
||||
(codul care nu rulase niciodata incepe sa ruleze). La regresii dupa fix-uri
|
||||
"inofensive" in COMUN, cauta defectul latent, nu doar diff-ul.
|
||||
|
||||
## 6. Studiu de caz: "Property CNRCRT is not found" (15.07.2026)
|
||||
|
||||
Lant complet: `frm_import_extrase_banca.modificanote` copia `crsJTVATemp` fara index
|
||||
(defect latent) -> coloana `cExplicatieTVA` din `frm_modific2024.grdRulaje` face
|
||||
`Seek(trul.id_jtva_coloana,'crsJtvaTemp','id_jtva')` in ControlSource -> fix-ul
|
||||
typo-ului `oMinHeaderHeight`->`nMinHeaderHeight` in `cusfonthandler` (r17869) a facut
|
||||
ca ApplyFontToGrid sa atinga coloanele la Init -> grid-ul a ramas cu 0 coloane ->
|
||||
footer-ul a crapat in calctotal. Fix: `INDEX ON id_jtva_coloana TAG id_jtva` dupa
|
||||
SELECT INTO in modificanote. Repro/regresie: `utile\Teste\test_repro_cnrcrt_footer.prg`
|
||||
(mod FARAINDEX reproduce bug-ul, mod CUINDEX valideaza fix-ul).
|
||||
41
docs/flux-editare-vfp-text.md
Normal file
41
docs/flux-editare-vfp-text.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# 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: in `docs\` proiectului.
|
||||
|
||||
**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
|
||||
inainte de orice `git commit`. Write-back doar pentru vcx/scx; `frx/mnx/lbx/pjx/dbc/dbf` doar
|
||||
in IDE. `txt2vcx.ps1` cu `-CacheRoot` = `-ProjectRoot` (implicit). Pasul 0 de mai jos devine
|
||||
rularea `git_sync.ps1`; restul pasilor raman la fel. Fluxul cu cache extern (`vcx2txt.ps1` +
|
||||
`-CacheRoot` separat) ramane doar pentru proiectele nemigrate.
|
||||
|
||||
## 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).
|
||||
2. Editare byte-safe: PowerShell `[IO.File]::ReadAllText/WriteAllText(..., GetEncoding(1252))`;
|
||||
NU tool-ul Edit/Write (UTF-8 strica diacriticele). Continut nou ASCII, TAB-uri ca in jur,
|
||||
fara reflow (format position-sensitive, proprietati alfabetizate). Valabil si pentru `.prg`.
|
||||
3. Patch review: `git diff --no-index <bak> <editat> > docs/diff_runda<N>_<subiect>.patch`
|
||||
(exit 1 = normal). Utilizatorul revizuieste FISIERUL de patch si aproba; write-back-ul
|
||||
(pasul 5) se face DOAR dupa aprobare. Commit doar dupa confirmare pe patch + test in IDE.
|
||||
Comentariile in cod: maxim o linie (`*!* DD.MM.YYYY autor - motiv scurt`), fara explicatii lungi.
|
||||
4. Preconditie write-back: niciun proces vfp9/<exe proiect> (tin lock pe binar); nu se omoara.
|
||||
5. Write-back: `txt2vcx.ps1 -TextFile <vc2> -ProjectRoot <root> -CacheRoot <cache>`
|
||||
(+ `-AllowComun` cu aprobare explicita pentru tinte COMUN — afecteaza toate aplicatiile ROA).
|
||||
Succes = fidelity-check trecut: binar cu mtime nou; `vcx2txt.ps1` ulterior il vede la zi.
|
||||
6. Backup-urile `.pre_runda*.bak` si patch-urile se sterg la curatenia de dupa commit.
|
||||
|
||||
## Capcane
|
||||
|
||||
- `.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:`.
|
||||
- Subagentii delegati primesc regulile 2-5 in prompt si raporteaza unicitatea sirurilor
|
||||
inlocuite + rezultatul fidelity-check-ului.
|
||||
65
docs/fluxul_svn_git.md
Normal file
65
docs/fluxul_svn_git.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Flux SVN + git pentru COMUN
|
||||
|
||||
**SVN = șeful** (munca reală circulă prin el). **git = oglindă** pentru unelte (Claude, căutare).
|
||||
git primește de la SVN, niciodată invers.
|
||||
|
||||
## Reguli
|
||||
|
||||
1. **Munca reală se comite DOAR în SVN.** Nu face `git commit` cu o modificare nouă care n-a trecut prin SVN.
|
||||
2. **git se împrospătează DIN svn**, într-o singură direcție.
|
||||
3. **COMUN se publică pe git dintr-UN SINGUR folder** (publisher, ex. `ROAAUTO\COMUN`). Celelalte doar se aliniază la origin.
|
||||
|
||||
## Lucrat în paralel în 2 proiecte (ex. roagest + roaauto), fișiere diferite
|
||||
|
||||
### 1. Împaci în SVN
|
||||
```
|
||||
# ROAGEST\COMUN
|
||||
svn commit -m "modificari roagest"
|
||||
# ROAAUTO\COMUN
|
||||
svn update # aduce fisierele din roagest (alte fisiere -> fara conflict)
|
||||
svn commit -m "modificari roaauto"
|
||||
# ROAGEST\COMUN
|
||||
svn update # aduce fisierele din roaauto
|
||||
```
|
||||
Acum ambele copii SVN au tot. E sursa de adevăr.
|
||||
|
||||
### 2. Oglindești în git (doar din folderul publisher)
|
||||
```
|
||||
cd ROAAUTO\COMUN
|
||||
git add -A
|
||||
git commit -m "sync svn"
|
||||
git push
|
||||
```
|
||||
|
||||
### 3. Celălalt folder: aliniere, NU commit
|
||||
```
|
||||
cd ROAGEST\COMUN
|
||||
git fetch origin
|
||||
git reset --hard origin/main
|
||||
```
|
||||
Sigur: fișierele sunt deja identice cu origin (le-a făcut svn), `reset` doar mută pointerul.
|
||||
|
||||
## Când te muți dintr-un proiect în altul
|
||||
```
|
||||
svn update # in proiectul unde intri
|
||||
git reset --hard origin/main # in COMUN, ca git-ul sa fie curat
|
||||
```
|
||||
|
||||
## Regula care rezumă tot
|
||||
> Un singur folder publică în git (commit+push). Celelalte doar `git reset --hard origin/main`.
|
||||
> Munca circulă prin SVN; git fotografiază rezultatul.
|
||||
|
||||
## Model de branching (git urmareste text .??2)
|
||||
|
||||
git urmareste versiunile text FoxBin2Prg (.vc2/.sc2/…), improspatate in-arbore cu
|
||||
`git_sync.ps1` la inceput de sesiune si inainte de orice commit; nu comite cat timp
|
||||
`git_sync` raporteaza esecuri (exit nenul). Doua benzi:
|
||||
|
||||
- **`main` = oglinda SVN**: primeste DOAR commit-uri `sync SVN rN`, facute din stare curata
|
||||
(imediat dupa `svn update`, inainte de lucru local).
|
||||
- **Claude lucreaza pe branch** `claude/<subiect>` si comite doar acolo;
|
||||
`git diff main..claude/<subiect>` arata exact si numai munca lui.
|
||||
- Dupa ce modificarile intra in SVN (`svn commit` facut de utilizator), branch-ul se inchide
|
||||
(merge in `main` la urmatorul sync sau stergere).
|
||||
- Igiena: sync pe `main` doar din stare curata — `svn update` in mijlocul lucrului amesteca
|
||||
binarele pe disc.
|
||||
86
docs/git_svn_parallel_init_prompt.md
Normal file
86
docs/git_svn_parallel_init_prompt.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Prompt: init git in paralel cu SVN pentru un proiect ROA
|
||||
|
||||
Foloseste acest prompt intr-o sesiune Claude Code noua, deschisa in radacina proiectului
|
||||
tinta (ex. `D:\ROA\ROAIMOB`). Functioneaza generic pentru orice proiect VFP din `D:\ROA\`
|
||||
care are structura ROAACNPRO (proiect + subfolder COMUN\ partajat, ambele in SVN).
|
||||
|
||||
---
|
||||
|
||||
```
|
||||
Vreau sa initializezi git pentru proiectul VFP din directorul curent, in paralel cu SVN-ul
|
||||
existent (nu atinge SVN, nu rula comenzi svn, doar adauga .svn/ in .gitignore).
|
||||
|
||||
Structura e identica cu D:\ROA\ROAACNPRO: acest folder e propriul proiect VFP (are un .PJX
|
||||
al lui), si contine un subfolder COMUN\ care e framework-ul PARTAJAT intre toate aplicatiile
|
||||
ROA, versionat separat prin SVN (are propriul .svn\).
|
||||
|
||||
Fa exact ce s-a facut deja pentru ROAACNPRO (poti citi acolo ca referinta/sablon):
|
||||
- D:\ROA\ROAACNPRO\.gitignore (sablon pentru .gitignore-ul proiectului principal)
|
||||
- D:\ROA\ROAACNPRO\COMUN\.gitignore (sablon pentru .gitignore-ul din COMUN)
|
||||
- D:\ROA\ROAACNPRO\CLAUDE.md (conventii proiect) si docs\cautare_vcx_vct.md (cum se cauta
|
||||
cod in interiorul .vcx/.scx binare, via D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1)
|
||||
|
||||
Pasi:
|
||||
|
||||
1. Verifica intai ce exista deja: `git status`/`.git` in radacina si in COMUN\, si
|
||||
`git remote -v` daca exista deja vreun remote configurat gresit (asa cum a fost cazul la
|
||||
ROAACNPRO, unde originul proiectului principal pointa gresit catre repo-ul comun.git).
|
||||
|
||||
2. REPO PRINCIPAL (radacina acestui folder):
|
||||
- Daca nu exista .git, `git init -b main`.
|
||||
- Creeaza/adapteaza .gitignore dupa modelul ROAACNPRO/.gitignore (artefacte VFP compilate:
|
||||
*.fxp, *.mpx, *.bak, *.mpr, *.err, log.txt, *.tmp, *.dct, *.exe, cruft Windows), plus
|
||||
obligatoriu `COMUN/` (COMUN e gestionat de git-ul lui separat, nu de-al acestui repo)
|
||||
si `.svn/`.
|
||||
- Deduce numele repo-ului gitea dupa conventia romfast/<nume-folder-lowercase>.git
|
||||
(ex. romfast/roaimob.git). INAINTE sa creezi/pushezi orice, verifica cu
|
||||
`git ls-remote git@gitea.romfast.ro:romfast/<nume>.git` daca exista deja si ce contine
|
||||
(clone --depth 1 intr-un folder temporar din scratchpad daca ai dubii). Daca exista deja
|
||||
cu istoric care nu se potriveste cu ce ai local, OPRESTE-TE si intreaba-ma inainte sa
|
||||
faci push sau orice suprascriere.
|
||||
- Daca remote-ul e gol/nou: add -A, commit "Initial commit — sursa <PROIECT>", adauga
|
||||
origin, push normal (fara --force).
|
||||
|
||||
3. COMUN\ (subfolder-ul partajat):
|
||||
- Initializeaza un git SEPARAT, propriu, in interiorul COMUN\ (COMUN are propriul .git,
|
||||
nu e tracked de repo-ul principal — de-asta l-am exclus mai sus).
|
||||
- .gitignore propriu in COMUN\ dupa modelul ROAACNPRO/COMUN/.gitignore (artefacte VFP +
|
||||
`.svn/` + `bash.exe.stackdump`).
|
||||
- Origin-ul din COMUN\ trebuie sa fie EXACT acelasi repo pentru toate proiectele ROA:
|
||||
git@gitea.romfast.ro:romfast/comun.git — repo-ul asta e deja populat (din COMUN-ul lui
|
||||
ROAACNPRO). NU face commit+push orbeste peste el.
|
||||
- Fa intai `git fetch origin`, compara continutul de pe origin/main cu fisierele locale
|
||||
din acest COMUN\ (diff pe folder, nu doar pe nume). Daca sunt identice sau diferentele
|
||||
sunt neglijabile, seteaza pur si simplu branch-ul local sa urmareasca origin/main (fara
|
||||
sa strici fisierele din working copy SVN). Daca sunt diferente reale intre COMUN-ul
|
||||
acestui proiect si cel deja impins pe gitea, arata-mi un rezumat al diferentelor si
|
||||
intreaba-ma explicit cum procedez (nu face force-push fara aprobarea mea explicita —
|
||||
ar sterge ireversibil istoricul comun tuturor proiectelor ROA).
|
||||
|
||||
4. Cautare in cod VFP binar (.vcx/.scx) pentru acest proiect:
|
||||
- Foloseste acelasi vcx2txt.ps1, dar parametrizat pentru proiectul curent (nu ROAACNPRO):
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
||||
-Project D:\ROA\<PROIECT>\<proiect>.PJX -ProjectRoot D:\ROA\<PROIECT> `
|
||||
-CacheRoot D:\ROA\UTIL\foxbin2prg\_textcache_<proiect>
|
||||
- Cache separat per proiect (nu-l amesteca cu _textcache al ROAACNPRO). Grep in cache-ul
|
||||
respectiv, la fel ca in docs\cautare_vcx_vct.md.
|
||||
|
||||
5. La final, adauga/actualizeaza CLAUDE.md al acestui proiect cu o sectiune scurta: git ruleaza
|
||||
in paralel cu SVN legacy (SVN ramane sursa "vie" pentru COMUN, sincronizat manual catre git);
|
||||
COMUN e partajat intre toate aplicatiile ROA prin acelasi git@gitea.romfast.ro:romfast/comun.git;
|
||||
cautarile in .vcx/.scx se fac cu vcx2txt.ps1 parametrizat pentru acest proiect (vezi mai sus).
|
||||
|
||||
Inainte de orice `push --force` sau orice operatie care ar suprascrie istoric remote deja
|
||||
existent (mai ales pe romfast/comun.git, care e comun mai multor proiecte), opreste-te si
|
||||
intreaba-ma explicit — nu decide singur.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Note
|
||||
|
||||
- Cel mai sensibil pas e COMUN\: daca versiunea de COMUN a noului proiect difera de cea deja
|
||||
impinsa pe `comun.git` (din ROAACNPRO), Claude trebuie sa se opreasca si sa intrebe cum se
|
||||
reconciliaza, nu sa faca force-push automat.
|
||||
- Daca `romfast/<proiect>.git` nu exista inca pe gitea, trebuie creat gol acolo inainte de push
|
||||
(manual sau prin API) — altfel push-ul esueaza cu "repository not found".
|
||||
61
docs/oracle_export.md
Normal file
61
docs/oracle_export.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# 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
|
||||
PL/SQL Developer.
|
||||
|
||||
## Conexiune
|
||||
|
||||
- Client: `D:\ROA\instantclient_19_18\sqlplus.exe` (`TNS_ADMIN` e 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).
|
||||
- **Parola nu e versionată** — se află local, în `D:\ROA\ROAGEST\docs\local\oracle.md`
|
||||
(folder ignorat de git), pe mașina de lucru.
|
||||
|
||||
`PACK_CONTAFIN` există în schemele `MARIUSM_AUTO` (dev) și `ACN`, plus un sinonim `PUBLIC`.
|
||||
Exportul de referință se face din `MARIUSM_AUTO`.
|
||||
|
||||
## 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`.
|
||||
|
||||
## Comanda de export (re-generare .pck)
|
||||
|
||||
```sql
|
||||
-- export_pack.sql
|
||||
set pagesize 0 linesize 400 trimspool on feedback off heading off termout off
|
||||
spool D:\ROA\ROAGEST\COMUN\docs\PACK_CONTAFIN.pck
|
||||
select text from all_source where owner='MARIUSM_AUTO' and name='PACK_CONTAFIN' and type='PACKAGE' order by line;
|
||||
select '/' from dual;
|
||||
select text from all_source where owner='MARIUSM_AUTO' and name='PACK_CONTAFIN' and type='PACKAGE BODY' order by line;
|
||||
select '/' from dual;
|
||||
spool off
|
||||
exit
|
||||
```
|
||||
|
||||
```powershell
|
||||
& '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 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ă).
|
||||
19
docs/prompt_project_insights_docs.md
Normal file
19
docs/prompt_project_insights_docs.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Prompt: seteaza conventia docs/ (insight-uri de proiect) intr-un proiect ROA
|
||||
|
||||
Template partajat intre proiectele ROA* (similar cu `changelog_template.txt`). Origine: ROAIMOB, 08/07/2026. Copiaza blocul de mai jos (adaptat, daca e nevoie) intr-o sesiune Claude Code din radacina oricarui proiect ROA* pentru a initializa aceeasi conventie.
|
||||
|
||||
---
|
||||
|
||||
In acest proiect vreau sa creezi un director `docs/` cu documentatie tehnica concisa, minimalista, descoperita in timp ce lucrezi la sarcini reale (nu documentatie generica, nu ce e deja evident din cod).
|
||||
|
||||
Cerinte:
|
||||
|
||||
1. Creeaza `docs/README.md` — index cu lista fisierelor din `docs/` si o regula scurta: se adauga/actualizeaza o notita ori de cate ori descoperi ceva nou si ne-evident despre structura proiectului (flux ascuns, capcana, conventie, procedura/pachet cheie, tabel relevant) in timpul rezolvarii unei sarcini. Nu re-documenta ce oricine ar afla citind codul in 30 de secunde.
|
||||
2. Organizeaza notitele in fisiere separate pe subiect, nu un singur fisier uriaș — ex: `flux-<nume-flux>.md`, `pachet-<nume-pachet>.md`, `tabele.md`.
|
||||
3. In `CLAUDE.md` (la final), adauga o sectiune "Project insights (docs/)" care:
|
||||
- trimite spre `docs/README.md`
|
||||
- imi cere sa iti ofer proactiv actualizarea `docs/` ori de cate ori descoperi un insight ne-evident, fara sa astept sa fiu intrebat
|
||||
4. Daca `docs/` sau o sectiune similara in `CLAUDE.md` exista deja, nu duplica — extinde ce exista.
|
||||
5. Nu inventa continut acum daca nu am rezolvat inca o problema concreta in acest proiect — doar pregateste structura (README + sectiunea din CLAUDE.md). Prima notita de continut se scrie cand rezolvam ceva impreuna.
|
||||
|
||||
Intreaba-ma doar daca trebuie sa alegi intre variante (ex. denumirea directorului); altfel foloseste `docs/` ca implicit.
|
||||
15
docs/reguli_lucru.md
Normal file
15
docs/reguli_lucru.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Reguli de lucru agent (comune proiectelor ROA VFP)
|
||||
|
||||
1. Modificari de cod: livreaza FISIER de diff `docs\diff_runda<N>_<subiect>.patch`
|
||||
(`git diff --no-index <baseline.bak> <editat>`), nu diff in terminal.
|
||||
Write-back in binar (txt2vcx) si commit DOAR dupa aprobarea patch-ului de catre utilizator.
|
||||
2. Comentarii in cod: max o linie `*!* DD.MM.YYYY autor - motiv scurt`.
|
||||
Explicatiile merg in docs/ sau in mesajul de commit, nu in cod.
|
||||
3. Modificari minime: doar ce s-a cerut; fara refactorizari sau curatenie din oficiu.
|
||||
4. Testare headless (fara IDE): `vfp9.exe -A -T "<script.prg>" <param>` din PowerShell,
|
||||
logare cu STRTOFILE, `ON ERROR` care logheaza si continua, QUIT la final.
|
||||
Init mediu neinteractiv: `utile\Teste\test_init_env_auto.prg` (CENTRAL / MARIUSM_AUTO;
|
||||
user aplicatie "MARIUS M"/"123"). Exemplu harness complet: `utile\Teste\test_repro_cnrcrt_footer.prg`.
|
||||
Metoda de depanare (log.txt, cascade ON ERROR, bisectie clase): `depanare_testare_vfp.md`.
|
||||
5. Editare .vcx/.scx pe text (cache, cp1252 byte-safe, fidelity-check): `flux-editare-vfp-text.md`.
|
||||
Cautare in binare: `cautare_vcx_vct.md`.
|
||||
Reference in New Issue
Block a user