19 KiB
Fiche OUTC-T2 — Niveau N1 — Modèle prévu sonnet | utilisé claude-sonnet-5-5 — Agent lp-impl — Skills sk-protocol (préchargé), sk-windows-shell (invoqué), sk-repo § 2 et § 6 et lp-repo § 7 (lus par Read), ue-cpp-build / lp-build / lp-ue-compat (préchargés, sans objet)
OUTC-T2-IMPL : Tools\Verrou.ps1 et Tools\Numero.ps1 (2026-10-11)
Résultat : réussi, avec un écart de moyen à décider (§ 2 E1 : création du dossier de verrou par CreateDirectoryW et non par New-Item, parce que New-Item sans -Force n'est pas atomique, mesure à l'appui). Essais : 124 appels et contrôles, 0 écart (SYNTHESE de OUTC-T2_essais.txt l. 417) ; vrai VERROU lu en -Etat seulement ; vrai NUMEROS.md jamais écrit.
1. Fichiers modifiés (chemins, lignes)
Dépôt du jeu D:\Game\LifePlay-master 5.8, branche ue5.8, HEAD ae5d5e4 (la fiche citait 06dfb55 : le HEAD a avancé, sans effet sur ces fichiers). Les deux sont neufs, LF, sans BOM, ASCII seul (FileCheck.ps1 : LF, CRLF=0, BOM -, alertes 0 ; octets > 0x7F = 0 ; analyse syntaxique pwsh : 0 erreur).
| Fichier | Lignes | Taille | MD5 | Contenu |
|---|---|---|---|---|
Tools\Verrou.ps1 |
228 | 11 010 o | 788B21F30155200A497C3919FB3CBA29 |
en-tête d'aide l. 1-58 ; param l. 59 ; New-DossierAtomique l. 75 ; Get-VerrouK l. 86 ; Get-Qui l. 99 ; Fin l. 123 ; New-LignesOccupe l. 130 ; -Prendre l. 157 ; -Rendre l. 190 ; -Etat l. 216 ; catch général (code 2) l. 225 |
Tools\Numero.ps1 |
291 | 13 849 o | 8803E6A42DAD21292DFE3024732BF589 |
en-tête d'aide ; param l. 63 ; Get-MaxFichier l. 85 ; Get-MaxDocs l. 100 ; Get-MaxRegistre l. 116 ; Get-Maxima l. 134 ; usage l. 168 ; -Dernier l. 178 ; -Reserver l. 194 ; try l. 220 ; catch l. 270 ; finally (rend le verrou) l. 273 |
Comportement livré (conforme à OUTC-SPEC.md § 3.2 et § 3.3 sauf § 2) :
Verrou.ps1 -Prendre <ticket> [-Session] | -Rendre [-Ticket] | -Etat,-Racine(défaut<projet>\Docs\Migration\etat\REPO\VERROU),-Json. Codes 0 / 1 / 2 comme la SPEC. Rien n'est supprimé ni renommé, aucun paramètre de forçage ; au-delà de 30 min, suffixeANCIEN (signaler, ne pas forcer).Numero.ps1 -Reserver CHG|ERR|DOC -Lot -Demandeur [-Nombre] [-Copie55] [-Fichier] [-Racine] [-Json]et-Dernier CHG|ERR|DOC. Écriture par ajout d'octets (FileStreamenAppend), séparateur détecté, contrôle du préfixe (MD5 desnoctets d'avant), de la longueur et de la fin ; verrou rendu dans unfinally.
2. Écarts à la SPEC (obligatoire)
- E1 (à décider) — moyen de création du dossier de verrou. SPEC § 3.2 point 2 et fiche § 5 prescrivent
New-Item -ItemType Directorysans-Force, « échoue si le dossier existe ». Vrai en séquentiel, faux en concurrence : essai en 100 tours de 8 threads alignés sur uneThreading.Barrier, tous appelantNew-Item -ItemType Directory -Path <même chemin> -ErrorAction Stop(pwsh 7.6.6) : exactement 1 succès dans 12 tours, plusieurs succès dans 88 tours, 0 tour sans succès (sortie de la commande, tour 9 de cette fiche ; commande rappelée ci-dessous). Même essai avecCreateDirectoryWdekernel32(P/Invoke parAdd-Type) : 1 succès dans 100 tours sur 100 ; second appel séquentiel :False,GetLastWin32Error= 183 (ERROR_ALREADY_EXISTS) (scratchpad\OUTC-T2\stress2.ps1, sortie dans ce compte rendu). AvecNew-Item, deux gardiens pourraient donc se croire titulaires du mêmek+1, ce que le verrou doit empêcher. Choix fait :New-DossierAtomique(Verrou.ps1l. 75-84) appelleCreateDirectoryW; 183 = occupé (code 1), autre erreur = code 2. Effet de bord :Add-Typecoûte ≈ 640 ms au premier appel de chaque processus. Retour à la lettre de la SPEC : remplacer le corps de cette seule fonction partry { New-Item -ItemType Directory -Path $Path -ErrorAction Stop | Out-Null; $true } catch { if (Test-Path -LiteralPath $Path) { $false } else { throw } }; je ne le recommande pas. Preuve en processus séparés (A17) : 5 tours de 6 processusVerrou.ps1 -Prendrelancés ensemble : à chaque tour un seul code 0, cinq codes 1,qui.txtdu dossier = celui du gagnant (l. 184-204 deOUTC-T2_essais.txt). Commande de l'essaiNew-Item(non rangée en fichier, rejouable) :pwsh -NoProfile -Commandavecforeach ($r in 1..100) { $p = Join-Path $base "r$r"; $bar = [Threading.Barrier]::new(8); $res = 1..8 | ForEach-Object -Parallel { $b = $using:bar; $path = $using:p; $b.SignalAndWait(); try { New-Item -ItemType Directory -Path $path -ErrorAction Stop | Out-Null; 1 } catch { 0 } } -ThrottleLimit 8; ... somme des 1 par tour }. - E2 — course simulée : paramètre caché
-TestCourse([Parameter(DontShow)], décrit dans l'aide) : juste avant la création, crée le dossier cible comme le ferait un tiers (avecqui.txtTIERS-TESTpour-Prendre). Prévu par la fiche (« paramètre caché de test, à décrire »). - E3 — affichage d'un verrou occupé : première ligne
qui.txt (k=<k>) : <contenu brut>, dernière ligneVERROU OCCUPE k=<k> par <qui> depuis <min> min, où<qui>=qui.txtsans la date finale.-Etatn'imprime que la ligne de verdict. La SPEC dit « affiche<k>\qui.txt» sans préciser le format. Refus de-Rendre -Ticket:VERROU REFUS k=<k> : tenu par <qui>, pas par <ticket>(libellé non fixé par la SPEC). - E4 —
-Rendre -Ticket T: correspondance =qui.txtcommence parTsuivi d'un caractère autre que lettre, chiffre,_ou-(ou fin de ligne), insensible à la casse ; la SPEC dit « commence par ce ticket », ce qui ferait rendre le verrou deOUTC-R10àOUTC-R1(essais A11b, A11c). - E5 — points laissés ouverts par la SPEC, tranchés : sans
-Session,qui.txtportesession non precisee;-Ticketsans-Rendreet-Sessionsans-Prendre= paramètres incohérents, code 2 ; racine vide =k0, libre ;-Rendresans-Ticketrend le verrou tenu, quel qu'en soit le titulaire (SPEC § 3.2 point 3 ne demande le contrôle qu'avec-Ticket). - E6 —
-Jsonaccepté par les trois actions deVerrou.ps1(la SPEC ne le cite que pour-Etat) :Numero.ps1en a besoin pour lireket le code. - E7 —
Numero.ps1, format : dateAAAA-MM-JJ HH:MM(heure locale ; la SPEC montreAAAA-MM-JJ, la fiche § 5 prescritGet-Date -Format 'yyyy-MM-dd HH:mm', comme les lignes existantes) ; plusieurs numéros :NUMERO RESERVE CHG-330 CHG-331 lot=TEST verrou=5; JSON :type,numeros[](entiers),ids[](CHG-330),lot,demandeur,verrou,fichier,date,maxima{copie58, copie55, registre, max},avertissements[](la SPEC liste{type, numeros[], lot, verrou, maxima{}}, ces ajouts sont rétrocompatibles) ;-Dernier:DERNIER CHG max=327 5.8=326 5.5=297 registre=327. - E8 — cas non couverts par la SPEC : source 5.8 absente ou sans numéro = code 2 (jamais « max = 0 ») ; copie 5.5 absente = avertissement et
5.5=absentdans la ligne ;-Nombrehors 1..50 = code 2 ;|du lot ou du demandeur remplacé par/, sauts de ligne par un blanc ; session du verrou = demandeur tronqué à 80 caractères, ticketNUMERO-<LOT>; fichier vide ou sans aucun saut de ligne = code 2 après la prise du verrou (le verrou est rendu : essais B6a, B6b) ; fichier à fins de ligne mixtes = avertissement, séparateur du dernier saut de ligne retenu ; verrou non rendu après une réservation réussie = ligneVERROU NON RENDUet code 2. - E9 — le livrable
OUTC-T2_essais.txtdemandé par la fiche est ignoré par git (.gitignore:75 /Docs/Migration/etat/**, seuls.mdet.csvsont repris, l. 77) : il reste sur disque, hors « Fichiers à commiter ».
3. Instantané (lot, manifeste)
Lot OUTC : D:\Game\LifePlay-master 5.8 instantané D:\Game\LifePlay_Backup_5.5\OUTC\manifest.csv (2026-10-11 06:26) ; les deux fichiers y sont Existed=False, Size=0 (lu l. 3-4 du manifeste) : rien à restaurer, le repli est « ne pas commiter / retirer les deux fichiers neufs » (Tools\Restore.ps1 -Lot OUTC, proposé, non lancé).
4. Ce qui n'a pas été fait
- Aucun essai en écriture sur le vrai
VERROUni sur le vraiNUMEROS.md(interdit). Le vrai verrou n'a été lu que parVerrou.ps1 -Etat(A18, série officielle :VERROU LIBRE k=93, 186 dossiers, liste identique avant / après l'appel) et parGet-ChildItem. Le vraiNUMEROS.mdn'a été lu que parNumero.ps1 -Dernier(B1r) etGet-FileHash; MD5CD7800199276A0AB4F2019D4044816DFau début, à la copie et à la fin de la série. - Pas d'essai de concurrence entre processus pour
Numero.ps1(fait pourVerrou.ps1, A17) : l'exclusion repose surVerrou.ps1. - Windows PowerShell 5.1 : 6 commandes seulement (§ D du fichier d'essais :
Verrou-Etat,-Prendre, occupé,-Rendre -Ticket;Numero-Dernier,-Reserver), codes attendus, puisFileCheckde la copie sous pwsh 7 ; pas la série complète. - Pas d'essai d'erreur de droits d'écriture ni de fichier verrouillé par un autre processus.
- Pas de mise à jour de
sk-repo§ 2 ni delp-repo§ 7 (qui décrivent encoremkdiret la lecture manuelle) : lot DOC séparé (SPEC § 5, décision E5). - Aucun autre fichier de
Tools\touché ; pas de commit, pas de git en écriture, aucune suppression.
5. Points à confirmer en VAL
- E1 : l'orchestrateur confirme
CreateDirectoryW(recommandé) ou demande le retour àNew-Item; la VAL peut rejouerscratchpad\OUTC-T2\stress2.ps1 -Base <dossier neuf>(attendu :exactement 1 succes=100). - V7 rejoué : Prendre (0), Prendre encore (1), Etat (1), Rendre -Ticket autre (1), Rendre (0), Rendre encore (1), Etat (0) = essais A2 à A8 (
essais.ps1du scratchpad,-Baseneuf obligatoire : le script refuse une base oùVERROUexiste). - V7 course :
-TestCourserend 1 pour-Prendreet pour-Rendre, lequi.txtdu tiers n'est pas écrasé (A12, A13). - V8 rejoué :
Numero.ps1 -Reserver CHG -Lot TEST -Fichier <copie> -Racine <test>deux fois puis-Nombre 2: numéros consécutifs 328, 329, 330-331 ; préfixe de 12 601 octets de MD5 identique ;FileCheck:CRLF,LF=0,CR=0(B2, B4) ; verrou occupé = code 1, MD5 entier inchangé (B5). - Le format de la ligne ajoutée (statut
réservéavec accents UTF-8 ; date avec heure) convient au gardien et àlp-repo§ 7. -Rendresans-Ticket(E5) : acceptable pour le gardien, ou exiger-Ticket.- Coût de ≈ 640 ms d'
Add-Typepar appel deVerrou.ps1acceptable (≈ 1 085 appels de verrou en 72 h d'après la SPEC). - À la DOC (T5),
Numero.ps1 -Reserver CHGréel sans-Fichierni-Racine: le défaut est le vraiNUMEROS.mdet le vraiVERROU; à ce jour (06:44) le registre réel donnemax=327(CHG-326etCHG-327posés par d'autres sessions depuis la rédaction de la fiche).
6. Fichiers à commiter
Dépôt du jeu D:\Game\LifePlay-master 5.8, branche ue5.8 :
- A
Tools/Verrou.ps1 - A
Tools/Numero.ps1 - A
Docs/Migration/etat/OUTC/OUTC-T2-IMPL.md
Non commités : Docs/Migration/etat/OUTC/OUTC-T2_essais.txt (ignoré, .gitignore:75) ; scratchpad <scratchpad>\OUTC-T2\ (essais.ps1, stress2.ps1, racines et copies de test VERROU*, NUMEROS-test.md, NUM-*.md, essais de mise au point dev1, dev2, stress, stress2, sorties dev1.txt, dev2.txt ; rien supprimé). essais.ps1 est réutilisable par la VAL : à ranger dans Saved\OUTC\ ou à copier, selon sk-protocol § 7.
Table des essais (commande → code → sortie)
Sorties brutes complètes : D:\Game\LifePlay-master 5.8\Docs\Migration\etat\OUTC\OUTC-T2_essais.txt (76 appels >>> / <<<, dont 7 de la section D lancés à la main hors du script, + 55 contrôles CHECK, tous OK ; les 124 de SYNTHESE = 69 appels comptés par le script + 55 contrôles). Racine de test …\scratchpad\OUTC-T2\VERROU (départ 1 1-libre 2 2-libre, k = 2). Toutes les commandes sont pwsh -NoProfile -File <script> ….
| Id | Commande (abrégée) | Code | Sortie / dossiers |
|---|---|---|---|
| A1 | Verrou -Etat |
0 | VERROU LIBRE k=2 |
| A2 | Verrou -Prendre OUTC-T2-A -Session "essai Verrou" |
0 | VERROU PRIS k=3 ticket=OUTC-T2-A ; dossier 3, qui.txt = OUTC-T2-A, session essai Verrou, 2026-10-11 06:44, LF seul |
| A3 | Verrou -Prendre OUTC-T2-B |
1 | VERROU OCCUPE k=3 par OUTC-T2-A, session essai Verrou depuis 0 min ; qui.txt inchangé |
| A4 | Verrou -Etat |
1 | VERROU OCCUPE k=3 par … |
| A5 | Verrou -Rendre -Ticket AUTRE-TICKET |
1 | VERROU REFUS k=3 : tenu par OUTC-T2-A, … ; pas de 3-libre |
| A6 | Verrou -Rendre -Ticket OUTC-T2-A |
0 | VERROU RENDU k=3 ; 3-libre créé |
| A7 | Verrou -Rendre |
1 | VERROU DEJA LIBRE k=3 |
| A8 | Verrou -Etat |
0 | VERROU LIBRE k=3 ; dossiers 1 1-libre 2 2-libre 3 3-libre |
| A9-A11 | sans -Session ; -Etat -Json ; -Prendre OUTC-R10 puis -Rendre -Ticket OUTC-R1 (1) puis -Ticket outc-r10 (0) ; -Prendre -Json (0 puis 1) |
0 / 1 | session non precisee ; JSON valide (etat, k, code) ; R1 ne rend pas R10 |
| A12 | Verrou -Prendre OUTC-T2-X -TestCourse |
1 | qui.txt (k=7) : TIERS-TEST, session essai de course … ; dossier 7 créé par le « tiers », son qui.txt non écrasé, aucun qui.txt OUTC-T2-X ; -Etat 1 ; -Rendre -Ticket TIERS-TEST 0 |
| A13 | Verrou -Rendre -TestCourse (tiers crée 8-libre avant nous) |
1 | VERROU DEJA LIBRE k=8 ; -Etat 0 |
| A14 | aucune action ; deux actions ; -Ticket avec -Etat ; -Session avec -Etat ; racine introuvable ; -Prendre "" |
2 (×6) | messages Verrou.ps1 : … ; dossiers inchangés |
| A15 | racine avec 2 daté de 45 min : -Etat ; -Prendre |
1 / 1 | … depuis 45 min ANCIEN (signaler, ne pas forcer) ; rien forcé |
| A16 | 9 9-libre 10 : -Etat ; 10 10-libre 9 9-libre : -Etat ; racine vide : -Etat, -Rendre, -Prendre |
1 / 0 / 0 / 1 / 0 | k=10 (tri numérique) ; k=0 ; PRIS k=1 |
| A17 | 5 tours × 6 processus Verrou -Prendre P<t>-<i> lancés ensemble |
0 ×1 + 1 ×5 par tour | gagnants P1-2, P2-2, P3-1, P4-1, P5-1 ; qui.txt = celui du gagnant ; -Rendre -Ticket <gagnant> 0 à chaque tour |
| A18 | Verrou -Etat (vrai VERROU, sans -Racine) |
0 | VERROU LIBRE k=93 ; 186 dossiers avant et après l'appel, listes identiques |
| B1 | `Numero -Dernier CHG | ERR | DOC -Fichier ;-Json; vrai fichier par défaut ; plage150 à 190` |
| B2a | Numero -Reserver CHG -Lot TEST -Demandeur essai -Fichier <copie> -Racine <VERROU-NUM> |
0 | NUMERO RESERVE CHG-328 lot=TEST verrou=3 |
| B2b | idem | 0 | NUMERO RESERVE CHG-329 lot=TEST verrou=4 |
| B2c | idem -Nombre 2 |
0 | NUMERO RESERVE CHG-330 CHG-331 lot=TEST verrou=5 ; dossiers 1 1-libre … 5 5-libre |
| B3 | -Reserver ERR ; DOC ; CHG -Json (demandeur avec ` |
) ; CHG -Copie55 ;DOC` avec accents |
0 ×5 |
| B4 | contrôles sur la copie après 8 appels | — | préfixe : 12 601 octets, MD5 avant = après CD7800199276A0AB4F2019D4044816DF ; longueur 12 601 → 13 664 ; 9 lignes ajoutées, toutes au format SPEC, CRLF, 0 LF seul, pas de BOM ; FileCheck : CRLF, LF=0, CR=0, alertes 0 |
| B5 | -Reserver CHG avec verrou 2 occupé par un tiers |
1 | NUMERO REFUSE : verrou occupe (…) ; rien n'a ete ecrit ; MD5 entier de la copie et liste du verrou inchangés |
| B6 | fichier sans saut de ligne ; fichier vide ; fichier introuvable | 2 ×3 | erreur nommée ; verrou pris puis rendu (2-libre, 3-libre) pour les deux premiers ; aucun verrou pris pour le troisième ; fichiers non modifiés |
| B7 | fichier LF sans saut final ; fichier CRLF sans saut final | 0 ×2 | CHG-327 ; LF conservé (LF seul 6, CRLF 0) ; CRLF conservé (CRLF 6, LF seul 0) ; préfixe identique |
| B8 | pas de type ; deux types ; type inconnu ; -Lot ou -Demandeur manquant ; -Nombre 0 ; racine de verrou introuvable |
2 ×7 | messages d'usage ; aucun verrou pris ; copie inchangée |
| C | vrai NUMEROS.md / vrai VERROU après la série |
— | MD5 réel inchangé CD78… ; aucune ligne TEST dans le vrai fichier ; 1 dossier apparu dans le vrai VERROU (93-libre, autre session), aucun ticket des essais |
| D | powershell.exe 5.1.26100.9549 : Verrou -Etat ; -Prendre PS51-A ; -Prendre PS51-B ; -Rendre -Ticket PS51-A ; Numero -Dernier CHG ; -Reserver CHG -Lot TEST51 ; puis FileCheck (pwsh 7) |
0 / 0 / 1 / 0 / 0 / 0 / 0 | PRIS k=2 ; OCCUPE k=2 ; RENDU k=2 ; DERNIER CHG max=333 … ; NUMERO RESERVE CHG-334 lot=TEST51 verrou=3 ; copie CRLF, LF=0, alertes 0 |
Commande rejouable de la série complète : pwsh -NoProfile -File "…\scratchpad\OUTC-T2\essais.ps1" -Base <dossier neuf> (garde interne : tout appel qui écrit exige -Racine et -Fichier sous -Base).
Tours : 26 / 40 (compte propre, à confirmer par python -I Tools/FicheStats.py --lot OUTC ; la fiche demande 40, le plafond de l'agent est 75)
Constats
New-Itemn'est pas atomique (E1) : l'hypothèse desk-repo§ 2 / de la SPEC («mkdiréchoue si le dossier existe, opération atomique ») est vraie pourcmd mkdiretCreateDirectoryW, pas pourNew-Itemde PowerShell. Un gardien qui poserait le verrou à la main parNew-Item(et non parmkdirde cmd ou parVerrou.ps1) hériterait du même défaut ; à noter pour le lot DOC qui réécrirask-repo§ 2.- Le vrai
NUMEROS.mda changé pendant l'IMPL (11 885 octets à ma première lecture, avecCHG-326; 12 601 octets à 06:41, avecCHG-327; réservations d'autres sessions) : une copie de test doit être faite et hachée au même instant ;B0compare la copie au vrai fichier avant et après la copie. - Dossier vide
D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REPO\3-libre(créé le 2026-10-10 10:46, hors deVERROU\) : vraisemblablement unmkdir 3-librefait au mauvais endroit ; sans effet sur les scripts (hors racine), non touché. git statusmontre aussiM Tools/EtatDir.ps1et?? Tools/GitEtat.ps1(OUTC-T3) : pas de moi, non touchés.UeState.ps1/FileCheck.ps1:FileCheck.ps1accepte plusieurs fichiers parpwsh -Command "& 'Tools\FileCheck.ps1' a, b"mais pas parpwsh -File … a b(« paramètre positionnel », piège connu delp-build§ 8) ; la commande de la fiche (-File … <copie>, un seul fichier) fonctionne.- Fixes de mise au point faits sur mes propres essais (pas sur les scripts livrés) :
Measure-Object -Maximumrend undouble(formatD3invalide), citation''dans unpwsh -Commandsous Git Bash, comparaison du vraiNUMEROS.mdà un MD5 pris trop tôt.