Commit Graph

10 Commits

Author SHA1 Message Date
5710cb69ce L'overlay ne peut plus rester fige a l'ecran
Le halo est reste affiche indefiniment. Depuis la refonte du design, la fenetre ne
se ferme plus a l'arret de l'enregistrement mais apres le collage : tout blocage
dans cette chaine — transcription qui traine, thread mort, bug en amont — la laisse
a l'ecran, et l'utilisateur n'a aucun moyen de s'en debarrasser.

La fenetre porte desormais sa propre duree de vie : une minuterie armee dans show()
la ferme quoi qu'il arrive, et hide() l'annule au passage normal. Le garde-fou ne
depend d'AUCUN code en amont, c'est tout l'interet.

La limite doit couvrir le pire cas reel — un enregistrement de duree maximale SUIVI
de sa transcription — sinon on remplacerait un halo fige par un halo qui s'evapore
pendant que Zonza travaille. validate_config refuse desormais une valeur trop courte
(210 s pour 120 s d'enregistrement + 30 s de marge minimale).

Prouve en conditions reelles, limite abaissee a 3 s : visible a 1,5 s (pas de
fermeture prematuree), fermee a 4 s et 5,5 s.

60 tests passent.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 01:48:07 +02:00
58ed0d9e6c Attend le relachement des touches avant de coller
Deux dictees ont ete transcrites correctement puis n'ont jamais atteint la zone de
saisie, sans la moindre erreur : inject_text avait bien envoye ses touches. Cause :
la hotkey Cmd+Ctrl+D etait encore enfoncee quand Zonza a simule Cmd+V. Le systeme a
recu Cmd+Ctrl+V, que l'application cible ignore. Le code croyait avoir reussi.

inject_text patiente donc jusqu'a ce qu'aucun modificateur physique ne soit enfonce
(drapeaux Quartz), au plus 2 s. Au-dela, il colle quand meme : mieux vaut un collage
douteux qu'une transcription perdue. Le delai du presse-papier passe de 0,05 a 0,12 s,
0,05 etant juste.

Et surtout, le collage se TRACE desormais ("[collage] ok" ou l'avertissement) : sans
cela, un echec futur resterait invisible dans le log, comme celui-ci l'a ete.

L'attente est une unite pure et bornee (core.attendre, horloge et sommeil injectables).
Detecteur verifie en conditions reelles : False au repos, retour immediat.

55 tests passent.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 01:42:44 +02:00
f8c30e0402 Overlay reduit d'un quart, et sa geometrie devient proportionnelle
Barre 440x52 -> 330x40. Les proportions internes (bouton stop, micro, marges,
ecarts) etaient en dur dans le dessin : les laisser telles quelles aurait donne
une grosse pastille dans une barre retrecie. Elles derivent desormais de la
hauteur de la barre via core.bar_metrics, donc une seule valeur commande toute
l'echelle — diviser bar_height par deux divise tout par deux (teste).

Rendu verifie par capture d'ecran apres reduction.

50 tests passent.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 00:49:38 +02:00
55c860c5b9 L'overlay devient une barre de dictee au lieu d'un cercle
Reprend le design demande par Ralph, d'apres une capture : barre sombre
arrondie posee en bas de l'ecran, et dedans, de gauche a droite, un bouton stop
rond rouge-orange a carre blanc, une forme d'onde en barres verticales dont la
traine retombe en pointilles, une icone de micro. Au-dessus, une bulle sombre a
pointe.

La forme d'onde demandait un HISTORIQUE de niveaux, la ou l'ancien cercle ne
lisait que le niveau courant : push_level et bar_heights sont ajoutes a
audio_level.py comme unites pures (le plus recent a gauche, les positions vides
ou silencieuses retombent sur un plancher — c'est lui qui donne les pointilles).

La bulle ne peut pas afficher le texte en direct comme la reference : Zonza
transcrit APRES l'arret, il n'y a pas de flux continu. Elle porte donc l'etape
en cours, et la fenetre reste affichee jusqu'au collage au lieu de disparaitre
pendant les secondes de calcul — l'ecran ne se vide plus sans explication.

Rendu verifie par capture d'ecran, pas seulement par les tests : le micro a ete
redessine apres coup (il sortait en tache blanche) et une marge basse ajoutee,
l'arrondi de la barre etant rogne par le bord de la fenetre.

45 tests passent. Le cdhash du stub est inchange, donc les autorisations
d'Accessibilite survivent a cette mise a jour (verifie : accordee = True).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 00:46:56 +02:00
f1cff4239d Whisper recoit le vocabulaire metier en amorce
Sans contexte, le modele rendait « Playwright » en « PlayWreck », « iCloud » en
« Auriclaw », « Supabase » en « Supabass », « Vercel » en « Versell » : 4 termes
sur 5 faux, mesure sur audio reel. Avec l'amorce (initial_prompt), les 5 sont
corrects, sans changer de modele ni ralentir (1,3 s).

Passer a large-v3-turbo a ete teste et ecarte : PIRE sur le meme echantillon
(« commit sur Gitea » -> « commis sur JTA », « Stripe » -> « Trip »), pour 1,5 Go
de plus. C'est l'amorce qui paie, pas la taille du modele.

VOCABULAIRE est une simple liste a completer dans core.py. Whisper ne lit que
~224 tokens d'amorce et tronque le reste EN SILENCE : la longueur est donc
bornee explicitement, pour qu'un ajout de termes ne soit jamais sans effet a
l'insu de celui qui l'ecrit (47 termes = 416 caracteres sur 800).

34 tests passent (27 + 7 nouveaux).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 00:28:52 +02:00
3ad274a774 Zonza ne se lance plus qu'une fois a la fois
Deux bundles portant l'identifiant cloud.mrtechlab.zonza etaient enregistres
aupres de LaunchServices : /Applications/Zonza.app et un fantome laisse dans la
Corbeille le 13 juin, dont le stub visait l'ancien chemin du depot — valide
jusqu'a aujourd'hui. Les deux etaient donc lancables simultanement. Chaque
instance chargeait son propre modele MLX-Whisper medium et captait la MEME
hotkey globale : un seul appui declenchait deux transcriptions, la machine
saturait.

Le fantome est desenregistre, mais la classe de bug revient au moindre bundle
egare. D'ou un verrou exclusif (flock non bloquant) pris au demarrage : la
seconde instance renonce et sort. Le noyau libere le verrou meme apres un
plantage, donc pas d'orphelin.

Prouve avec le vrai binaire : 2e lancement direct -> "[garde] une autre instance
tourne deja", 1 seul process ; et controle negatif, seule elle demarre bien.

27 tests passent (22 + 5 nouveaux).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 00:25:05 +02:00
8a9a6de98c feat: demande d'accessibilité native au premier lancement
AXIsProcessTrustedWithOptions(prompt) : macOS affiche sa popup officielle
et crée l'entrée TCC correctement (l'ajout manuel via « + » ne prenait pas).
Diag de l'état de confiance dans le log.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 01:03:09 +02:00
2236f2d11f fix: icône barre de menu sur Tahoe — stub libpython + abandon de rumps
Sur macOS Tahoe (26.5), le NSStatusItem n'est jamais placé (fenêtre h=0) si :
1. l'exécutable du processus n'appartient pas au bundle lancé (le python
   framework se ré-exécute → identité dépareillée) → stub C qui dlopen
   libpython et exécute app.py DANS le processus du bundle ;
2. l'item est créé par rumps (cause interne non isolée, l'API native
   fonctionne) → app.py réécrit en pyobjc pur (NSStatusItem + NSMenu).

Le stub transmet argv à python quand il y en a (workers multiprocessing
de MLX) — sinon bombe à fork (9 instances observées). PYTHONUNBUFFERED
pour que les print atteignent ~/Library/Logs/Zonza.log. Auto-diagnostic
du placement de l'icône au démarrage. rumps retiré des dépendances.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 00:54:44 +02:00
2b0d81796b fix: icône de barre de menu absente sur macOS Tahoe
setActivationPolicy_(Accessory) appelé avant rumps.run() empêche la
création du NSStatusItem sur Tahoe (vérifié par test A/B). Retiré :
LSUIElement dans l'Info.plist suffit pour masquer l'icône Dock.
Le lanceur redirige aussi stdout/stderr vers ~/Library/Logs/Zonza.log.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 00:14:15 +02:00
22080eb997 Zonza : dictée vocale locale macOS (MLX-Whisper + cercle pulsant)
Reconstruction propre de l'ancien projet Dictée. Bundle id neuf
(cloud.mrtechlab.zonza), chemin de build unique vers /Applications
(plus jamais de builds /tmp enregistrés dans LaunchServices).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 23:57:59 +02:00