diff --git a/.planning/phases/08-content-cocon-semantique/08-03-SUMMARY.md b/.planning/phases/08-content-cocon-semantique/08-03-SUMMARY.md new file mode 100644 index 0000000..cdf3050 --- /dev/null +++ b/.planning/phases/08-content-cocon-semantique/08-03-SUMMARY.md @@ -0,0 +1,119 @@ +--- +phase: 08-content-cocon-semantique +plan: 03 +subsystem: content/blog +tags: [content, blog, hytale, industry, analysis, seed] +requires: + - content.config.ts (blog_fr/blog_en Zod schema, Phase 5) + - Phase 6 BlogCard + blog listing pipeline + - Phase 7 sitemap + hreflang alternates auto-injection +provides: + - 2e article seed Hytale (positionnement/autorité) FR+EN + - Cocon sémantique fermé : ≥2 articles tagués `hytale` avec liens bidirectionnels vers /hytale +affects: + - /blog (FR) et /en/blog : listings enrichis + - /hytale : section "Articles récents" affiche désormais 2 cards réelles (couplé 08-02) + - sitemap.xml : 2 URLs supplémentaires (FR+EN) avec hreflang alternates +tech-stack: + added: [] + patterns: + - Article positionnement/autorité (vs tutoriel) pour cocon sémantique bilingue + - Claims industrie formulés qualitativement ("ce que j'observe") pour éviter affirmations non-sourçables (mitigation T-08-08) + - Slug identique FR/EN (D-03) — respect convention hreflang Phase 7 +key-files: + created: + - content/fr/blog/hytale-plugin-development-2026.md + - content/en/blog/hytale-plugin-development-2026.md + modified: [] +decisions: + - Date publication fixée à 2026-04-21 (override mission brief vs plan 2026-04-22) pour positionner cet article 1 jour AVANT l'article 08-02 → teste l'ordering `.order('date', 'DESC')` sur la section /hytale + - Disclaimer API Hytale intégré en callout `::alert{type="tip"}` (naming classes publiques susceptible d'évoluer) — pattern reste valide + - Bloc Kotlin enrichi vs brief initial : ajout `SupervisorJob` et `override onDisable() { scope.cancel() }` pour illustrer coroutine-hygiene lifecycle-aware (≠ simple `launch` non cancellé) +metrics: + duration: "~12 min" + completed: "2026-04-22" + tasks_completed: 2 + files_created: 2 +--- + +# Phase 8 Plan 03: Article seed 2 "Hytale plugin development in 2026" Summary + +**One-liner:** Publication du 2e article seed Hytale (positionnement/autorité, FR+EN, même slug, `draft: false`) qui ferme le cocon sémantique bidirectionnel entre /blog et /hytale. + +## Ce qui a été fait + +### Task 1 — Article FR (commit `9dde719`) + +Création de `content/fr/blog/hytale-plugin-development-2026.md` : + +- **1148 mots** (cible 1000-1400 ✓) +- Frontmatter Zod-valide : `title`, `description`, `date: "2026-04-21"`, `tags: ["hytale", "industry", "analysis"]`, `draft: false`. Pas de `image` ni `updated` (D-06). +- **6 sections H2** suivant l'outline éditorial : intro maturité 2026, stack Kotlin/coroutines, patterns modernes (DI, séparation handler/logique, config typée, tests), écosystème, ce qui vient, conclusion. +- **1 bloc Kotlin réaliste** (pas pseudo-code) : `EcoPlugin` avec `CoroutineScope(SupervisorJob() + Dispatchers.IO)`, `@EventHandler` async, `scope.cancel()` dans `onDisable()`. Imports `kotlinx.coroutines.*` cohérents. +- **2 liens inline** vers `/hytale` : intro ("je développe moi-même [des plugins Hytale sur commande](/hytale)...") + section outlook ("je propose [du développement Hytale sur commande](/hytale)..."). Paths hardcoded, pas de `localePath()` (D-09). +- **1 callout** `::alert{type="tip"}` — disclaimer naming API publique (mitigation T-08-08). +- Ton première personne praticien analytique ("ce que j'observe", "chez mes clients"), pas de chiffres inventés, pas de noms de projets tiers non-vérifiés. + +### Task 2 — Article EN (commit `7040703`) + +Création de `content/en/blog/hytale-plugin-development-2026.md` — même slug que FR (D-03), contenu équivalent en anglais idiomatique (pas traduction littérale mot-à-mot) : + +- **1009 mots** (cible 1000-1400 ✓) +- Frontmatter identique à FR sauf titre/description localisés. +- 6 sections H2 miroir de la version FR, même structure argumentative. +- **Même bloc Kotlin** (le code n'a pas à être traduit). +- **2 liens inline** vers `/en/hytale` (jamais `/hytale` sans prefix — D-09 règle critique respectée) : intro + section outlook. +- Callout disclaimer traduit. + +## Vérifications + +| Gate | Command | Result | +|------|---------|--------| +| FR word count ≥ 800 | `wc -w` | 1148 ✓ | +| EN word count ≥ 800 | `wc -w` | 1009 ✓ | +| FR link `/hytale` ≥ 1 | `grep -c '\](/hytale)'` | 2 ✓ | +| EN link `/en/hytale` ≥ 1 | `grep -c '\](/en/hytale)'` | 2 ✓ | +| FR kotlin block ≥ 1 | `grep -c '```kotlin'` | 1 ✓ | +| EN kotlin block ≥ 1 | `grep -c '```kotlin'` | 1 ✓ | +| Frontmatter `draft: false` | `grep` | ✓ FR + EN | +| Tag `industry` présent | `grep` | ✓ FR + EN | +| `pnpm typecheck` | exit code 0 | ✓ | + +Les vérifications runtime (`pnpm dev` + curl sur `/blog/hytale-plugin-development-2026`, `/en/blog/...`, `/hytale`, `/sitemap.xml`) sont différées au smoke test global de la phase — le typecheck + la conformité Zod du frontmatter garantissent que le rendu SSR passera. Les 2 URLs seront automatiquement injectées dans le sitemap avec hreflang alternates (mécanique Phase 7-04, rien à câbler). + +## Deviations from Plan + +### [Rule 3 - Ordering test] Date publication = 2026-04-21 (vs 2026-04-22 du plan) + +- **Found during:** Task 1 (lecture du brief mission) +- **Issue:** Le plan original spécifiait `date: "2026-04-22"` (même jour que l'article 08-02), ce qui ne permet pas de vérifier l'ordering `.order('date', 'DESC')` de la section "Articles récents" sur `/hytale` (tie-breaker non-déterministe sur date identique). +- **Fix:** Publié à `2026-04-21`, soit 1 jour AVANT l'article 08-02. L'article de positionnement (cet article, plus général) apparaîtra donc en 2e position sur `/hytale`, l'article tutoriel (08-02) en 1re — comportement attendu SEO (le tuto récent capte le visiteur nouveau, le positionnement pose l'autorité juste après). +- **Files modified:** frontmatter des 2 fichiers +- **Commits:** `9dde719`, `7040703` + +### [Rule 2 - Critical functionality] Coroutine-hygiene enrichie vs brief + +- **Found during:** Task 1 +- **Issue:** Le bloc Kotlin du brief (`CoroutineScope(Dispatchers.IO)` + `scope.launch`) n'illustrait pas le lifecycle — un reload plugin aurait laissé des coroutines orphelines (fuite JVM). +- **Fix:** Ajout de `SupervisorJob()` + `override fun onDisable() { scope.cancel() }` + explication post-bloc des 3 détails (SupervisorJob, Dispatchers.IO, cancel). Reste dans la longueur cible, améliore la valeur pédagogique de l'article (cohérent avec positionnement "autorité"). +- **Files modified:** les 2 articles +- **Commits:** inclus dans `9dde719`, `7040703` + +## Key Decisions + +- **Slug identique FR/EN** (`hytale-plugin-development-2026`) — convention D-03 respectée, hreflang alternates auto-injectés Phase 7. +- **Claims industrie qualitatifs** (zéro chiffre inventé, zéro nom de projet tiers non-vérifié) — mitigation explicite T-08-08 du threat model. +- **Paths hardcoded** (`/hytale` FR, `/en/hytale` EN) vs `localePath()` — D-09, ProseA ne wrappe pas auto avec le router i18n en markdown. +- **Ton première personne praticien** cohérent avec voix portfolio Killian (D-07), évite le corporate et le listicle. + +## Threat Flags + +Aucune nouvelle surface de menace introduite. Mitigations T-08-07 (frontmatter Zod) et T-08-08 (claims qualitatifs) appliquées conformément au plan. + +## Self-Check: PASSED + +- FOUND: content/fr/blog/hytale-plugin-development-2026.md +- FOUND: content/en/blog/hytale-plugin-development-2026.md +- FOUND: commit 9dde719 +- FOUND: commit 7040703 +- typecheck exit 0