diff --git a/.github/workflows/mac-build.yml b/.github/workflows/mac-build.yml
index 390047a..5386ae3 100644
--- a/.github/workflows/mac-build.yml
+++ b/.github/workflows/mac-build.yml
@@ -17,7 +17,7 @@ jobs:
run: |
mkdir -p dist
CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 \
- go build -trimpath -ldflags="-s -w" -o dist/ajean-darwin-arm64 ./cmd/ajean
+ go build -trimpath -ldflags="-s -w" -o dist/ajean-macos-arm ./cmd/ajean
mkdir -p /tmp/ajean.iconset
sips -s format png 'cmd/ajean/icon.ico' --out /tmp/icon.png >/dev/null 2>&1 || true
for s in 16 32 128 256 512; do
@@ -26,7 +26,7 @@ jobs:
iconutil -c icns /tmp/ajean.iconset -o /tmp/ajean.icns >/dev/null 2>&1 || true
app="dist/AJEAN.app"
mkdir -p "$app/Contents/MacOS" "$app/Contents/Resources"
- cp dist/ajean-darwin-arm64 "$app/Contents/MacOS/ajean"
+ cp dist/ajean-macos-arm "$app/Contents/MacOS/ajean"
chmod +x "$app/Contents/MacOS/ajean"
cp /tmp/ajean.icns "$app/Contents/Resources/ajean.icns" 2>/dev/null || true
printf '%s\n' \
@@ -44,9 +44,9 @@ jobs:
'NSHighResolutionCapable' \
'' > "$app/Contents/Info.plist"
codesign --force --deep -s - "$app" || true
- (cd dist && zip -qry AJEAN-macos-arm64.zip AJEAN.app && rm -rf AJEAN.app)
+ (cd dist && zip -qry AJEAN-macos-arm.zip AJEAN.app && rm -rf AJEAN.app)
ls -l dist
- uses: actions/upload-artifact@v4
with:
- name: AJEAN-macos-arm64
- path: dist/AJEAN-macos-arm64.zip
+ name: AJEAN-macos-arm
+ path: dist/AJEAN-macos-arm.zip
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 5635688..1e76fe5 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -29,11 +29,11 @@ jobs:
mkdir -p dist
# arm64 = natif ; amd64 = cross avec le SDK universel (-arch x86_64).
CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 \
- go build -trimpath -ldflags="-s -w" -o dist/ajean-darwin-arm64 ./cmd/ajean
+ go build -trimpath -ldflags="-s -w" -o dist/ajean-macos-arm ./cmd/ajean
CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 \
CGO_CFLAGS="-arch x86_64" CGO_LDFLAGS="-arch x86_64" \
- go build -trimpath -ldflags="-s -w" -o dist/ajean-darwin-amd64 ./cmd/ajean
- file dist/ajean-darwin-*
+ go build -trimpath -ldflags="-s -w" -o dist/ajean-macos ./cmd/ajean
+ file dist/ajean-macos*
- name: bundles AJEAN.app
run: |
# Un binaire nu double-cliqué ouvrirait le Terminal. On publie donc
@@ -51,10 +51,10 @@ jobs:
done
iconutil -c icns /tmp/ajean.iconset -o /tmp/ajean.icns
v="${GITHUB_REF_NAME#v}"
- for arch in amd64 arm64; do
- app="dist/mac-$arch/AJEAN.app"
+ for bin in ajean-macos ajean-macos-arm; do
+ app="dist/bundle-$bin/AJEAN.app"
mkdir -p "$app/Contents/MacOS" "$app/Contents/Resources"
- cp "dist/ajean-darwin-$arch" "$app/Contents/MacOS/ajean"
+ cp "dist/$bin" "$app/Contents/MacOS/ajean"
chmod +x "$app/Contents/MacOS/ajean"
cp /tmp/ajean.icns "$app/Contents/Resources/ajean.icns" 2>/dev/null || true
printf '%s\n' \
@@ -76,12 +76,8 @@ jobs:
# Signature ad-hoc : sans elle, macOS refuse purement et simplement
# de lancer un binaire arm64 non signé (pas juste un avertissement).
codesign --force --deep -s - "$app" || true
- (cd "dist/mac-$arch" && zip -qry "../AJEAN-macos-$arch.zip" AJEAN.app)
- # Nom hérité conservé : les liens de téléchargement déjà publiés
- # (site, mails, messages) pointent dessus et doivent continuer de
- # fonctionner. Même contenu, deux noms.
- cp "dist/AJEAN-macos-$arch.zip" "dist/AJEAN-macos-$arch.zip"
- rm -rf "dist/mac-$arch"
+ (cd "dist/bundle-$bin" && zip -qry "../AJEAN-${bin#ajean-}.zip" AJEAN.app)
+ rm -rf "dist/bundle-$bin"
done
ls -l dist
- uses: actions/upload-artifact@v4
@@ -100,13 +96,20 @@ jobs:
- name: build Linux + Windows
run: |
mkdir -p dist
- for t in linux/amd64 linux/arm64 windows/amd64 windows/arm64; do
- os=${t%/*}; arch=${t#*/}; ext=""; ldflags="-s -w"
+ # Noms d'asset : ajean-[-arm][.exe]. Volontairement lisibles, et
+ # volontairement DIFFÉRENTS du schéma ajean-- des 0.7 :
+ # leur mise à jour automatique ne trouve alors aucun asset et échoue
+ # sans rien remplacer, au lieu d'installer un binaire 0.8 sur une
+ # machine encore agencée en 0.7 (voir updateAssetName, sys_update.go).
+ for t in linux/amd64:ajean-linux linux/arm64:ajean-linux-arm \
+ windows/amd64:ajean-windows.exe windows/arm64:ajean-windows-arm.exe; do
+ target=${t%%:*}; name=${t#*:}
+ os=${target%/*}; arch=${target#*/}; ldflags="-s -w"
# Windows : sous-système GUI → aucune console noire au double-clic
# (l'app se rattache à la console du terminal parent si lancée en CLI).
- [ "$os" = windows ] && { ext=".exe"; ldflags="$ldflags -H=windowsgui"; }
+ [ "$os" = windows ] && ldflags="$ldflags -H=windowsgui"
GOOS=$os GOARCH=$arch CGO_ENABLED=0 \
- go build -trimpath -ldflags="$ldflags" -o "dist/ajean-$os-$arch$ext" ./cmd/ajean
+ go build -trimpath -ldflags="$ldflags" -o "dist/$name" ./cmd/ajean
done
- uses: actions/download-artifact@v4
with:
@@ -114,7 +117,7 @@ jobs:
path: dist
- name: SHA256SUMS
run: |
- chmod +x dist/ajean-darwin-*
+ chmod +x dist/ajean-macos*
(cd dist && sha256sum ajean-* *.zip > SHA256SUMS)
ls -l dist && cat dist/SHA256SUMS
- name: publier la release
diff --git a/README.md b/README.md
index a475509..9513c87 100644
--- a/README.md
+++ b/README.md
@@ -41,12 +41,12 @@ Aucune dépendance à l'exécution, aucun flag CMake à retenir, aucun conteneur
### 1. Le binaire
```bash
-curl -L -o ajean https://github.com/nathaninline/ajean/releases/latest/download/ajean-linux-amd64
+curl -L -o ajean https://github.com/nathaninline/ajean/releases/latest/download/ajean-linux
chmod +x ajean
sudo mv ajean /usr/local/bin/ajean
```
-(Autres cibles sur la page [Releases](../../releases) : Linux, macOS et Windows, en amd64 et arm64.)
+Les binaires publiés : `ajean-linux`, `ajean-linux-arm`, `ajean-macos`, `ajean-macos-arm`, `ajean-windows.exe`, `ajean-windows-arm.exe` — le suffixe `-arm` désigne l'arm64, l'absence de suffixe l'x86-64.
### 2. Installation et compilation du moteur
@@ -231,11 +231,11 @@ ajean status
## macOS
-La page [Releases](../../releases) publie `AJEAN-macos-arm64.zip` / `AJEAN-macos-amd64.zip`, un bundle **`AJEAN.app`**. Dézipper, glisser dans *Applications*, ouvrir : l'interface démarre sur `http://localhost:8090`, s'ouvre dans le navigateur, et l'icône se pose dans la **barre de menus**. Pas de fenêtre de Terminal, pas d'icône dans le Dock.
+La page [Releases](../../releases) publie `AJEAN-macos-arm.zip` (Apple Silicon) et `AJEAN-macos.zip` (Intel), un bundle **`AJEAN.app`**. Dézipper, glisser dans *Applications*, ouvrir : l'interface démarre sur `http://localhost:8090`, s'ouvre dans le navigateur, et l'icône se pose dans la **barre de menus**. Pas de fenêtre de Terminal, pas d'icône dans le Dock.
L'application n'est signée qu'en ad-hoc : au premier lancement, faire **clic droit → Ouvrir**.
-Pour un usage en ligne de commande, prendre le binaire nu `ajean-darwin-arm64` : hors bundle, il conserve son comportement CLI. Les services passent par **launchd**.
+Pour un usage en ligne de commande, prendre le binaire nu `ajean-macos-arm` : hors bundle, il conserve son comportement CLI. Les services passent par **launchd**.
## Accès distant via ajean.link
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 9478d9a..f10f655 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,6 +1,6 @@
Le renommage est terminé. Plus rien ne s'appelle jean : ni le binaire, ni les services, ni les variables, ni les dossiers. Et le dossier de données, qui s'était couvert d'une douzaine de petits fichiers d'état, tient désormais dans six dossiers et une base.
-**La reprise d'une installation 0.7 tient en une commande : `sudo ajean install`.** Il déplace les dossiers, reprend les réglages en base, désactive les anciens services et installe les nouveaux. Rien n'est supprimé : presets, mémoire et modèles sont déplacés, les anciens fichiers d'état rangés dans `avant-0.8/`. C'est le seul code de compatibilité de la version, isolé dans un fichier prévu pour être supprimé.
+**Une installation 0.7 doit être RÉINSTALLÉE : ne passez pas par le bouton de mise à jour.** Téléchargez le binaire 0.8, puis `sudo ajean install` — il fait la reprise complète. Il déplace les dossiers, reprend les réglages en base, désactive les anciens services et installe les nouveaux. Rien n'est supprimé : presets, mémoire et modèles sont déplacés, les anciens fichiers d'état rangés dans `avant-0.8/`. C'est le seul code de compatibilité de la version, isolé dans un fichier prévu pour être supprimé.
## Une base à la place des fichiers d'état
@@ -32,4 +32,6 @@ Tout le code écrit pour ménager les installations « jean » : la migration du
La CLI perd ses alias hérités — `skills`, `machine`, `tools`, `web-access`, `mem`, `upgrade`, `self-update`, `paths`, `llama` — et son aide est réorganisée autour des deux services. Chaque commande a désormais un seul nom. `app` quitte l'aide : c'est le comportement du double-clic, qu'on n'atteint pas en tapant son nom.
-Les releases ne publient plus qu'un jeu de binaires, `ajean--`. La double publication qui accompagnait la transition n'a plus d'objet.
+Les releases ne publient plus qu'un jeu de binaires, et sous des noms lisibles : `ajean-linux`, `ajean-linux-arm`, `ajean-macos`, `ajean-macos-arm`, `ajean-windows.exe`, `ajean-windows-arm.exe`. La double publication qui accompagnait la transition n'a plus d'objet.
+
+Ce changement de noms n'est pas cosmétique. Les versions 0.7 cherchent leur mise à jour sous la forme `ajean--` : ne trouvant aucun asset qui corresponde, leur bouton « mettre à jour » échoue proprement, sans rien remplacer. C'est délibéré. Laisser la 0.7 installer ce binaire aurait remplacé l'exécutable sans migrer les données ni les unités : le service de lien serait reparti en boucle d'échec sur une sous-commande disparue, et le moteur n'aurait plus trouvé sa configuration — une machine à réparer en SSH après un clic dans un navigateur.
diff --git a/internal/ajean/sys_update.go b/internal/ajean/sys_update.go
index a9428bf..095c76b 100644
--- a/internal/ajean/sys_update.go
+++ b/internal/ajean/sys_update.go
@@ -35,13 +35,33 @@ type ghRelease struct {
}
// updateAssetName est le nom de l'asset de release pour la plateforme courante :
-// ajean--[.exe]. Un seul nom publié, un seul nom cherché.
-func updateAssetName() string {
- suffix := runtime.GOOS + "-" + runtime.GOARCH
- if runtime.GOOS == "windows" {
- suffix += ".exe"
+// ajean-linux, ajean-linux-arm, ajean-macos, ajean-macos-arm, ajean-windows.exe,
+// ajean-windows-arm.exe. Un seul nom publié, un seul nom cherché.
+//
+// Ces noms sont volontairement lisibles — « macos » plutôt que « darwin », pas
+// de « amd64 » pour le cas courant — et volontairement DIFFÉRENTS du schéma
+// ajean-- qu'utilisaient les versions 0.7 : leur mise à jour
+// automatique ne trouve donc aucun asset et échoue sans rien remplacer, au lieu
+// d'installer un binaire 0.8 sur une machine encore agencée en 0.7 — ce qui
+// laissait le service de lien en boucle d'échec. La 0.7 se met à jour à la main,
+// par réinstallation.
+func updateAssetName() string { return assetNameFor(runtime.GOOS, runtime.GOARCH) }
+
+// assetNameFor est séparée pour être vérifiable sur les six plateformes, et pas
+// seulement sur celle qui exécute les tests.
+func assetNameFor(goos, goarch string) string {
+ name := "ajean-" + map[string]string{
+ "darwin": "macos",
+ "linux": "linux",
+ "windows": "windows",
+ }[goos]
+ if goarch == "arm64" {
+ name += "-arm"
}
- return "ajean-" + suffix
+ if goos == "windows" {
+ name += ".exe"
+ }
+ return name
}
// pickAsset trouve dans la release l'asset de cette plateforme. Renvoie son nom
diff --git a/internal/ajean/sys_update_asset_test.go b/internal/ajean/sys_update_asset_test.go
index 8dbdd59..ce87a7a 100644
--- a/internal/ajean/sys_update_asset_test.go
+++ b/internal/ajean/sys_update_asset_test.go
@@ -1,6 +1,9 @@
package ajean
-import "testing"
+import (
+ "runtime"
+ "testing"
+)
// relWith fabrique une release ne contenant que les assets nommés.
func relWith(names ...string) *ghRelease {
@@ -34,3 +37,32 @@ func TestPickAssetSansCorrespondance(t *testing.T) {
t.Fatalf("URL inattendue: %q", url)
}
}
+
+// Le schéma de nommage ne doit PAS coïncider avec ajean-- : c'est
+// ce qui empêche la mise à jour automatique d'une 0.7 de s'installer sur une
+// machine encore agencée en 0.7.
+func TestNomDAssetDistinctDuSchema07(t *testing.T) {
+ legacy := "ajean-" + runtime.GOOS + "-" + runtime.GOARCH
+ if runtime.GOOS == "windows" {
+ legacy += ".exe"
+ }
+ if got := updateAssetName(); got == legacy {
+ t.Fatalf("le nom %q est celui que cherche la 0.7 — sa mise à jour casserait l'installation", got)
+ }
+}
+
+// Les six noms publiés par la release, vérifiés un par un.
+func TestNomsDAssetParPlateforme(t *testing.T) {
+ for _, c := range []struct{ goos, goarch, want string }{
+ {"linux", "amd64", "ajean-linux"},
+ {"linux", "arm64", "ajean-linux-arm"},
+ {"darwin", "amd64", "ajean-macos"},
+ {"darwin", "arm64", "ajean-macos-arm"},
+ {"windows", "amd64", "ajean-windows.exe"},
+ {"windows", "arm64", "ajean-windows-arm.exe"},
+ } {
+ if got := assetNameFor(c.goos, c.goarch); got != c.want {
+ t.Errorf("%s/%s → %q, attendu %q", c.goos, c.goarch, got, c.want)
+ }
+ }
+}