<?xml version="1.0"?>
<rss version="2.0"
     xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>JBake</title>
        <link >https://cheroliv.com/</link>
        <atom:link href="https://cheroliv.com/feed.xml" rel="self" type="application/rss+xml" />
        <description>JBake Bootstrap Template</description>
        <language>en-gb</language>
        <pubDate>Fri, 25 Sep 2026 01:36:38 +0000</pubDate>
        <lastBuildDate>Fri, 25 Sep 2026 01:36:38 +0000</lastBuildDate>

        <item>
            <title>HyperFrames-Gradle : Transformer l&#39;AsciiDoc en Vidéo MP4</title>
            <link >https://cheroliv.com/blog/2026/0126_hyperframes_asciidoc_video_post.html</link>
            <pubDate>Sun, 31 May 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0126_hyperframes_asciidoc_video_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_trou_dans_le_pipeline_vidéo&amp;quot;&amp;gt;Le Trou dans le Pipeline Vidéo&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_hyperframes_le_moteur&amp;quot;&amp;gt;HyperFrames : Le Moteur&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_larchitecture_du_plugin&amp;quot;&amp;gt;L&amp;amp;#8217;Architecture du Plugin&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_pipeline_en_quatre_étapes&amp;quot;&amp;gt;Le Pipeline en Quatre Étapes&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_dsl_asciidoc&amp;quot;&amp;gt;Le DSL AsciiDoc&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_bridge_node_js&amp;quot;&amp;gt;Le Bridge Node.js&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_deux_plugins_vidéo_deux_usages&amp;quot;&amp;gt;Deux Plugins Vidéo, Deux Usages&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_les_6_epics_de_la_roadmap&amp;quot;&amp;gt;Les 6 EPICs de la Roadmap&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pourquoi_ça_marche&amp;quot;&amp;gt;Pourquoi Ça Marche&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_conclusion_le_chaînon_manquant&amp;quot;&amp;gt;Conclusion : Le Chaînon Manquant&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_références&amp;quot;&amp;gt;Références&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 8 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Il y a deux semaines, j&amp;amp;#8217;ai lancé &amp;lt;code&amp;gt;capsule-gradle&amp;lt;/code&amp;gt; — un plugin qui transforme un deck reveal.js en capsule vidéo WebM avec TTS. Aujourd&amp;amp;#8217;hui, j&amp;amp;#8217;ajoute un nouveau plugin : &amp;lt;code&amp;gt;hyperframes-gradle&amp;lt;/code&amp;gt;. Il fait quelque chose que capsule-gradle ne fait pas : transformer l&amp;amp;#8217;AsciiDoc &amp;lt;strong&amp;gt;directement&amp;lt;/strong&amp;gt; en vidéo MP4, sans passer par reveal.js.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Voici pourquoi ce plugin existe, comment il s&amp;amp;#8217;articule avec l&amp;amp;#8217;existant, et ce que le moteur HyperFrames de HeyGen apporte au pipeline de production de contenu.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_trou_dans_le_pipeline_vidéo&amp;quot;&amp;gt;Le Trou dans le Pipeline Vidéo&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mon pipeline documentaire produit deux types de vidéos :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Capsule de révision&amp;lt;/strong&amp;gt; (capsule-gradle) — un deck reveal.js capturé en WebM avec&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;narration TTS. Parfait pour revoir un module.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Slides d&amp;amp;#8217;animation&amp;lt;/strong&amp;gt; (slider-gradle) — un deck reveal.js HTML interactif pour&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;le formateur en présentiel.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mais il manque un troisième format : la &amp;lt;strong&amp;gt;vidéo standalone&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5555%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5555%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5555%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5555%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5555%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5555%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5555%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5555%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5555%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5555%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5555%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5555%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5555%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5555%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5555%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5555%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5555%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5.5565%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Use case&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Solution actuelle&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Manque&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Slides formateur&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;slider-gradle → reveal.js&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Capsule révision&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;capsule-gradle → WebM&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Vidéo teasing&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Aucune&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;❌&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Démo technique animée&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Aucune&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;❌&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Doc-to-video&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Aucune&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;❌&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le premier use case est critique : comment générer automatiquement une vidéo de 60 secondes qui présente un projet ou un module, avec animations GSAP, narration TTS, et fond musical — le tout depuis le même fichier AsciiDoc que les slides ?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Capsule-gradle ne peut pas répondre : il lui faut &amp;lt;strong&amp;gt;déjà&amp;lt;/strong&amp;gt; un deck reveal.js. slider-gradle produit bien ce deck, mais il n&amp;amp;#8217;est pas conçu pour le rendu vidéo. Il fallait un pipeline &amp;lt;strong&amp;gt;direct&amp;lt;/strong&amp;gt; : AsciiDoc → vidéo.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_hyperframes_le_moteur&amp;quot;&amp;gt;HyperFrames : Le Moteur&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ai découvert &amp;lt;a href=&amp;quot;https://github.com/heygen-com/hyperframes&amp;quot;&amp;gt;HyperFrames&amp;lt;/a&amp;gt; il y a quelques jours. C&amp;amp;#8217;est un framework open-source (Apache 2.0) créé par HeyGen, la licorne de la vidéo IA. 22 700 étoiles sur GitHub. Le pitch tient en une phrase :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;quoteblock&amp;quot;&amp;gt;
&amp;lt;blockquote&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Write HTML. Render video. Built for agents.&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/blockquote&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le principe : vous écrivez du HTML avec des &amp;lt;code&amp;gt;data-*&amp;lt;/code&amp;gt; attributes, vous référencez une animation GSAP (ou CSS, Lottie, Three.js…), et le moteur rend le tout en MP4 via Puppeteer (headless Chrome) + FFmpeg. Résultat déterministe : même input, mêmes frames, même vidéo.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html hljs&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;div id=&amp;quot;stage&amp;quot; data-composition-id=&amp;quot;intro&amp;quot; data-start=&amp;quot;0&amp;quot; data-width=&amp;quot;1920&amp;quot; data-height=&amp;quot;1080&amp;quot;&amp;amp;gt;
  &amp;amp;lt;video class=&amp;quot;clip&amp;quot; data-start=&amp;quot;0&amp;quot; data-duration=&amp;quot;6&amp;quot; data-track-index=&amp;quot;0&amp;quot;
         src=&amp;quot;background.mp4&amp;quot; muted playsinline&amp;amp;gt;&amp;amp;lt;/video&amp;amp;gt;

  &amp;amp;lt;h1 id=&amp;quot;title&amp;quot; class=&amp;quot;clip&amp;quot; data-start=&amp;quot;1&amp;quot; data-duration=&amp;quot;4&amp;quot; data-track-index=&amp;quot;1&amp;quot;&amp;amp;gt;
    Formation Docker &amp;amp;amp; Kubernetes
  &amp;amp;lt;/h1&amp;amp;gt;

  &amp;amp;lt;audio data-start=&amp;quot;0&amp;quot; data-duration=&amp;quot;6&amp;quot; data-track-index=&amp;quot;2&amp;quot;
         data-volume=&amp;quot;0.3&amp;quot; src=&amp;quot;music.wav&amp;quot;&amp;amp;gt;&amp;amp;lt;/audio&amp;amp;gt;

  &amp;amp;lt;script src=&amp;quot;https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
  &amp;amp;lt;script&amp;amp;gt;
    const tl = gsap.timeline({ paused: true });
    tl.from(&amp;quot;#title&amp;quot;, { opacity: 0, y: 40, duration: 0.8 }, 1);
    window.__timelines = window.__timelines || {};
    window.__timelines.intro = tl;
  &amp;amp;lt;/script&amp;amp;gt;
&amp;amp;lt;/div&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Qu&amp;amp;#8217;est-ce qui rend HyperFrames différent de Remotion ? Pas de React, pas de bundler, pas de JSX. Du HTML brut que les agents IA savent écrire nativement. C&amp;amp;#8217;est taillé &amp;lt;strong&amp;gt;exactement&amp;lt;/strong&amp;gt; pour mon pipeline : planner-gradle avec deepseek peut générer ce HTML à partir d&amp;amp;#8217;un plan SPG/SPD, et un plugin Gradle peut le convertir en MP4.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_larchitecture_du_plugin&amp;quot;&amp;gt;L&amp;amp;#8217;Architecture du Plugin&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;hyperframes-gradle suit le même pattern que tous mes plugins : le &amp;lt;a href=&amp;quot;0124_architecture_plugin_gradle_racine_consommateur_independant_post.html&amp;quot;&amp;gt;pattern « Plugin Indépendant + Racine Consommateur »&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;hyperframes-gradle/
├── settings.gradle.kts          ← racine consommateur (dogfood)
├── build.gradle.kts              ← 3 lignes : apply plugin hyperframes
├── hyperframes-plugin/           ← BUILD INDÉPENDANT
│   ├── gradlew                    ← son propre wrapper
│   ├── build.gradle.kts           ← java-gradle-plugin
│   ├── src/main/kotlin/education/cccp/hyperframes/
│   │   ├── HyperframesPlugin.kt
│   │   ├── GenerateHyperframesHtmlTask.kt
│   │   ├── RenderHyperframesTask.kt
│   │   └── HyperframesExtension.kt
│   ├── .agents/                   ← gouvernance agent
│   └── doc/
│       └── HYPERFRAMES_ARCHITECTURE.adoc
└── video.yml                      ← configuration dogfood&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_pipeline_en_quatre_étapes&amp;quot;&amp;gt;Le Pipeline en Quatre Étapes&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/pipeline-hyperframes.svg&amp;quot; alt=&amp;quot;pipeline hyperframes&amp;quot; width=&amp;quot;1005&amp;quot; height=&amp;quot;100&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;AsciidoctorJ&amp;lt;/strong&amp;gt; parse l&amp;amp;#8217;AsciiDoc source et extrait les blocs customs&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;[hyperframes-composition]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;[hyperframes-track]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;[hyperframes-animation]&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;GenerateHyperframesHtmlTask&amp;lt;/strong&amp;gt; génère le HTML HyperFrames avec les&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;data-*&amp;lt;/code&amp;gt; attributes correspondants.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;RenderHyperframesTask&amp;lt;/strong&amp;gt; appelle la CLI HyperFrames via &amp;lt;code&amp;gt;ProcessBuilder&amp;lt;/code&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;npx hyperframes render --input index.html --output video.mp4&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le MP4 est déployé dans &amp;lt;code&amp;gt;output/&amp;lt;/code&amp;gt; avec un &amp;lt;code&amp;gt;metadata.json&amp;lt;/code&amp;gt; pour l&amp;amp;#8217;orchestration.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_dsl_asciidoc&amp;quot;&amp;gt;Le DSL AsciiDoc&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La vraie valeur ajoutée du plugin, c&amp;amp;#8217;est le DSL AsciiDoc. L&amp;amp;#8217;utilisateur n&amp;amp;#8217;écrit jamais de HTML. Il annote son document AsciiDoc existant :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;= Formation Docker &amp;amp;amp; Kubernetes
:hyperframes-width: 1920
:hyperframes-height: 1080
:hyperframes-fps: 30

[hyperframes-composition, id=&amp;quot;intro&amp;quot;]
== Introduction

Le titre apparaît avec un fondu GSAP sur fond vidéo.

[hyperframes-track, index=0, start=0, duration=6]
video::assets/background.mp4[muted, playsinline]

[hyperframes-track, index=1, start=1, duration=4]
Formation Docker &amp;amp;amp; Kubernetes

[hyperframes-animation, type=gsap]&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;const tl = gsap.timeline({ paused: true }); tl.from(&amp;quot;#title&amp;quot;, { opacity: 0, y: 40, duration: 0.8 }, 1); window.&amp;lt;em&amp;gt;timelines = window.&amp;lt;/em&amp;gt;timelines || {}; window.__timelines.intro = tl;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Les attributs docinfo (&amp;lt;code&amp;gt;:hyperframes-width:&amp;lt;/code&amp;gt;) configurent les dimensions. Les blocs customs définissent les compositions et les tracks. Le bloc &amp;lt;code&amp;gt;[hyperframes-animation]&amp;lt;/code&amp;gt; contient le code GSAP brut — que l&amp;amp;#8217;agent IA peut générer à partir d&amp;amp;#8217;une description en langage naturel.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_bridge_node_js&amp;quot;&amp;gt;Le Bridge Node.js&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le seul point de friction technique : HyperFrames est en Node.js/TypeScript, et mes plugins sont en Kotlin/JVM. La solution est un &amp;lt;code&amp;gt;ProcessBuilder&amp;lt;/code&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;class RenderHyperframesTask : DefaultTask() {

    @TaskAction
    fun render() {
        val process = ProcessBuilder(
            &amp;quot;npx&amp;quot;, &amp;quot;hyperframes&amp;quot;, &amp;quot;render&amp;quot;,
            &amp;quot;--input&amp;quot;, inputHtml.absolutePath,
            &amp;quot;--output&amp;quot;, outputMp4.absolutePath
        )
            .inheritIO()
            .start()

        val exitCode = process.waitFor()
        require(exitCode == 0) {
            &amp;quot;HyperFrames render failed with exit code $exitCode&amp;quot;
        }
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Zéro couplage code JVM ↔ Node.js. Le contrat est par ligne de commande et fichiers sur disque. C&amp;amp;#8217;est le même pattern que &amp;lt;code&amp;gt;plantuml-gradle&amp;lt;/code&amp;gt; (qui appelle la CLI PlantUML) ou &amp;lt;code&amp;gt;slider-gradle&amp;lt;/code&amp;gt; (qui appelle AsciidoctorJ). Rien de nouveau sous le soleil — juste appliqué à un outil plus récent.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_deux_plugins_vidéo_deux_usages&amp;quot;&amp;gt;Deux Plugins Vidéo, Deux Usages&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.7619%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.762%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;capsule-gradle&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;hyperframes-gradle&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Source&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Deck reveal.js (HTML existant)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;AsciiDoc → HTML HyperFrames&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Use case&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Capsule de révision&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Vidéo standalone explicative&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Nature&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Slides → vidéo&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Document → vidéo&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Rendu&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Playwright Java → WebM&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;HyperFrames CLI → MP4&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Animation&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Transitions reveal.js natives&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;GSAP/CSS data-attributes&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Stack&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;100% JVM (Kotlin)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;JVM + Node.js CLI externe&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ils ne se remplacent pas. Ils se complètent. La chaîne de valeur complète :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;AsciiDoc ──→ slider-gradle ──→ deck reveal.js ──→ capsule-gradle ──→ WebM (capsule révision)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;AsciiDoc ──→ hyperframes-gradle ──→ MP4 (vidéo standalone)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;utilisateur écrit un seul fichier AsciiDoc. slider-gradle produit les slides. capsule-gradle produit la capsule de révision. hyperframes-gradle produit la vidéo de teasing et les démos techniques.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_les_6_epics_de_la_roadmap&amp;quot;&amp;gt;Les 6 EPICs de la Roadmap&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le plugin est structuré en 6 EPICs :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1682%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;EPIC&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Description&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Priorité&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;HF-0&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Bootstrap gouvernance + cadrage architecture&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅ TERMINE&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;HF-1&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Plugin Gradle stub + AsciidoctorJ intégration&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;P0&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;HF-2&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Bridge CLI HyperFrames (ProcessBuilder → npx → MP4)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;P1&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;HF-3&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;DSL AsciiDoc customs (blocs, docinfo, templates)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;P1&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;HF-4&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Intégration runner-gradle (metadata.json)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;P2&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;HF-5&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Templates prêts à l&amp;amp;#8217;emploi (title-card, code-diff, captions)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;P3&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;HF-6&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;CI + publication Maven Central / Gradle Portal&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;P3&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La session 000 (bootstrap) est déjà terminée. La session 001 attaquera HF-1 : le stub du plugin Gradle et l&amp;amp;#8217;intégration AsciidoctorJ.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_pourquoi_ça_marche&amp;quot;&amp;gt;Pourquoi Ça Marche&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Trois raisons :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;HyperFrames est &amp;quot;built for agents&amp;quot;&amp;lt;/strong&amp;gt;. Mon pipeline repose sur des agents IA&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;(planner-gradle + deepseek) qui génèrent du contenu. HyperFrames accepte du HTML brut — le format que les LLMs maîtrisent le mieux. Pas de React, pas de JSX, pas de courbe d&amp;amp;#8217;apprentissage pour l&amp;amp;#8217;agent.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Le DSL AsciiDoc est naturel&amp;lt;/strong&amp;gt;. Tout mon écosystème parle AsciiDoc.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;slider-gradle, codex-gradle, training-gradle — tous consomment du &amp;lt;code&amp;gt;.adoc&amp;lt;/code&amp;gt;. Ajouter des blocs customs &amp;lt;code&amp;gt;[hyperframes-composition]&amp;lt;/code&amp;gt; est une extension logique, pas une rupture.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Le bridge Node.js est un pattern éprouvé&amp;lt;/strong&amp;gt;. ProcessBuilder hors de la JVM,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;c&amp;amp;#8217;est ce que je fais déjà pour PlantUML, Graphviz, Piper. Ajouter HyperFrames ne change rien à l&amp;amp;#8217;architecture — c&amp;amp;#8217;est un outil externe de plus, piloté depuis Gradle.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;ℹ️&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La vraie force du pattern, c&amp;amp;#8217;est qu&amp;amp;#8217;il n&amp;amp;#8217;y a &amp;lt;strong&amp;gt;aucune&amp;lt;/strong&amp;gt; dépendance npm dans le build Gradle. Le plugin n&amp;amp;#8217;importe pas de code Node.js. Il exécute une commande shell. Si HyperFrames évolue ou casse, le plugin n&amp;amp;#8217;est pas couplé — il suffit de mettre à jour la commande.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_conclusion_le_chaînon_manquant&amp;quot;&amp;gt;Conclusion : Le Chaînon Manquant&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avec hyperframes-gradle, mon pipeline vidéo est complet. J&amp;amp;#8217;ai :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Les &amp;lt;strong&amp;gt;slides interactives&amp;lt;/strong&amp;gt; (slider-gradle)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Les &amp;lt;strong&amp;gt;capsules de révision&amp;lt;/strong&amp;gt; (capsule-gradle)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Les &amp;lt;strong&amp;gt;vidéos standalone&amp;lt;/strong&amp;gt; (hyperframes-gradle)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Trois formats. Un seul fichier source : l&amp;amp;#8217;AsciiDoc.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le prochain objectif est HF-1 : faire compiler le plugin et générer un premier HTML HyperFrames à partir d&amp;amp;#8217;un document AsciiDoc annoté. La session 001 est déjà cadrée.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;hyperframes-gradle existe. La gouvernance est en place. Le backlog est écrit. L&amp;amp;#8217;architecture est documentée. Le plugin est né.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_références&amp;quot;&amp;gt;Références&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0124_architecture_plugin_gradle_racine_consommateur_independant_post.html&amp;quot;&amp;gt;Article 0124 — L&amp;amp;#8217;Architecture Plugin Indépendant + Racine Consommateur&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/heygen-com/hyperframes&amp;quot;&amp;gt;HyperFrames — GitHub&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://hyperframes.heygen.com/introduction&amp;quot;&amp;gt;HyperFrames — Documentation&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;foundry/public/hyperframes-gradle/hyperframes-plugin/doc/HYPERFRAMES_ARCHITECTURE.adoc&amp;lt;/code&amp;gt; — Architecture détaillée&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Audit de ma Consommation LLM : SQLite, OpenCode, Ollama Cloud, et Pourquoi Mon Abonnement Pro Éclate le Marché Mondial</title>
            <link >https://cheroliv.com/blog/2026/0125_audit_conso_opencode_methodologie_comparaison_prix_llm_post.html</link>
            <pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0125_audit_conso_opencode_methodologie_comparaison_prix_llm_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_comprendre_la_stack_qui_fait_quoi&amp;quot;&amp;gt;Comprendre la Stack : Qui Fait Quoi ?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_introduction_pourquoi_un_audit&amp;quot;&amp;gt;Introduction : Pourquoi un Audit ?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_base_de_données_opencode_une_mine_dor&amp;quot;&amp;gt;La Base de Données OpenCode : Une Mine d&amp;amp;#8217;Or&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_schéma&amp;quot;&amp;gt;Le Schéma&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_code_dextraction&amp;quot;&amp;gt;Le Code d&amp;amp;#8217;Extraction&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_les_résultats_73_jours_de_consommation&amp;quot;&amp;gt;Les Résultats : 73 Jours de Consommation&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_vue_globale&amp;quot;&amp;gt;Vue Globale&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ventilation_par_modèle_et_fournisseur&amp;quot;&amp;gt;Ventilation par Modèle et Fournisseur&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_les_modèles_intra_session_ce_que_la_table_session_ne_voit_pas&amp;quot;&amp;gt;Les Modèles Intra-Session : Ce Que la Table Session Ne Voit Pas&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_comparatif_tarifaire_fournisseurs_occidentaux&amp;quot;&amp;gt;Comparatif Tarifaire — Fournisseurs Occidentaux&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_anthropic_claude&amp;quot;&amp;gt;Anthropic — Claude&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_openai_gpt&amp;quot;&amp;gt;OpenAI — GPT&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_google_gemini&amp;quot;&amp;gt;Google — Gemini&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_huggingface_inference_providers&amp;quot;&amp;gt;HuggingFace Inference Providers&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_groq&amp;quot;&amp;gt;Groq&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_comparatif_tarifaire_fournisseurs_chinois&amp;quot;&amp;gt;Comparatif Tarifaire — Fournisseurs Chinois&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_deepseek_api_direct_platform_deepseek_com&amp;quot;&amp;gt;DeepSeek API Direct (platform.deepseek.com)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_kimi_moonshot_platform_kimi_com&amp;quot;&amp;gt;Kimi Moonshot (platform.kimi.com)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_alibaba_bailian_bailian_aliyun_com&amp;quot;&amp;gt;Alibaba Bailian (bailian.aliyun.com)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_tableau_récapitulatif_tous_providers&amp;quot;&amp;gt;Tableau Récapitulatif — Tous Providers&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_coût_caché_prompt_engineering_et_itérations&amp;quot;&amp;gt;Le Coût Caché : Prompt Engineering et Itérations&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_cumuler_les_abonnements_ollama_cloud_pro_la_méthode_docker&amp;quot;&amp;gt;Cumuler les Abonnements Ollama Cloud Pro : La Méthode Docker&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ce_que_laudit_ne_mesure_pas&amp;quot;&amp;gt;Ce Que l&amp;amp;#8217;Audit Ne Mesure Pas&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_conclusion_le_verdict_des_chiffres&amp;quot;&amp;gt;Conclusion : Le Verdict des Chiffres&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_références&amp;quot;&amp;gt;Références&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_sources_des_tarifs&amp;quot;&amp;gt;Sources des Tarifs&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 22 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;On me demande souvent combien coûte ma consommation d&amp;amp;#8217;IA. Je réponds « 20 balles par mois » et on me regarde avec des yeux ronds. Alors aujourd&amp;amp;#8217;hui, je vous ouvre la boîte noire. Cet article est l&amp;amp;#8217;audit complet de mes 73 jours de vibe coding : la méthodologie pour extraire les données depuis la base SQLite d&amp;amp;#8217;OpenCode, le code SQL pour interroger les tables, et la comparaison exhaustive avec &amp;lt;strong&amp;gt;tous&amp;lt;/strong&amp;gt; les fournisseurs du marché — occidentaux comme chinois. Le résultat est tellement asymétrique que j&amp;amp;#8217;ai dû vérifier mes calculs trois fois.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;toc&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;[]&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_comprendre_la_stack_qui_fait_quoi&amp;quot;&amp;gt;Comprendre la Stack : Qui Fait Quoi ?&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avant de plonger dans les chiffres, clarifions l&amp;amp;#8217;architecture. Il y a trois acteurs distincts dans mon setup, et c&amp;amp;#8217;est important de ne pas les confondre :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/stack-architecture.svg&amp;quot; alt=&amp;quot;stack architecture&amp;quot; width=&amp;quot;1474&amp;quot; height=&amp;quot;431&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock important&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-important&amp;quot; title=&amp;quot;❗&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;OpenCode n&amp;amp;#8217;est PAS un fournisseur de modèles.&amp;lt;/strong&amp;gt; C&amp;amp;#8217;est un CLI open source (&amp;lt;a href=&amp;quot;https://github.com/anomalyco/opencode&amp;quot;&amp;gt;github.com/anomalyco/opencode&amp;lt;/a&amp;gt;) qui orchestre des agents IA. Il ne vend pas d&amp;amp;#8217;abonnement, il ne fournit pas d&amp;amp;#8217;inférence. C&amp;amp;#8217;est l&amp;amp;#8217;équivalent de &amp;lt;code&amp;gt;git&amp;lt;/code&amp;gt; pour le versionnement : un outil, pas un service. &amp;lt;strong&amp;gt;Ollama Cloud est le fournisseur d&amp;amp;#8217;inférence.&amp;lt;/strong&amp;gt; Mon installation locale d&amp;amp;#8217;Ollama agit comme &amp;lt;strong&amp;gt;client&amp;lt;/strong&amp;gt; — elle s&amp;amp;#8217;authentifie auprès des serveurs d&amp;amp;#8217;Ollama via une clé SSH unique (Device Key) et leur délègue l&amp;amp;#8217;exécution des modèles tagués &amp;lt;code&amp;gt;:cloud&amp;lt;/code&amp;gt;. L&amp;amp;#8217;abonnement Pro (20€/mois) débloque des quotas supérieurs et permet de cumuler plusieurs comptes sur une même machine via Docker.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_introduction_pourquoi_un_audit&amp;quot;&amp;gt;Introduction : Pourquoi un Audit ?&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Il y a deux mois, j&amp;amp;#8217;utilisais des modèles gratuitement sur mon installation locale d&amp;amp;#8217;Ollama. Puis j&amp;amp;#8217;ai souscrit un premier abonnement Ollama Cloud Pro à 20€/mois, qui me permet d&amp;amp;#8217;utiliser les modèles cloud (ceux avec le tag &amp;lt;code&amp;gt;:cloud&amp;lt;/code&amp;gt;) via le provider &amp;lt;code&amp;gt;ollama-cloud&amp;lt;/code&amp;gt;. Un deuxième abonnement a suivi un mois plus tard, sur une instance Docker séparée avec son propre compte et sa propre clé SSH — la méthode de cumul décrite dans &amp;lt;a href=&amp;quot;0120_cumuler_deux_abonnements_ollama_pro_docker_post.html&amp;quot;&amp;gt;mon article sur le cumul d&amp;amp;#8217;abonnements&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La question qui me taraudait : &amp;lt;strong&amp;gt;est-ce que ces 20€ par mois sont justifiés ?&amp;lt;/strong&amp;gt; Pas au doigt mouillé. Avec des chiffres.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pour répondre, j&amp;amp;#8217;avais besoin de données précises. Pas des estimations. Pas des moyennes. Ma consommation &amp;lt;strong&amp;gt;réelle&amp;lt;/strong&amp;gt;, token par token, modèle par modèle, session par session.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Et OpenCode — le CLI — stocke tout ça dans une base SQLite.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_base_de_données_opencode_une_mine_dor&amp;quot;&amp;gt;La Base de Données OpenCode : Une Mine d&amp;amp;#8217;Or&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;OpenCode persiste l&amp;amp;#8217;intégralité de l&amp;amp;#8217;historique de ses sessions dans un fichier SQLite situé à &amp;lt;code&amp;gt;~/.local/share/opencode/opencode.db&amp;lt;/code&amp;gt;. La mienne pèse 660 Mo pour 73 jours d&amp;amp;#8217;utilisation — une base de données de production tout à fait respectable.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ ls -lh ~/.local/share/opencode/opencode.db
-rw-r--r-- 1 cheroliv cheroliv 660M mai 18 12:25 opencode.db&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_schéma&amp;quot;&amp;gt;Le Schéma&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La base contient une vingtaine de tables, mais trois d&amp;amp;#8217;entre elles sont cruciales pour notre audit :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/schema-principal.svg&amp;quot; alt=&amp;quot;schema principal&amp;quot; width=&amp;quot;684&amp;quot; height=&amp;quot;397&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La table &amp;lt;code&amp;gt;session&amp;lt;/code&amp;gt; est parfaite pour un audit global : chaque session a son décompte de tokens agrégé, son modèle utilisé, et son coût. Le champ &amp;lt;code&amp;gt;model&amp;lt;/code&amp;gt; est du JSON brut :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-json hljs&amp;quot; data-lang=&amp;quot;json&amp;quot;&amp;gt;{
  &amp;quot;id&amp;quot;: &amp;quot;deepseek-v4-pro:cloud&amp;quot;,
  &amp;quot;providerID&amp;quot;: &amp;quot;ollama-cloud&amp;quot;,
  &amp;quot;variant&amp;quot;: &amp;quot;default&amp;quot;
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock important&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-important&amp;quot; title=&amp;quot;❗&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le champ &amp;lt;code&amp;gt;cost&amp;lt;/code&amp;gt; dans la base OpenCode ne reflète que les &amp;lt;strong&amp;gt;frais d&amp;amp;#8217;API externes&amp;lt;/strong&amp;gt; payés à la consommation via API key (Google Gemini, OpenAI, etc.). Les appels via Ollama — que ce soit en local ou via Ollama Cloud Pro — sont marqués &amp;lt;code&amp;gt;cost=0&amp;lt;/code&amp;gt; parce que le coût est forfaitaire (abonnement), pas per-token. Le vrai coût de ces appels, c&amp;amp;#8217;est l&amp;amp;#8217;abonnement mensuel.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_code_dextraction&amp;quot;&amp;gt;Le Code d&amp;amp;#8217;Extraction&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pas besoin d&amp;amp;#8217;installer quoi que ce soit. Node.js 22+ intègre un module SQLite expérimental (&amp;lt;code&amp;gt;node:sqlite&amp;lt;/code&amp;gt;) qui fonctionne parfaitement. Voici le script qui m&amp;amp;#8217;a tout donné :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript hljs&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;const { DatabaseSync } = require(&amp;#39;node:sqlite&amp;#39;);
const db = new DatabaseSync(
  `${process.env.HOME}/.local/share/opencode/opencode.db`,
  { readonly: true }
);

// 1. Statistiques globales
const global = db.prepare(`
  SELECT
    COUNT(*) as sessions,
    SUM(tokens_input) as total_input,
    SUM(tokens_output) as total_output,
    SUM(tokens_reasoning) as total_reasoning,
    SUM(tokens_cache_read) as total_cache_read,
    SUM(cost) as total_cost
  FROM session
`).get();

// 2. Ventilation par modèle et fournisseur
const byModel = db.prepare(`
  SELECT
    json_extract(model, &amp;#39;$.id&amp;#39;) as model_id,
    json_extract(model, &amp;#39;$.providerID&amp;#39;) as provider,
    COUNT(*) as sessions,
    SUM(tokens_input) as total_input,
    SUM(tokens_output) as total_output,
    SUM(cost) as total_cost
  FROM session
  WHERE model IS NOT NULL
  GROUP BY model_id, provider
  ORDER BY SUM(tokens_input) DESC
`).all();

// 3. Par mois
const monthly = db.prepare(`
  SELECT
    strftime(&amp;#39;%Y-%m&amp;#39;, datetime(time_created/1000, &amp;#39;unixepoch&amp;#39;)) as month,
    COUNT(*) as sessions,
    SUM(tokens_input) as total_input,
    SUM(tokens_output) as total_output,
    SUM(cost) as total_cost
  FROM session
  WHERE time_created IS NOT NULL
  GROUP BY month
  ORDER BY month
`).all();

// 4. Messages par modèle (détection des changements intra-session)
const msgByModel = db.prepare(`
  SELECT
    json_extract(m.data, &amp;#39;$.model.providerID&amp;#39;) as provider,
    json_extract(m.data, &amp;#39;$.model.modelID&amp;#39;) as model_id,
    COUNT(*) as messages
  FROM message m
  WHERE json_extract(m.data, &amp;#39;$.model&amp;#39;) IS NOT NULL
  GROUP BY provider, model_id
  ORDER BY COUNT(*) DESC
`).all();

console.log({ global, byModel, monthly, msgByModel });
db.close();&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;ℹ️&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le flag &amp;lt;code&amp;gt;--experimental-sqlite&amp;lt;/code&amp;gt; est nécessaire sur Node.js 22.x. Sur Node.js 24+, le module est stable et ne nécessite plus de flag.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_les_résultats_73_jours_de_consommation&amp;quot;&amp;gt;Les Résultats : 73 Jours de Consommation&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_vue_globale&amp;quot;&amp;gt;Vue Globale&amp;lt;/h3&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3334%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Métrique&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Valeur&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Contexte&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Sessions OpenCode&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;1 022&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;~14 sessions/jour en moyenne&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Tokens Input&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;2,62 milliards&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Dont 94,5M en cache hit&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Tokens Output&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;21 millions&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Ratio input/output ~125:1&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Tokens Reasoning&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;141 000&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Négligeable — quasi pas de thinking&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Coût API externe&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;\$0,22&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Frais hors abonnement (Gemini + free tiers)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce chiffre de \$0,22 est crucial : il représente tout ce que j&amp;amp;#8217;ai payé &amp;lt;strong&amp;gt;en plus&amp;lt;/strong&amp;gt; de mon abonnement Ollama Cloud Pro. C&amp;amp;#8217;est-à-dire quasiment rien. L&amp;amp;#8217;abonnement couvre l&amp;amp;#8217;essentiel.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/repartition-mensuelle.svg&amp;quot; alt=&amp;quot;repartition mensuelle&amp;quot; width=&amp;quot;638&amp;quot; height=&amp;quot;207&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le décollage entre mars et avril est spectaculaire : ×35 en un mois. C&amp;amp;#8217;est la transition de l&amp;amp;#8217;usage « test » à l&amp;amp;#8217;usage « production » — quand j&amp;amp;#8217;ai commencé à faire tourner des agents OpenCode en continu pour mes plugins Gradle.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ventilation_par_modèle_et_fournisseur&amp;quot;&amp;gt;Ventilation par Modèle et Fournisseur&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le champ &amp;lt;code&amp;gt;model&amp;lt;/code&amp;gt; de la table &amp;lt;code&amp;gt;session&amp;lt;/code&amp;gt; étant du JSON, &amp;lt;code&amp;gt;json_extract()&amp;lt;/code&amp;gt; permet de ventiler proprement :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 27.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1819%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Modèle × Provider&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Sessions&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Input&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Output&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Coût&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;deepseek-v4-pro @ ollama-cloud&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;63&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;220 M&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;1,94 M&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$0&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;deepseek-v4-pro @ ollama-b&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;124&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;463 M&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;4,15 M&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$0&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;deepseek-v4-pro @ ollama&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;100&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;252 M&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;2,25 M&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$0&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;deepseek-v4-flash-free @ opencode&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;16&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;1,3 M&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;279 K&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$0&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;qwen3.6-plus-free @ opencode&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;1&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;369 K&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;25 K&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$0&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;gemini-2.5-flash @ google&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;1&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;211 K&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;19 K&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$0,04&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock important&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-important&amp;quot; title=&amp;quot;❗&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Trois providers différents pour exactement le même modèle DeepSeek V4 Pro :
* &amp;lt;code&amp;gt;ollama-cloud&amp;lt;/code&amp;gt; → via &amp;lt;strong&amp;gt;abonnement Pro payant&amp;lt;/strong&amp;gt; (cloud managé par Ollama)
* &amp;lt;code&amp;gt;ollama-b&amp;lt;/code&amp;gt; → &amp;lt;strong&amp;gt;deuxième abonnement Pro&amp;lt;/strong&amp;gt;, isolé dans un conteneur Docker distinct
* &amp;lt;code&amp;gt;ollama&amp;lt;/code&amp;gt; → instance native locale, &amp;lt;strong&amp;gt;gratuite&amp;lt;/strong&amp;gt; (tourne directement sur ma machine)
La somme des trois donne 936M input, 8,4M output — c&amp;amp;#8217;est ma conso totale DeepSeek V4 Pro, tous providers confondus. Seul &amp;lt;code&amp;gt;ollama-cloud&amp;lt;/code&amp;gt; (220M input) coûte un abonnement. Les 716M restants sont gratuits (local ou cumul d&amp;amp;#8217;abonnements).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_les_modèles_intra_session_ce_que_la_table_session_ne_voit_pas&amp;quot;&amp;gt;Les Modèles Intra-Session : Ce Que la Table Session Ne Voit Pas&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La table &amp;lt;code&amp;gt;session&amp;lt;/code&amp;gt; ne capture que le modèle &amp;lt;strong&amp;gt;principal&amp;lt;/strong&amp;gt; de la session. Mais pendant une même session, un agent OpenCode peut basculer entre plusieurs modèles. La table &amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt; le révèle :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;Modèles utilisés dans les messages (ollama-cloud provider) :
├─ deepseek-v4-pro      1 441 msgs  (32%)
├─ qwen3.5:397b         1 217 msgs  (27%)
├─ glm-5.1                712 msgs  (16%)
├─ kimi-k2.6:cloud        634 msgs  (14%)
├─ qwen3-coder:480b       414 msgs   (9%)
├─ gpt-oss:20b             34 msgs  (0,8%)
├─ qwen3-coder-next        27 msgs  (0,6%)
└─ gemma4:31b               7 msgs  (0,2%)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock caution&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-caution&amp;quot; title=&amp;quot;🔒&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Je n&amp;amp;#8217;utilise plus Qwen, GLM, Kimi ni les autres modèles. Ils apparaissent dans l&amp;amp;#8217;historique parce que j&amp;amp;#8217;ai testé pas mal de choses en avril. Depuis mi-mai, je suis verrouillé sur DeepSeek V4 Pro — c&amp;amp;#8217;est le seul qui tient la charge sur du long contexte avec gouvernance agent (cf. &amp;lt;a href=&amp;quot;0112_comparaison_kimi_glm_deepseek_long_contexte_plugin_gradle_opencode_post.html&amp;quot;&amp;gt;ma comparaison Kimi/GLM/DeepSeek&amp;lt;/a&amp;gt;). Les 32% de messages deepseek dans l&amp;amp;#8217;historique sont trompeurs : aujourd&amp;amp;#8217;hui c&amp;amp;#8217;est 100%.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_comparatif_tarifaire_fournisseurs_occidentaux&amp;quot;&amp;gt;Comparatif Tarifaire — Fournisseurs Occidentaux&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La question qui fâche : combien coûterait cette même consommation chez les fournisseurs traditionnels ?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ma base de calcul pour le comparatif : &amp;lt;strong&amp;gt;220M tokens input + 1,9M tokens output&amp;lt;/strong&amp;gt; — &amp;lt;strong&amp;gt;uniquement&amp;lt;/strong&amp;gt; le volume passé par &amp;lt;code&amp;gt;ollama-cloud&amp;lt;/code&amp;gt; (le seul qui correspond à mon abonnement payant). Les 716M restants sont gratuits (Ollama local et instance Docker B).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 23.0769%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 15.3846%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 15.3846%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 15.3846%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 15.3846%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 15.3847%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Fournisseur&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Modèle&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Input \$/M&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Output \$/M&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Coût/mois&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;× mon abonnement&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Mon setup&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;DeepSeek V4 Pro&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;0&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;0&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;\~20€&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;1×&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_anthropic_claude&amp;quot;&amp;gt;Anthropic — Claude&amp;lt;/h3&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 27.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1819%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Modèle&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Input \$/M&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Output \$/M&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Coût/mois&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;× mon abonnement&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Opus 4.7&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$5&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$25&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$1 148&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;57×&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Sonnet 4.6&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$3&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$15&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$689&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;34×&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Haiku 4.5&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$1&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$5&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$230&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;11×&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Même Haiku 4.5, le modèle le plus « économique » de Claude, coûte 11× mon abonnement. Et il ne connaît rien de mon codebase, ne génère pas dans mon style, et hallucine sur les APIs Gradle Kotlin DSL.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_openai_gpt&amp;quot;&amp;gt;OpenAI — GPT&amp;lt;/h3&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 27.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1819%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Modèle&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Input \$/M&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Output \$/M&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Coût/mois&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;× mon abonnement&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;GPT 5.5&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$5&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$30&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$1 157&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;58×&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;GPT 5.4&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$2,50&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$15&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$579&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;29×&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;GPT 5.4 Mini&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$0,75&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$4,50&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$174&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;9×&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_google_gemini&amp;quot;&amp;gt;Google — Gemini&amp;lt;/h3&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 27.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1819%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Modèle&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Input \$/M&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Output \$/M&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Coût/mois&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;× mon abonnement&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Gemini 3.1 Pro&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$2,00&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$10&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$459&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;23×&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Gemini 3 Flash&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$0,30&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$1,50&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$69&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;3,5×&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Gemini 3 Flash à 69€ est le seul concurrent « proche » en prix pur — mais c&amp;amp;#8217;est un modèle dense léger, pas un MoE 1.6T comme DeepSeek V4 Pro. La qualité du code généré n&amp;amp;#8217;a rien à voir.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_huggingface_inference_providers&amp;quot;&amp;gt;HuggingFace Inference Providers&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;HuggingFace ne fait pas d&amp;amp;#8217;inférence lui-même — il agrège des &amp;lt;strong&amp;gt;providers&amp;lt;/strong&amp;gt; tiers (Novita, Together, DeepInfra, Cerebras, SambaNova, Fireworks, Groq…) via une API unifiée. On choisit le provider le moins cher ou le plus rapide. Voici les tarifs relevés en mai 2026 pour DeepSeek V4 Pro :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 27.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1819%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Provider HF&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Input \$/M&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Output \$/M&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Coût/mois&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;× mon abonnement&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Novita (le moins cher)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$1,67&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$3,38&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;\$374&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;19×&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;DeepInfra&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$1,74&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$3,48&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;\$389&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;19×&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Together&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$2,10&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$4,40&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;\$470&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;23×&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Fireworks&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;tarif non public&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;—&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;—&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;—&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Même le provider le moins cher sur HuggingFace (Novita) facture 19× le prix de mon abonnement. Et contrairement à Ollama Cloud, HuggingFace facture &amp;lt;strong&amp;gt;en plus&amp;lt;/strong&amp;gt; les frais de plateforme si vous n&amp;amp;#8217;avez pas d&amp;amp;#8217;abonnement PRO HF (\$9/mois).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_groq&amp;quot;&amp;gt;Groq&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Groq n&amp;amp;#8217;a &amp;lt;strong&amp;gt;aucun&amp;lt;/strong&amp;gt; des modèles que j&amp;amp;#8217;utilise — leur catalogue se limite à GPT-OSS, Llama et Qwen 32B. Impossible de comparer.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_comparatif_tarifaire_fournisseurs_chinois&amp;quot;&amp;gt;Comparatif Tarifaire — Fournisseurs Chinois&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le vrai test, c&amp;amp;#8217;est le marché chinois. Si DeepSeek est un modèle chinois, son API native devrait être moins chère, non ?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_deepseek_api_direct_platform_deepseek_com&amp;quot;&amp;gt;DeepSeek API Direct (platform.deepseek.com)&amp;lt;/h3&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 22.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 22.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 22.2223%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Période&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Input \$/M&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Output \$/M&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Coût/mois&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Promo -75% (fin 31 mai)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$0,435&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$0,87&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;\$98&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Plein tarif (à partir de juin)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$1,74&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$3,48&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;\$390&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Même avec la promo agressive de DeepSeek (-75% prolongée), l&amp;amp;#8217;API directe coûte &amp;lt;strong&amp;gt;5×&amp;lt;/strong&amp;gt; plus cher. Au tarif normal, &amp;lt;strong&amp;gt;20×&amp;lt;/strong&amp;gt;. Et c&amp;amp;#8217;est &amp;lt;strong&amp;gt;uniquement&amp;lt;/strong&amp;gt; DeepSeek — pas d&amp;amp;#8217;accès à d&amp;amp;#8217;autres modèles.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_kimi_moonshot_platform_kimi_com&amp;quot;&amp;gt;Kimi Moonshot (platform.kimi.com)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Kimi ne propose que ses propres modèles. Pas de DeepSeek.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_alibaba_bailian_bailian_aliyun_com&amp;quot;&amp;gt;Alibaba Bailian (bailian.aliyun.com)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Seul fournisseur qui agrège tous les modèles chinois — mais via revente avec marge. Les prix sont chargés dynamiquement en JavaScript, rendant le scraping impossible.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_tableau_récapitulatif_tous_providers&amp;quot;&amp;gt;Tableau Récapitulatif — Tous Providers&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 23.0769%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 15.3846%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 15.3846%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 15.3846%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 15.3846%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 15.3847%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Fournisseur&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Modèle&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Input \$/M&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Output \$/M&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Coût/mois&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;× mon abonnement&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Ollama Cloud Pro&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;DeepSeek V4 Pro&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;0&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;0&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;~20€&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;1×&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Gemini 3 Flash&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Gemini 3 Flash&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$0,30&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$1,50&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$69&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;3,5×&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;DeepSeek API (promo)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;DeepSeek V4 Pro&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$0,44&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$0,87&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$98&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;5×&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;GPT 5.4 Mini&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;GPT 5.4 Mini&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$0,75&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$4,50&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$174&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;9×&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Claude Haiku 4.5&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Claude Haiku 4.5&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$1&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$5&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$230&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;11×&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;HuggingFace/Novita&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;DeepSeek V4 Pro&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$1,67&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$3,38&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$374&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;19×&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;DeepSeek API (normal)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;DeepSeek V4 Pro&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$1,74&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$3,48&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$390&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;20×&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Together AI&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;DeepSeek V4 Pro&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$2,10&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$4,40&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$470&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;23×&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;GPT 5.4&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;GPT 5.4&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$2,50&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$15&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$579&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;29×&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Claude Sonnet 4.6&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Claude Sonnet 4.6&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$3&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$15&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$689&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;34×&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Claude Opus 4.7&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Claude Opus 4.7&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$5&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$25&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$1 148&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;57×&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;GPT 5.5&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;GPT 5.5&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$5&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$30&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\$1 157&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;58×&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/cout-comparaison-barres.svg&amp;quot; alt=&amp;quot;cout comparaison barres&amp;quot; width=&amp;quot;655&amp;quot; height=&amp;quot;279&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_coût_caché_prompt_engineering_et_itérations&amp;quot;&amp;gt;Le Coût Caché : Prompt Engineering et Itérations&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le coût token n&amp;amp;#8217;est qu&amp;amp;#8217;une partie de l&amp;amp;#8217;équation. Le vrai coût, c&amp;amp;#8217;est le temps développeur.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avec OpenCode + Ollama Cloud Pro + ma gouvernance agent (EAGER/LAZY/Hot/Warm/Cold, décrite dans &amp;lt;a href=&amp;quot;0108_gouvernance_agent_opencode_eager_lazy_post.html&amp;quot;&amp;gt;l&amp;amp;#8217;article sur la gouvernance&amp;lt;/a&amp;gt;), j&amp;amp;#8217;obtiens :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;0 prompt engineering répétitif&amp;lt;/strong&amp;gt; : le contexte est injecté automatiquement&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;90%+ first-shot correct&amp;lt;/strong&amp;gt; : le code compile du premier coup&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Zéro hallucination deepseek sur 8 sessions consécutives&amp;lt;/strong&amp;gt; (documenté dans &amp;lt;a href=&amp;quot;0112_comparaison_kimi_glm_deepseek_long_contexte_plugin_gradle_opencode_post.html&amp;quot;&amp;gt;la comparaison Kimi/GLM/DeepSeek&amp;lt;/a&amp;gt;)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avec Claude ou GPT &amp;lt;strong&amp;gt;sans&amp;lt;/strong&amp;gt; fine-tune ni gouvernance :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;2-3 itérations par tâche en moyenne&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Prompt engineering systématique&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Hallucinations sur les APIs Kotlin/Gradle dès que le contexte dépasse 30K tokens&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le coût « effectif » mensuel — tokens × itérations × temps de correction — est de 27× à 54× celui de ma solution, comme je l&amp;amp;#8217;ai démontré dans &amp;lt;a href=&amp;quot;0122_ratio_efficacite_27x_45x_flotte_experts_ia_vs_claude_gpt_post.html&amp;quot;&amp;gt;l&amp;amp;#8217;article sur le ratio d&amp;amp;#8217;efficacité&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&amp;lt;em&amp;gt;_ Ce n&amp;amp;#8217;est pas juste une histoire de prix au token. Un Claude Opus à 57× le prix qui nécessite 3× plus d&amp;amp;#8217;itérations, c&amp;amp;#8217;est un coût effectif ~170× supérieur. Pour le dire crûment : payer un stagiaire le salaire d&amp;amp;#8217;un partner McKinsey. &amp;lt;/em&amp;gt;_&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_cumuler_les_abonnements_ollama_cloud_pro_la_méthode_docker&amp;quot;&amp;gt;Cumuler les Abonnements Ollama Cloud Pro : La Méthode Docker&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Si un seul abonnement ne suffit pas, on en cumule. Le principe est d&amp;amp;#8217;isoler chaque abonnement dans sa propre installation Ollama, avec sa propre clé SSH d&amp;amp;#8217;authentification. Docker rend ça trivial.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La méthode complète est détaillée dans &amp;lt;a href=&amp;quot;0120_cumuler_deux_abonnements_ollama_pro_docker_post.html&amp;quot;&amp;gt;l&amp;amp;#8217;article sur le cumul Docker&amp;lt;/a&amp;gt;, voici le principe :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/architecture-dual-abonnement.svg&amp;quot; alt=&amp;quot;architecture dual abonnement&amp;quot; width=&amp;quot;581&amp;quot; height=&amp;quot;481&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le pattern est simple :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Créer un volume &amp;lt;code&amp;gt;~/ollama-b-data&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Lancer un conteneur Docker &amp;lt;code&amp;gt;ollama/ollama:0.20.2&amp;lt;/code&amp;gt; mappé sur &amp;lt;code&amp;gt;11435:11434&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Récupérer la clé SSH du conteneur → l&amp;amp;#8217;enregistrer sur ollama.com&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Faire &amp;lt;code&amp;gt;ollama signin&amp;lt;/code&amp;gt; avec un deuxième email&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Configurer OpenCode avec deux providers (&amp;lt;code&amp;gt;ollama&amp;lt;/code&amp;gt; sur :11434, &amp;lt;code&amp;gt;ollama-b&amp;lt;/code&amp;gt; sur :11435)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Deux comptes, une carte bleue, zéro conflit.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_ce_que_laudit_ne_mesure_pas&amp;quot;&amp;gt;Ce Que l&amp;amp;#8217;Audit Ne Mesure Pas&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 40%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 60%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Angle mort&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Impact&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Qualité du code produit&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;2,6 milliards de tokens ne disent pas si le code compile. Mes 8 sessions DeepSeek V4 Pro ont un taux de first-shot &amp;amp;gt;90%.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Écosystème OpenCode&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Le CLI est gratuit, mais sa valeur (agents, sandboxes, historique, prompt caching) est immense. Il n&amp;amp;#8217;est pas inclus dans le prix de l&amp;amp;#8217;abonnement — c&amp;amp;#8217;est un outil séparé.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Coût d&amp;amp;#8217;opportunité&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Passer 2h/jour à debugger des hallucinations d&amp;amp;#8217;un modèle inférieur coûte plus cher que 20€/mois.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Tranquillité d&amp;amp;#8217;esprit&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Forfait fixe = pas de surprise. Avec du per-token, un pic d&amp;amp;#8217;activité peut faire très mal.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock warning&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-warning&amp;quot; title=&amp;quot;⚠️&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Les prix cités sont ceux de mai 2026. Dans six mois, tout aura baissé. Mais le rapport de force structurel — abonnement fixe vs paiement à l&amp;amp;#8217;usage — restera favorable à l&amp;amp;#8217;abonnement pour les gros consommateurs.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_conclusion_le_verdict_des_chiffres&amp;quot;&amp;gt;Conclusion : Le Verdict des Chiffres&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Après 73 jours, 1 022 sessions OpenCode, et 2,6 milliards de tokens :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 60%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 40%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Métrique&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Verdict&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Coût API externe cumulé&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;\$0,22&amp;lt;/strong&amp;gt; (quasi nul)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Coût abonnement Ollama Cloud Pro&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;~20€/mois&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Équivalent Claude Opus&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;\$1 148/mois&amp;lt;/strong&amp;gt; — 57× plus cher&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Équivalent GPT 5.5&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;\$1 157/mois&amp;lt;/strong&amp;gt; — 58× plus cher&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Équivalent HuggingFace/Novita&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;\$374/mois&amp;lt;/strong&amp;gt; — 19× plus cher&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Équivalent DeepSeek API direct&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;\$390/mois&amp;lt;/strong&amp;gt; — 20× plus cher&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Équivalent le moins cher (Gemini Flash)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;\$69/mois&amp;lt;/strong&amp;gt; — 3,5× plus cher, modèle inférieur&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Meilleure offre du marché&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Ollama Cloud Pro à 20€/mois&amp;lt;/strong&amp;gt; — imbattable&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;__&amp;lt;/em&amp;gt; À 20€ par mois pour accéder à DeepSeek V4 Pro (1.6T params, MoE, CSA+HCA, 1M contexte) via Ollama Cloud, j&amp;amp;#8217;ai le meilleur rapport qualité/prix du marché mondial. Même les fournisseurs chinois en direct sont 5× à 20× plus chers. Même HuggingFace, avec son agrégation de providers low-cost, est 19× plus cher. Le marché occidental (Claude, GPT) est à 50-60× — une autre planète.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce ratio est tellement déséquilibré qu&amp;amp;#8217;il ne peut pas durer éternellement. Profitez-en tant que ça existe. &amp;lt;em&amp;gt;__&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Alors oui, mes 20 balles par mois, c&amp;amp;#8217;est le meilleur investissement technique de ma vie de développeur. Et maintenant vous avez les chiffres pour le prouver.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_références&amp;quot;&amp;gt;Références&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0108_gouvernance_agent_opencode_eager_lazy_post.html&amp;quot;&amp;gt;Article 0108 — Gouvernance Agent EAGER/LAZY/Hot/Warm/Cold&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0112_comparaison_kimi_glm_deepseek_long_contexte_plugin_gradle_opencode_post.html&amp;quot;&amp;gt;Article 0112 — DeepSeek V4 Pro vs Kimi K2.6 vs GLM 5.1&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0119_benchmark_dgx_spark_vs_cloud_abonnement_llm_post.html&amp;quot;&amp;gt;Article 0119 — Benchmark DGX Spark vs Cloud vs Abonnements LLM&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0120_cumuler_deux_abonnements_ollama_pro_docker_post.html&amp;quot;&amp;gt;Article 0120 — Cumuler Deux Abonnements Ollama Cloud Pro avec Docker&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0121_plugin_gradle_piloter_deux_instances_ollama_pro_post.html&amp;quot;&amp;gt;Article 0121 — Plugin Gradle pour Piloter Deux Instances Ollama&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0122_ratio_efficacite_27x_45x_flotte_experts_ia_vs_claude_gpt_post.html&amp;quot;&amp;gt;Article 0122 — Ratio Efficacité 27× à 54×&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_sources_des_tarifs&amp;quot;&amp;gt;Sources des Tarifs&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://ollama.com/pricing&amp;quot;&amp;gt;Ollama Cloud — Tarifs Pro \$20/mois&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://api-docs.deepseek.com/quick_start/pricing&amp;quot;&amp;gt;DeepSeek API — Tarifs officiels V4 Pro&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://platform.kimi.com/docs/pricing/chat-k26&amp;quot;&amp;gt;Kimi Moonshot — Tarifs K2.6&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://huggingface.co/inference/models&amp;quot;&amp;gt;HuggingFace Inference Providers — Tarifs par provider&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://www.anthropic.com/pricing&amp;quot;&amp;gt;Anthropic — Tarifs Claude API&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://openai.com/api/pricing/&amp;quot;&amp;gt;OpenAI — Tarifs GPT API&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://together.ai/pricing&amp;quot;&amp;gt;Together AI — Tarifs inférence&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://groq.com/pricing&amp;quot;&amp;gt;Groq — Tarifs API&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://deepinfra.com/pricing&amp;quot;&amp;gt;DeepInfra — Tarifs GPU et modèles&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://help.aliyun.com/zh/model-studio/text-generation-model/&amp;quot;&amp;gt;Alibaba Bailian — Modèles disponibles&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/anomalyco/opencode&amp;quot;&amp;gt;OpenCode — CLI open source sur GitHub&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>L&#39;Architecture « Plugin Indépendant + Racine Consommateur » : Pourquoi mes Builds Gradle Se Dédoublent</title>
            <link >https://cheroliv.com/blog/2026/0124_architecture_plugin_gradle_racine_consommateur_independant_post.html</link>
            <pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0124_architecture_plugin_gradle_racine_consommateur_independant_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_problème_trois_architectures_qui_mont_fait_perdre_du_temps&amp;quot;&amp;gt;Le Problème : Trois Architectures Qui M&amp;amp;#8217;ont Fait Perdre du Temps&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_option_1_le_plugin_isolé_pas_de_dogfooding&amp;quot;&amp;gt;Option 1 : Le Plugin Isolé (pas de dogfooding)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_option_2_le_monorepo_classique_includeplugin&amp;quot;&amp;gt;Option 2 : Le Monorepo Classique (&amp;lt;code&amp;gt;include(&amp;quot;:plugin&amp;quot;)&amp;lt;/code&amp;gt;)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_option_3_le_composite_build_includebuild&amp;quot;&amp;gt;Option 3 : Le Composite Build (&amp;lt;code&amp;gt;includeBuild()&amp;lt;/code&amp;gt;)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_solution_deux_builds_indépendants_une_racine_consommateur&amp;quot;&amp;gt;La Solution : Deux Builds Indépendants, Une Racine Consommateur&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_flux_de_travail&amp;quot;&amp;gt;Le Flux de Travail&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_workflow_concret&amp;quot;&amp;gt;Le Workflow Concret&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pourquoi_cette_architecture_ma_conquis&amp;quot;&amp;gt;Pourquoi Cette Architecture M&amp;amp;#8217;a Conquis&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_1_dogfooding_natif_feedback_instantané&amp;quot;&amp;gt;1. Dogfooding Natif, Feedback Instantané&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_2_clonage_zero_config&amp;quot;&amp;gt;2. Clonage Zero-Config&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_3_builds_isolés_ci_indépendants&amp;quot;&amp;gt;3. Builds Isolés, CI Indépendants&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_lanatomie_du_sous_dossier_name_plugin&amp;quot;&amp;gt;L&amp;amp;#8217;Anatomie du Sous-Dossier &amp;lt;code&amp;gt;{name}-plugin/&amp;lt;/code&amp;gt;&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_catalogue_de_versions_deux_fichiers_distincts&amp;quot;&amp;gt;Le Catalogue de Versions : Deux Fichiers Distincts&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ce_quon_ne_fait_pas&amp;quot;&amp;gt;Ce Qu&amp;amp;#8217;On Ne Fait Pas&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_comparaison_les_trois_architectures_face_au_dogfooding&amp;quot;&amp;gt;Comparaison : Les Trois Architectures Face au Dogfooding&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_contrat_dag_un_build_racin_nimporte_jamais_depuis_un_sous_dossier&amp;quot;&amp;gt;Le Contrat DAG : Un Build Racin N&amp;amp;#8217;Importe Jamais Depuis un Sous-Dossier&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_conclusion_la_duplication_apparente_qui_fait_gagner_du_temps&amp;quot;&amp;gt;Conclusion : La Duplication Apparente Qui Fait Gagner du Temps&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_références&amp;quot;&amp;gt;Références&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 11 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Vous clonez un dépôt de plugin Gradle. Vous ouvrez un terminal. Qu&amp;amp;#8217;est-ce que vous tapez ensuite ? &amp;lt;code&amp;gt;./gradlew tasks&amp;lt;/code&amp;gt;, bien sûr. Mais dans quel dossier ? La racine ? Le sous-module ? Faut-il d&amp;amp;#8217;abord lire un README pour savoir comment builder ? Si vous hésitez ne serait-ce qu&amp;amp;#8217;une seconde, l&amp;amp;#8217;architecture du projet est cassée.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Voici comment j&amp;amp;#8217;ai résolu ce problème une fois pour toutes — et pourquoi ce pattern est aujourd&amp;amp;#8217;hui la signature de tous mes plugins Gradle dans &amp;lt;code&amp;gt;foundry/public/&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_problème_trois_architectures_qui_mont_fait_perdre_du_temps&amp;quot;&amp;gt;Le Problème : Trois Architectures Qui M&amp;amp;#8217;ont Fait Perdre du Temps&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avant de converger vers le pattern actuel, j&amp;amp;#8217;ai tâtonné entre trois approches classiques pour organiser un plugin Gradle. Chacune avait un défaut rédhibitoire.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_option_1_le_plugin_isolé_pas_de_dogfooding&amp;quot;&amp;gt;Option 1 : Le Plugin Isolé (pas de dogfooding)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le projet ne contient que le plugin. Pas d&amp;amp;#8217;exemple de consommation. Pas de projet qui l&amp;amp;#8217;exerce. Pour le tester, il faut créer un projet externe, y référencer le plugin via &amp;lt;code&amp;gt;mavenLocal&amp;lt;/code&amp;gt; ou un composite build, et seulement là vérifier qu&amp;amp;#8217;il marche.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-shell hljs&amp;quot; data-lang=&amp;quot;shell&amp;quot;&amp;gt;$ git clone mon-plugin
$ cd mon-plugin
$ ./gradlew build          # le plugin compile
$ # ... et maintenant ? comment je l&amp;#39;essaie ?&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock warning&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-warning&amp;quot; title=&amp;quot;⚠️&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un plugin Gradle sans exemple de consommation, c&amp;amp;#8217;est une bibliothèque sans tests d&amp;amp;#8217;intégration. Vous ne savez jamais si la dernière modification a cassé l&amp;amp;#8217;expérience utilisateur.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_option_2_le_monorepo_classique_includeplugin&amp;quot;&amp;gt;Option 2 : Le Monorepo Classique (&amp;lt;code&amp;gt;include(&amp;quot;:plugin&amp;quot;)&amp;lt;/code&amp;gt;)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Gradle &amp;lt;code&amp;gt;init&amp;lt;/code&amp;gt; génère &amp;lt;code&amp;gt;settings.gradle.kts&amp;lt;/code&amp;gt; avec &amp;lt;code&amp;gt;include(&amp;quot;plugin&amp;quot;)&amp;lt;/code&amp;gt;. Le root et le sous-module partagent le même daemon, les mêmes configurations, les mêmes catalogues. Pratique, mais couplé.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;.
├── settings.gradle.kts   → include(&amp;quot;plugin&amp;quot;)
├── build.gradle.kts      → plugins { id(&amp;quot;mon-plugin&amp;quot;) }
├── plugin/
│   └── build.gradle.kts  → java-gradle-plugin
└── gradle/
    └── libs.versions.toml&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce qui coince :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le root &amp;lt;strong&amp;gt;doit&amp;lt;/strong&amp;gt; avoir la même version de Gradle que le sous-module.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;libs.versions.toml&amp;lt;/code&amp;gt; est partagé — version catalogs communs, dépendances&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;qui fuient d&amp;amp;#8217;un module à l&amp;amp;#8217;autre.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Impossible de builder le plugin indépendamment du root.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;La CI doit builder les deux modules, même si seul le plugin a changé.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_option_3_le_composite_build_includebuild&amp;quot;&amp;gt;Option 3 : Le Composite Build (&amp;lt;code&amp;gt;includeBuild()&amp;lt;/code&amp;gt;)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;On sépare les deux en builds Gradle distincts et on les relie via &amp;lt;code&amp;gt;includeBuild(&amp;quot;mon-plugin&amp;quot;)&amp;lt;/code&amp;gt; dans &amp;lt;code&amp;gt;settings.gradle.kts&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est déjà mieux. Le build du plugin est isolé. Mais le consommateur doit explicitement référencer le build externe — et la sortie de &amp;lt;code&amp;gt;./gradlew tasks&amp;lt;/code&amp;gt; à la racine dépend de la bonne configuration du composite. Le clonage n&amp;amp;#8217;est pas zero-config : il faut savoir que le plugin est dans un dossier à part, que le root le référence, etc.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-shell hljs&amp;quot; data-lang=&amp;quot;shell&amp;quot;&amp;gt;.
├── settings.gradle.kts   → includeBuild(&amp;quot;plugin-build/&amp;quot;)
├── build.gradle.kts      → plugins { id(&amp;quot;mon-plugin&amp;quot;) }
└── plugin-build/
    ├── settings.gradle.kts
    └── build.gradle.kts&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Je cherchais mieux. Beaucoup mieux.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_solution_deux_builds_indépendants_une_racine_consommateur&amp;quot;&amp;gt;La Solution : Deux Builds Indépendants, Une Racine Consommateur&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Voici le pattern que j&amp;amp;#8217;ai fini par adopter :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;.
├── settings.gradle.kts          ← racine consommateur
├── build.gradle.kts              ← 3 lignes : apply plugin + dogfood
├── gradle/
│   └── libs.versions.toml        ← catalogue du consommateur
├── {name}-plugin/                ← BUILD INDÉPENDANT
│   ├── gradlew                    ← son propre wrapper
│   ├── settings.gradle.kts        ← rootProject.name = &amp;quot;{name}-plugin&amp;quot;
│   ├── build.gradle.kts           ← java-gradle-plugin, signing, publish
│   ├── gradle/
│   │   ├── libs.versions.toml     ← catalogue du plugin
│   │   └── wrapper/
│   ├── src/                       ← sources du plugin
│   ├── .agents/                   ← gouvernance agent
│   └── *.adoc                     ← AGENT, PROMPT_REPRISE, snapshot, etc.
└── site.yml / slides-context.yml / ...   ← configs dogfood&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock important&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-important&amp;quot; title=&amp;quot;❗&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La clé : &amp;lt;code&amp;gt;{name}-plugin/&amp;lt;/code&amp;gt; est un projet Gradle &amp;lt;strong&amp;gt;complet et autonome&amp;lt;/strong&amp;gt;. Il a son propre wrapper, son propre settings, son propre catalogue de versions. Il se clone, se build, se teste, et se publie sans que le root soit au courant de son existence.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le root, lui, ne fait qu&amp;#39;&amp;lt;strong&amp;gt;une&amp;lt;/strong&amp;gt; chose : appliquer le plugin.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;plugins {
    alias(libs.plugins.bakery)
}

repositories {
    mavenLocal()
    mavenCentral()
}

bakery { configPath = file(&amp;quot;site.yml&amp;quot;).absolutePath }&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Trois lignes dans le cas de &amp;lt;code&amp;gt;bakery-gradle&amp;lt;/code&amp;gt;. Rien de plus. Zéro &amp;lt;code&amp;gt;include()&amp;lt;/code&amp;gt;, zéro &amp;lt;code&amp;gt;includeBuild()&amp;lt;/code&amp;gt;, zéro sous-projet. Un build Gradle classique qui applique un plugin comme n&amp;amp;#8217;importe quel consommateur le ferait.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_flux_de_travail&amp;quot;&amp;gt;Le Flux de Travail&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/architecture-deux-builds.svg&amp;quot; alt=&amp;quot;architecture deux builds&amp;quot; width=&amp;quot;1784&amp;quot; height=&amp;quot;5688&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_workflow_concret&amp;quot;&amp;gt;Le Workflow Concret&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-shell hljs&amp;quot; data-lang=&amp;quot;shell&amp;quot;&amp;gt;# 1. Builder le plugin
$ cd codebase-plugin
$ ./gradlew publishToMavenLocal

# 2. L&amp;#39;exercer depuis la racine
$ cd ..
$ ./gradlew indexCodebase queryCodebase snapshot

# La boucle est fermée. Le plugin est testé dans des conditions
# réelles de consommation, par le projet même qui l&amp;#39;héberge.&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_pourquoi_cette_architecture_ma_conquis&amp;quot;&amp;gt;Pourquoi Cette Architecture M&amp;amp;#8217;a Conquis&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Trois bénéfices qui, combinés, valent le coût de la « duplication » :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_1_dogfooding_natif_feedback_instantané&amp;quot;&amp;gt;1. Dogfooding Natif, Feedback Instantané&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le meilleur test d&amp;amp;#8217;un plugin Gradle, c&amp;amp;#8217;est de l&amp;amp;#8217;utiliser. Pas un test unitaire mocké. Pas un &amp;lt;code&amp;gt;GradleRunner&amp;lt;/code&amp;gt; avec un projet de test. Un &amp;lt;strong&amp;gt;vrai&amp;lt;/strong&amp;gt; build qui applique le plugin sur de vrais fichiers.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-shell hljs&amp;quot; data-lang=&amp;quot;shell&amp;quot;&amp;gt;$ git clone bakery-gradle
$ cd bakery-gradle
$ ./gradlew bake    # ← le plugin est exercé immédiatement&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Si le plugin est cassé, le build racine le dit. Pas besoin d&amp;amp;#8217;aller chercher un projet de test externe. Le dogfooding est la &amp;lt;strong&amp;gt;première&amp;lt;/strong&amp;gt; tâche que lance un nouveau contributeur. C&amp;amp;#8217;est le smoke test définitif.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock tip&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-tip&amp;quot; title=&amp;quot;💡&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La règle est simple : si la racine compile et que &amp;lt;code&amp;gt;./gradlew tasks&amp;lt;/code&amp;gt; affiche vos tâches de plugin, le plugin est fonctionnel. Pas de surprise en production.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_2_clonage_zero_config&amp;quot;&amp;gt;2. Clonage Zero-Config&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un &amp;lt;code&amp;gt;git clone &amp;amp;amp;&amp;amp;amp; ./gradlew tasks&amp;lt;/code&amp;gt; et le nouveau venu voit tout marcher sans rien configurer. Le &amp;lt;code&amp;gt;build.gradle.kts&amp;lt;/code&amp;gt; racine est la documentation vivante d&amp;amp;#8217;usage du plugin. Le &amp;lt;code&amp;gt;site.yml&amp;lt;/code&amp;gt; à côté montre la configuration attendue.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Comparez avec l&amp;amp;#8217;alternative : un README de trois paragraphes qui explique comment builder le plugin ET comment builder le projet de test. Un nouveau contributeur lit le README en diagonale, se trompe, ouvre une issue — alors que l&amp;amp;#8217;information pourrait être &amp;lt;strong&amp;gt;exécutable&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock important&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-important&amp;quot; title=&amp;quot;❗&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La documentation la plus robuste n&amp;amp;#8217;est pas celle qu&amp;amp;#8217;on lit. C&amp;amp;#8217;est celle qu&amp;amp;#8217;on &amp;lt;strong&amp;gt;exécute&amp;lt;/strong&amp;gt;. Le build racine est la documentation exécutable du plugin.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_3_builds_isolés_ci_indépendants&amp;quot;&amp;gt;3. Builds Isolés, CI Indépendants&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le plugin a son propre wrapper Gradle, son propre cycle de vie, ses propres tests. Vous pouvez :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Upgrader Gradle dans le plugin sans toucher au root&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Ajouter une dépendance dans le plugin sans qu&amp;amp;#8217;elle fuite dans le root&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Casser le plugin sans impacter le build racine (tant que vous ne&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;publiez pas la version cassée)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Avoir une CI qui build/test le plugin, et une autre qui exerce le&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;root — indépendamment&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;.github/workflows/
├── test-plugin.yml      → codebase-plugin/.gradlew build
├── test-root.yml        → .gradlew tasks (vérifie que le plugin est consommable)
└── publish.yml          → codebase-plugin/.gradlew publish&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_lanatomie_du_sous_dossier_name_plugin&amp;quot;&amp;gt;L&amp;amp;#8217;Anatomie du Sous-Dossier &amp;lt;code&amp;gt;{name}-plugin/&amp;lt;/code&amp;gt;&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Regardons de plus près ce qui vit dans le dossier du plugin :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;codebase-plugin/
├── gradlew                           ← wrapper indépendant
├── settings.gradle.kts               ← @Suppress(&amp;quot;UnstableApiUsage&amp;quot;)
│                                       + foobar-resolver-convention
├── build.gradle.kts                  ← java-gradle-plugin + signing + publish
├── gradle/
│   ├── libs.versions.toml            ← catalogue complet (langchain4j, pgvector...)
│   └── wrapper/
├── buildSrc/                         ← classes utilitaires buildSrc
│   ├── build.gradle.kts
│   └── src/main/kotlin/
│       ├── codebase/                 ← CodebaseYmlAnonymizer, CodebaseConfiguration
│       ├── benchmark/                ← BenchmarkConfig, BenchmarkProtocol
│       ├── readme/                   ← ReadmeYmlAnonymizer
│       ├── site/                     ← SiteYmlAnonymizer
│       ├── slider/                   ← SliderYmlAnonymizer
│       └── snapshot/                 ← SnapshotManager
├── src/
│   ├── main/kotlin/codebase/
│   │   ├── CodebasePlugin.kt         ← class Plugin&amp;amp;lt;Project&amp;amp;gt;
│   │   ├── rag/                      ← pgvector, embedding, anonymization...
│   │   ├── benchmark/                ← BenchmarkRunner, export, comparison...
│   │   └── walker/                   ← WorkspaceWalker
│   └── test/
│       ├── kotlin/codebase/scenarios/ ← steps Cucumber
│       ├── features/                  ← .feature files
│       └── resources/datasets/        ← fixtures .adoc, .yml, .json
├── .agents/                          ← gouvernance agent (INDEX, SESSIONS, etc.)
├── AGENT.adoc                        ← règles agent
├── PROMPT_REPRISE.adoc              ← mission session
├── BACKLOG.adoc                      ← backlog produit
├── snapshot.adoc                     ← snapshot auto-généré du projet
└── embeds.yml                        ← config RAG embeds&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Tout est là. Pas de dispersion entre la racine et le sous-dossier. Le développeur qui travaille sur le plugin n&amp;amp;#8217;a jamais besoin de quitter &amp;lt;code&amp;gt;codebase-plugin/&amp;lt;/code&amp;gt;. Le développeur qui utilise le plugin ne regarde que la racine — et le &amp;lt;code&amp;gt;build.gradle.kts&amp;lt;/code&amp;gt; de 3 lignes lui dit tout ce qu&amp;amp;#8217;il a besoin de savoir.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_catalogue_de_versions_deux_fichiers_distincts&amp;quot;&amp;gt;Le Catalogue de Versions : Deux Fichiers Distincts&amp;lt;/h3&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 37.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 37.5%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;gradle/libs.versions.toml&amp;lt;/code&amp;gt; (racine)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;{name}-plugin/gradle/libs.versions.toml&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Nombre de dépendances&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;2-3 (plugin + readme éventuellement)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;30+ (langchain4j, pgvector, cucumber&amp;amp;#8230;&amp;amp;#8203;)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Rôle&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Consommer le plugin&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Builder le plugin&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Qui le lit&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;L&amp;amp;#8217;utilisateur du plugin&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Le développeur du plugin&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le root a un catalogue volontairement minimal. Le plugin a un catalogue complet. La confusion est impossible : chaque build a son propre scope de dépendances.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;ℹ️&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Si vous avez déjà passé une heure à déboguer une collision de dépendances entre votre plugin et votre projet de test, vous comprenez la valeur de cette séparation. Les catalogues indépendants éliminent ce problème par construction.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_ce_quon_ne_fait_pas&amp;quot;&amp;gt;Ce Qu&amp;amp;#8217;On Ne Fait Pas&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce pattern n&amp;amp;#8217;est pas magique. Il impose une contrainte que je m&amp;amp;#8217;inflige volontiers :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Le root ne build pas le plugin.&amp;lt;/strong&amp;gt; Vous devez &amp;lt;code&amp;gt;publishToMavenLocal&amp;lt;/code&amp;gt; ou déployer sur un repository avant que le root puisse le consommer.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est un coût minime, et c&amp;amp;#8217;est la &amp;lt;strong&amp;gt;bonne&amp;lt;/strong&amp;gt; contrainte. Le root consomme le plugin comme un client externe — via Maven. Exactement comme le ferait un projet tiers. Si le plugin n&amp;amp;#8217;est pas publiable, le root vous le dit immédiatement.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-shell hljs&amp;quot; data-lang=&amp;quot;shell&amp;quot;&amp;gt;# La seule &amp;quot;friction&amp;quot; du pattern
$ cd codebase-plugin &amp;amp;amp;&amp;amp;amp; ./gradlew publishToMavenLocal &amp;amp;amp;&amp;amp;amp; cd ..
$ ./gradlew tasks --group=codebase&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_comparaison_les_trois_architectures_face_au_dogfooding&amp;quot;&amp;gt;Comparaison : Les Trois Architectures Face au Dogfooding&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 20%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 20%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 20%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 20%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 20%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Plugin isolé&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Monorepo &amp;lt;code&amp;gt;include()&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Composite &amp;lt;code&amp;gt;includeBuild()&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Racine + plugin indép.&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;git clone &amp;amp;amp;&amp;amp;amp; gradlew tasks&amp;lt;/code&amp;gt; donne les tâches du plugin&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;❌&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Build plugin indépendant du root&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;❌&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Catalogue versions séparé&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;❌&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Pas de &amp;lt;code&amp;gt;include()&amp;lt;/code&amp;gt; ni &amp;lt;code&amp;gt;includeBuild()&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;❌&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;❌&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Dogfood natif sans config&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;❌&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;⚠️&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;CI plugin indépendante&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;❌&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Le root est un exemple de conso réel&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;❌&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;⚠️&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La colonne de droite coche toutes les cases. C&amp;amp;#8217;est pour ça que je ne reviendrai plus en arrière.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_contrat_dag_un_build_racin_nimporte_jamais_depuis_un_sous_dossier&amp;quot;&amp;gt;Le Contrat DAG : Un Build Racin N&amp;amp;#8217;Importe Jamais Depuis un Sous-Dossier&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Cette architecture s&amp;amp;#8217;intègre naturellement dans le DAG N0→N3 de mon workspace. Le pattern est : &amp;lt;strong&amp;gt;le plugin N2 est le hub de ses propres dépendances, la racine N3 est un terminal qui applique des hubs&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/contrat-dag-architecture.svg&amp;quot; alt=&amp;quot;contrat dag architecture&amp;quot; width=&amp;quot;1746&amp;quot; height=&amp;quot;5508&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le &amp;lt;code&amp;gt;codebase-gradle/build.gradle.kts&amp;lt;/code&amp;gt; fait 6 lignes. Pas de &amp;lt;code&amp;gt;src/&amp;lt;/code&amp;gt;, pas de &amp;lt;code&amp;gt;buildSrc/&amp;lt;/code&amp;gt;, pas de &amp;lt;code&amp;gt;gradle/rag-bench.gradle.kts&amp;lt;/code&amp;gt;. Juste &amp;lt;code&amp;gt;plugins { alias(libs.plugins.codebase) }&amp;lt;/code&amp;gt; et les repositories. Toute la complexité vit dans &amp;lt;code&amp;gt;codebase-plugin/&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_conclusion_la_duplication_apparente_qui_fait_gagner_du_temps&amp;quot;&amp;gt;Conclusion : La Duplication Apparente Qui Fait Gagner du Temps&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Quand je montre cette structure à quelqu&amp;amp;#8217;un, la première réaction est souvent : « Mais tu as deux &amp;lt;code&amp;gt;gradlew&amp;lt;/code&amp;gt;, deux &amp;lt;code&amp;gt;settings.gradle.kts&amp;lt;/code&amp;gt;, deux &amp;lt;code&amp;gt;libs.versions.toml&amp;lt;/code&amp;gt; — c&amp;amp;#8217;est de la duplication ! »&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Oui. Et non.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La « duplication », c&amp;amp;#8217;est reproduire la même information à deux endroits. Ici, ce sont deux fichiers &amp;lt;strong&amp;gt;distincts&amp;lt;/strong&amp;gt; qui servent deux usages &amp;lt;strong&amp;gt;distincts&amp;lt;/strong&amp;gt; : le catalogue du plugin (30+ dépendances pour builder) et le catalogue de la racine (2-3 dépendances pour consommer). Le wrapper du plugin (version verrouillée pour le développement) et le wrapper de la racine (version potentiellement différente, pour l&amp;amp;#8217;exercice du plugin).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce n&amp;amp;#8217;est pas de la duplication. C&amp;amp;#8217;est de la &amp;lt;strong&amp;gt;séparation des responsabilités&amp;lt;/strong&amp;gt; appliquée au système de build. Chaque build fait une chose, et une seule. La racine consomme. Le plugin se build.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le coût ? Une commande &amp;lt;code&amp;gt;publishToMavenLocal&amp;lt;/code&amp;gt; entre le build du plugin et le build de la racine. Le gain ? Une clarté architecturale qui supprime des heures de débogage en aval.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Depuis que j&amp;amp;#8217;ai déployé ce pattern sur &amp;lt;code&amp;gt;bakery-gradle&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;plantuml-gradle&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;codebase-gradle&amp;lt;/code&amp;gt;, et les autres plugins de &amp;lt;code&amp;gt;foundry/public/&amp;lt;/code&amp;gt;, je n&amp;amp;#8217;ai plus jamais hésité en ouvrant un terminal dans un de mes dépôts. Le premier réflexe — &amp;lt;code&amp;gt;./gradlew tasks&amp;lt;/code&amp;gt; — marche toujours, donne toujours les bonnes tâches, et me dit instantanément si tout est sain.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est ça, la bonne architecture. Elle ne se lit pas dans un README. Elle s&amp;amp;#8217;éprouve dans un terminal, en moins de dix secondes.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_références&amp;quot;&amp;gt;Références&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0105_integrer_graphify_workflow_gradle_post.html&amp;quot;&amp;gt;Article 0105 — Intégrer Graphify dans un workflow Gradle&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0117_granularisation_oss_css_repositorie_workspace_post.html&amp;quot;&amp;gt;Article 0117 — La Granularisation OSS/CSS&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0123_knowledge_graph_moteur_recommandation_articles_connexes_post.html&amp;quot;&amp;gt;Article 0123 — Le Knowledge Graph comme moteur de recommandation&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Le Knowledge Graph comme moteur de recommandation : comment j&#39;ai tué les « articles connexes » chronologiques</title>
            <link >https://cheroliv.com/blog/2026/0123_knowledge_graph_moteur_recommandation_articles_connexes_post.html</link>
            <pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0123_knowledge_graph_moteur_recommandation_articles_connexes_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_scène_mardi_12_mai_17h30&amp;quot;&amp;gt;La Scène : Mardi 12 Mai, 17h30&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_diagnostic_trois_types_de_relations_quaucun_template_ne_voit&amp;quot;&amp;gt;Le Diagnostic : Trois Types de Relations Qu&amp;amp;#8217;Aucun Template Ne Voit&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_solution_un_pipeline_gradle_pas_un_appel_llm_à_chaud&amp;quot;&amp;gt;La Solution : Un Pipeline Gradle, Pas un Appel LLM à Chaud&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_larchitecture_bakery_importe_graphify_pas_engine&amp;quot;&amp;gt;L&amp;amp;#8217;Architecture : Bakery Importe Graphify, Pas Engine&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_pipeline_scan_graphe_template&amp;quot;&amp;gt;Le Pipeline : Scan → Graphe → Template&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_fallback_chronologique&amp;quot;&amp;gt;Fallback Chronologique&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_lontologie_émergente_quand_les_articles_se_regroupent_sans_se_connaître&amp;quot;&amp;gt;L&amp;amp;#8217;Ontologie Émergente : Quand les Articles Se Regroupent Sans Se Connaître&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_contrat_dag_qui_importe_qui&amp;quot;&amp;gt;Le Contrat DAG : Qui Importe Qui&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ce_quon_gagne_et_ce_quon_ne_gagne_pas&amp;quot;&amp;gt;Ce Qu&amp;amp;#8217;on Gagne (Et Ce Qu&amp;amp;#8217;on Ne Gagne Pas)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_perspectives_le_blog_comme_knowledge_graph_public&amp;quot;&amp;gt;Perspectives : Le Blog Comme Knowledge Graph Public&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_conclusion_le_système_de_fichiers_sait_ce_que_le_template_ignore&amp;quot;&amp;gt;Conclusion : Le Système de Fichiers Sait Ce Que le Template Ignore&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_références&amp;quot;&amp;gt;Références&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 14 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Vous lisez un article sur l&amp;amp;#8217;intégration de pgvector avec LangChain4j. En bas de page, JBake vous suggère « Articles connexes ». Vous cliquez. C&amp;amp;#8217;est un article sur&amp;amp;#8230;&amp;amp;#8203; la configuration de Kitty Terminal. Le seul point commun entre les deux ? Ils ont été publiés à moins de quinze jours d&amp;amp;#8217;écart. Ce n&amp;amp;#8217;est pas une recommandation. C&amp;amp;#8217;est un calendrier déguisé en éditorial.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_scène_mardi_12_mai_17h30&amp;quot;&amp;gt;La Scène : Mardi 12 Mai, 17h30&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Je relis un de mes articles — &amp;lt;a href=&amp;quot;0106_knowledge_graph_outil_comprehension_codebase_post.html&amp;quot;&amp;gt;celui sur le Knowledge Graph comme outil de compréhension de codebase&amp;lt;/a&amp;gt;. Le contenu est dense : nœuds, arêtes, communautés, PlantUML, onboarding. Un article technique de 15 minutes de lecture qui mobilise &amp;lt;code&amp;gt;graphify-gradle&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;plantuml-gradle&amp;lt;/code&amp;gt;, et les concepts de topologie de graphe.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;En bas de page, les « Articles connexes » me proposent :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Un article sur Firebase Contact Form (0113)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Un article sur le mécanisme Eager/Lazy (0108)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Un article sur la migration Gradle script → plugin (0102)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Un article sur le cumul d&amp;amp;#8217;abonnements Ollama Pro (0120)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Trois de ces quatre articles n&amp;amp;#8217;ont &amp;lt;strong&amp;gt;aucun&amp;lt;/strong&amp;gt; rapport avec le Knowledge Graph. Ils sont là parce qu&amp;amp;#8217;ils sont les derniers publiés — voisinage temporel, pas voisinage sémantique.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Je regarde le template &amp;lt;code&amp;gt;post.thyme&amp;lt;/code&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-xhtml hljs&amp;quot; data-lang=&amp;quot;xhtml&amp;quot;&amp;gt;&amp;amp;lt;!-- Articles connexes (liens internes SEO) --&amp;amp;gt;
&amp;amp;lt;th:block th:each=&amp;quot;post,postStat : ${published_posts}&amp;quot;&amp;amp;gt;
    &amp;amp;lt;th:block th:if=&amp;quot;${!post.uri.equals(content.uri) and postStat.index lt 4}&amp;quot;&amp;amp;gt;
        ...
    &amp;amp;lt;/th:block&amp;amp;gt;
&amp;amp;lt;/th:block&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;published_posts&amp;lt;/code&amp;gt; est une liste chronologique. &amp;lt;code&amp;gt;postStat.index lt 4&amp;lt;/code&amp;gt; prend les quatre premiers qui ne sont pas le post courant. C&amp;amp;#8217;est tout. Aucune logique de similarité. Aucune notion de contenu. Juste une boucle &amp;lt;code&amp;gt;for&amp;lt;/code&amp;gt; déguisée en recommandation.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock warning&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-warning&amp;quot; title=&amp;quot;⚠️&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce n&amp;amp;#8217;est pas un bug de JBake. C&amp;amp;#8217;est le comportement par défaut de tout générateur de site statique : la liste des posts est plate et ordonnée par date. Le template fait ce qu&amp;amp;#8217;il peut avec ce qu&amp;amp;#8217;il a.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mais ce n&amp;amp;#8217;est pas une raison pour l&amp;amp;#8217;accepter.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_diagnostic_trois_types_de_relations_quaucun_template_ne_voit&amp;quot;&amp;gt;Le Diagnostic : Trois Types de Relations Qu&amp;amp;#8217;Aucun Template Ne Voit&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mon corpus d&amp;amp;#8217;articles — 23 posts en 4 mois — a une structure riche que le template chronologique écrase complètement :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Références explicites&amp;lt;/strong&amp;gt; : j&amp;amp;#8217;utilise &amp;lt;code&amp;gt;xref:&amp;lt;/code&amp;gt; massivement dans mes articles.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;article 0122 référence 0106 (knowledge graph) et 0116 (compartimentage épistémique). Ces liens sont du &amp;lt;strong&amp;gt;hard linking&amp;lt;/strong&amp;gt; éditorial — j&amp;amp;#8217;ai délibérément décidé de connecter ces concepts.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Tags partagés&amp;lt;/strong&amp;gt; : chaque article a des &amp;lt;code&amp;gt;:jbake-tags:&amp;lt;/code&amp;gt;. L&amp;amp;#8217;article sur&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Graphify + PlantUML (0105) a &amp;lt;code&amp;gt;gradle, graphify, plantuml, knowledge-graph&amp;lt;/code&amp;gt;. L&amp;amp;#8217;article sur le Knowledge Graph (0106) a &amp;lt;code&amp;gt;knowledge-graph, graphify, plantuml&amp;lt;/code&amp;gt;. Trois tags en commun sur sept — 43% de recouvrement.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Entités nommées co-occurrentes&amp;lt;/strong&amp;gt; : « pgvector », « RAG », « embedding »&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;apparaissent ensemble dans quatre articles différents. « LangChain4j », « Ollama », « plugin Gradle » dans six autres. Ce ne sont pas des tags déclarés — ce sont des &amp;lt;strong&amp;gt;patterns émergents&amp;lt;/strong&amp;gt; du corpus que seul un NLP peut détecter.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/trois-couches-relation-articles.svg&amp;quot; alt=&amp;quot;trois couches relation articles&amp;quot; width=&amp;quot;1752&amp;quot; height=&amp;quot;5492&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Aujourd&amp;amp;#8217;hui, mon site n&amp;amp;#8217;utilise &amp;lt;strong&amp;gt;aucune&amp;lt;/strong&amp;gt; de ces trois couches. Il utilise la couche zéro : l&amp;amp;#8217;ordre d&amp;amp;#8217;insertion dans une liste Java.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_solution_un_pipeline_gradle_pas_un_appel_llm_à_chaud&amp;quot;&amp;gt;La Solution : Un Pipeline Gradle, Pas un Appel LLM à Chaud&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La première tentation serait d&amp;amp;#8217;appeler un LLM au moment du bake : « Pour cet article, trouve les trois articles les plus similaires dans le corpus. » Ne faites pas ça.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock important&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-important&amp;quot; title=&amp;quot;❗&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un appel LLM à chaque &amp;lt;code&amp;gt;./gradlew bake&amp;lt;/code&amp;gt; coûte du temps, de l&amp;amp;#8217;argent, et introduit de la non-déterminisme dans votre build. La réponse du LLM peut changer entre deux builds sans que le contenu ait changé. Votre CI devient non reproductible, vos tests deviennent flaky.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La solution est déterministe : un pipeline Gradle qui pré-calcule le graphe de similarité et le stocke dans &amp;lt;code&amp;gt;graph.json&amp;lt;/code&amp;gt;. Le template lit le résultat — jamais il ne déclenche un calcul.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_larchitecture_bakery_importe_graphify_pas_engine&amp;quot;&amp;gt;L&amp;amp;#8217;Architecture : Bakery Importe Graphify, Pas Engine&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est le point d&amp;amp;#8217;architecture le plus important. La tentation serait de câbler la collaboration dans &amp;lt;code&amp;gt;engine/build.gradle.kts&amp;lt;/code&amp;gt; : engine applique graphify pour le scan, bakery pour le bake, et engine fait le pont entre les deux.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est un anti-pattern. Engine est un &amp;lt;strong&amp;gt;terminal consommateur&amp;lt;/strong&amp;gt; — il applique des plugins, il n&amp;amp;#8217;implémente pas de logique métier. La règle est : &amp;lt;strong&amp;gt;la charge de la preuve est sur le plugin propriétaire.&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/bakery-import-graphify.svg&amp;quot; alt=&amp;quot;bakery import graphify&amp;quot; width=&amp;quot;1761&amp;quot; height=&amp;quot;5700&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Figure 1. Architecture correcte — Bakery importe Graphify&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le contrat DAG est respecté : bakery (N2) importe graphify (N0), N2 &amp;amp;gt; N0, aucune violation. Engine (N3) importe bakery (N2), N3 &amp;amp;gt; N2, OK.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Engine n&amp;amp;#8217;a &amp;lt;strong&amp;gt;aucune&amp;lt;/strong&amp;gt; ligne de code qui référence &amp;lt;code&amp;gt;graph.json&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;relatedPosts&amp;lt;/code&amp;gt;, ou toute autre notion de similarité. Il applique bakery, point. La collaboration est interne à bakery.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_pipeline_scan_graphe_template&amp;quot;&amp;gt;Le Pipeline : Scan → Graphe → Template&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Voici le pipeline complet en trois étapes :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Scan&amp;lt;/strong&amp;gt; (graphify) : &amp;lt;code&amp;gt;graphify-plugin&amp;lt;/code&amp;gt; scanne le workspace. Dans sa&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;forme actuelle, il détecte déjà les &amp;lt;code&amp;gt;xref:&amp;lt;/code&amp;gt; entre &amp;lt;code&amp;gt;.adoc&amp;lt;/code&amp;gt; et les expose dans &amp;lt;code&amp;gt;graph.json&amp;lt;/code&amp;gt; comme des edges de type &amp;lt;code&amp;gt;reference&amp;lt;/code&amp;gt;.&amp;lt;br&amp;gt;
On l&amp;amp;#8217;enrichit pour le contenu éditorial : * Parse les métadonnées JBake (&amp;lt;code&amp;gt;:jbake-tags:&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;:jbake-description:&amp;lt;/code&amp;gt;) de chaque &amp;lt;code&amp;gt;.adoc&amp;lt;/code&amp;gt; du blog * Calcule les co-occurrences de tags → edges &amp;lt;code&amp;gt;tag_cooccurrence&amp;lt;/code&amp;gt; avec poids * Extrait les entités nommées des descriptions via TF-IDF → edges &amp;lt;code&amp;gt;entity_overlap&amp;lt;/code&amp;gt; * Injecte une section &amp;lt;code&amp;gt;blog_articles&amp;lt;/code&amp;gt; dans le &amp;lt;code&amp;gt;graph.json&amp;lt;/code&amp;gt; existant&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// Extrait de l&amp;#39;enrichissement graphify pour le blog
fun enrichBlogSection(graphJson: File, blogDir: File): GraphJson {
    val articles = blogDir.listFiles { f -&amp;amp;gt; f.extension == &amp;quot;adoc&amp;quot; }
        .map { parseJbakeMetadata(it) }

    val nodes = articles.map { ArticleNode(it.slug, it.title, it.tags) }
    val edges = mutableListOf&amp;amp;lt;GraphEdge&amp;amp;gt;()

    // Couche 1 : xref (déjà fait par scanWorkspace)

    // Couche 2 : co-occurrences de tags
    for (a in articles) {
        for (b in articles) {
            if (a.slug == b.slug) continue
            val common = a.tags.intersect(b.tags)
            if (common.isNotEmpty()) {
                edges.add(GraphEdge(
                    source = a.slug,
                    target = b.slug,
                    type = &amp;quot;tag_cooccurrence&amp;quot;,
                    weight = common.size.toDouble() / (a.tags.size + b.tags.size)
                ))
            }
        }
    }

    return graphJson.copy(
        blogArticles = BlogSection(nodes, edges)
    )
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Bake&amp;lt;/strong&amp;gt; (bakery) : au moment du &amp;lt;code&amp;gt;./gradlew bake&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;BakeryPlugin&amp;lt;/code&amp;gt; lit&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;graph.json&amp;lt;/code&amp;gt; et résout les articles connexes pour chaque post.&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// BakeryPlugin — résolution des articles connexes
fun resolveRelatedPosts(
    currentSlug: String,
    graph: GraphJson,
    maxResults: Int = 4
): List&amp;amp;lt;RelatedPost&amp;amp;gt; {
    val edges = graph.blogArticles.edges
        .filter { it.source == currentSlug || it.target == currentSlug }

    return edges
        .sortedByDescending { it.weight }
        .take(maxResults)
        .map { edge -&amp;amp;gt;
            val relatedSlug = if (edge.source == currentSlug) edge.target else edge.source
            graph.blogArticles.nodes.first { it.slug == relatedSlug }
        }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Template&amp;lt;/strong&amp;gt; (&amp;lt;code&amp;gt;post.thyme&amp;lt;/code&amp;gt;) : le modèle JBake reçoit maintenant une map&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;structurée au lieu d&amp;amp;#8217;une liste chronologique plate.&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-xhtml hljs&amp;quot; data-lang=&amp;quot;xhtml&amp;quot;&amp;gt;&amp;amp;lt;!-- Articles connexes basés sur le Knowledge Graph --&amp;amp;gt;
&amp;amp;lt;th:block th:if=&amp;quot;${relatedPosts != null and !relatedPosts.empty}&amp;quot;&amp;amp;gt;
    &amp;amp;lt;section class=&amp;quot;mt-5 pt-4 border-top&amp;quot;&amp;amp;gt;
        &amp;amp;lt;h2 class=&amp;quot;h4 mb-3&amp;quot;&amp;amp;gt;Articles connexes&amp;amp;lt;/h2&amp;amp;gt;
        &amp;amp;lt;th:block th:each=&amp;quot;related : ${relatedPosts}&amp;quot;&amp;amp;gt;
            &amp;amp;lt;div class=&amp;quot;mb-2&amp;quot;&amp;amp;gt;
                &amp;amp;lt;a th:href=&amp;quot;${content.rootpath} + ${related.uri}&amp;quot;
                   th:text=&amp;quot;${related.title}&amp;quot; class=&amp;quot;fw-semibold&amp;quot;&amp;amp;gt;&amp;amp;lt;/a&amp;amp;gt;
                &amp;amp;lt;br/&amp;amp;gt;
                &amp;amp;lt;small class=&amp;quot;text-muted&amp;quot;&amp;amp;gt;
                    &amp;amp;lt;th:block th:each=&amp;quot;reason,iterStat : ${related.reasons}&amp;quot;&amp;amp;gt;
                        &amp;amp;lt;span class=&amp;quot;badge bg-light text-dark&amp;quot;
                              th:text=&amp;quot;${reason}&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;
                    &amp;amp;lt;/th:block&amp;amp;gt;
                &amp;amp;lt;/small&amp;amp;gt;
            &amp;amp;lt;/div&amp;amp;gt;
        &amp;amp;lt;/th:block&amp;amp;gt;
    &amp;amp;lt;/section&amp;amp;gt;
&amp;amp;lt;/th:block&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le template est le même — il ne sait pas &amp;lt;strong&amp;gt;d&amp;amp;#8217;où&amp;lt;/strong&amp;gt; viennent les données. Seul le contrat entre bakery et JBake a changé : &amp;lt;code&amp;gt;published_posts&amp;lt;/code&amp;gt; (liste chronologique) devient &amp;lt;code&amp;gt;relatedPosts&amp;lt;/code&amp;gt; (map pondérée par le graphe).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;ℹ️&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le badge « raison » (ex: &amp;lt;code&amp;gt;xref 0122&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;tag:gradle&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;cluster:pgvector-rag&amp;lt;/code&amp;gt;) explique au lecteur &amp;lt;strong&amp;gt;pourquoi&amp;lt;/strong&amp;gt; cet article est connexe. Ce n&amp;amp;#8217;est pas juste de la transparence — c&amp;amp;#8217;est de la pédagogie sur la topologie de votre propre contenu.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_fallback_chronologique&amp;quot;&amp;gt;Fallback Chronologique&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Si &amp;lt;code&amp;gt;graph.json&amp;lt;/code&amp;gt; est absent (build local sans scan préalable, premier déploiement, CI qui n&amp;amp;#8217;a pas encore intégré le scan graphify), le template doit dégrader gracieusement :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;fun resolveRelatedPosts(currentSlug: String, graph: GraphJson?): List&amp;amp;lt;RelatedPost&amp;amp;gt; {
    if (graph != null &amp;amp;amp;&amp;amp;amp; graph.blogArticles != null) {
        return resolveFromGraph(currentSlug, graph)
    }
    // Fallback chronologique — même comportement qu&amp;#39;aujourd&amp;#39;hui
    logger.warn(&amp;quot;[bakery] graph.json absent — fallback chronologique&amp;quot;)
    return resolveFromChronology(currentSlug)
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le comportement par défaut est identique au comportement actuel. Le moteur de recommandation est une &amp;lt;strong&amp;gt;amélioration progressive&amp;lt;/strong&amp;gt; — pas un breaking change.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_lontologie_émergente_quand_les_articles_se_regroupent_sans_se_connaître&amp;quot;&amp;gt;L&amp;amp;#8217;Ontologie Émergente : Quand les Articles Se Regroupent Sans Se Connaître&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La couche la plus intéressante est la troisième : l&amp;amp;#8217;ontologie émergente. Des articles qui ne se citent pas, qui n&amp;amp;#8217;ont pas les mêmes tags, mais qui &amp;lt;strong&amp;gt;parlent de la même chose&amp;lt;/strong&amp;gt; sans le savoir.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Prenons un exemple concret. Trois articles de mon corpus :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;0119 — Benchmark DGX Spark vs Cloud Abonnement LLM&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;0121 — Plugin Gradle Piloter Deux Instances Ollama Pro&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;0122 — Ratio Efficacité 27x 45x Flotte Experts IA&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ces trois articles n&amp;amp;#8217;ont &amp;lt;strong&amp;gt;aucun&amp;lt;/strong&amp;gt; xref entre eux. Leurs tags ne se recoupent qu&amp;amp;#8217;à 20% (« ollama », « llm » communs). Mais un NLP léger sur les descriptions révèle un cluster évident : « coût », « abonnement », « cloud », « GPU », « API key », « Ollama Pro », « efficacité », « ratio ».&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ils forment un cluster ontologique : &amp;lt;strong&amp;gt;l&amp;amp;#8217;économie du LLM self-hosted vs cloud&amp;lt;/strong&amp;gt;. Ce cluster n&amp;amp;#8217;est déclaré nulle part. Il émerge du corpus.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/cluster-ontologique-exemple.svg&amp;quot; alt=&amp;quot;cluster ontologique exemple&amp;quot; width=&amp;quot;1739&amp;quot; height=&amp;quot;5456&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce cluster ontologique devient un edge composite dans &amp;lt;code&amp;gt;graph.json&amp;lt;/code&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-json hljs&amp;quot; data-lang=&amp;quot;json&amp;quot;&amp;gt;{
  &amp;quot;source&amp;quot;: &amp;quot;0119-benchmark-dgx-spark&amp;quot;,
  &amp;quot;target&amp;quot;: &amp;quot;cluster:economie-llm&amp;quot;,
  &amp;quot;type&amp;quot;: &amp;quot;entity_cluster&amp;quot;,
  &amp;quot;weight&amp;quot;: 0.73,
  &amp;quot;metadata&amp;quot;: {
    &amp;quot;clusterLabel&amp;quot;: &amp;quot;Économie LLM Self-Hosted vs Cloud&amp;quot;,
    &amp;quot;commonEntities&amp;quot;: [&amp;quot;coût&amp;quot;, &amp;quot;GPU&amp;quot;, &amp;quot;abonnement&amp;quot;, &amp;quot;Ollama Pro&amp;quot;, &amp;quot;ratio&amp;quot;],
    &amp;quot;articlesInCluster&amp;quot;: [
      &amp;quot;0119-benchmark-dgx-spark&amp;quot;,
      &amp;quot;0121-ollama-pro-deux-instances&amp;quot;,
      &amp;quot;0122-ratio-efficacite-flotte-experts&amp;quot;
    ]
  }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le NLP est volontairement léger — TF-IDF + cosine similarity sur les descriptions. Pas besoin de BERT, pas besoin de modèle de langage. Le corpus fait 23 articles, la matrice de similarité tient dans un fichier JSON de 50 Ko.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock tip&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-tip&amp;quot; title=&amp;quot;💡&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La puissance du NLP ne vient pas de la sophistication de l&amp;amp;#8217;algorithme, mais de la &amp;lt;strong&amp;gt;taille du corpus&amp;lt;/strong&amp;gt; et de la &amp;lt;strong&amp;gt;qualité des descriptions&amp;lt;/strong&amp;gt;. Une &amp;lt;code&amp;gt;:jbake-description:&amp;lt;/code&amp;gt; bien écrite de 150 caractères contient plus de signal pour TF-IDF qu&amp;amp;#8217;un article entier de 3000 mots.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_contrat_dag_qui_importe_qui&amp;quot;&amp;gt;Le Contrat DAG : Qui Importe Qui&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est le point où la discipline architecturale paie. Le DAG N0→N3 défini dans &amp;lt;code&amp;gt;engine/build.gradle.kts&amp;lt;/code&amp;gt; donne une règle simple : aucun projet n&amp;amp;#8217;importe un projet de niveau supérieur.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 18.1818%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 27.2728%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Plugin consommateur&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Plugin importé&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Niveau consommateur&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Niveau importé&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Valide ?&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;bakery-gradle&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;graphify-gradle&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;N2&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;N0&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅ N2 &amp;amp;gt; N0 — OK&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;engine&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;bakery-gradle&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;N3&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;N2&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅ N3 &amp;amp;gt; N2 — OK&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;engine&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;graphify-gradle&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;N3&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;N0&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅ Technique OK, mais &amp;lt;strong&amp;gt;conceptuellement faux&amp;lt;/strong&amp;gt; — la collaboration est interne à bakery&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Engine applique bakery. Bakery applique graphify. C&amp;amp;#8217;est tout. Si un jour je veux ajouter le vector store codebase (N1) pour de la recherche sémantique cross-corpus, bakery l&amp;amp;#8217;importe aussi. Engine ne change pas.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock important&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-important&amp;quot; title=&amp;quot;❗&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le pattern est : &amp;lt;strong&amp;gt;le plugin N2 est le hub de ses propres dépendances&amp;lt;/strong&amp;gt;. Engine N3 n&amp;amp;#8217;est pas un hub — c&amp;amp;#8217;est un terminal qui applique des hubs.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_ce_quon_gagne_et_ce_quon_ne_gagne_pas&amp;quot;&amp;gt;Ce Qu&amp;amp;#8217;on Gagne (Et Ce Qu&amp;amp;#8217;on Ne Gagne Pas)&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le gain principal est éditorial, pas technique :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 50%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 50%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Avant&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Après&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Articles connexes = 4 derniers posts&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Articles connexes = top 4 par poids dans le Knowledge Graph&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Lecteur lit du RAG → recommandation Kitty Terminal&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Lecteur lit du RAG → recommandation pgvector, chunking, vector store&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Zéro transparence sur le pourquoi&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Badge &amp;lt;code&amp;gt;xref 0122&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;tag:gradle&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;cluster:rag&amp;lt;/code&amp;gt; visible&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;JBake standard, zéro effort, zéro valeur&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Pipeline Gradle déterministe, reproductible, testable&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Aucune courbe d&amp;amp;#8217;apprentissage pour le lecteur&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Le lecteur découvre la &amp;lt;strong&amp;gt;topologie&amp;lt;/strong&amp;gt; de mon contenu&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce qu&amp;amp;#8217;on &amp;lt;strong&amp;gt;ne&amp;lt;/strong&amp;gt; gagne pas :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Ce n&amp;amp;#8217;est pas un « vrai » moteur de recommandation (pas de collaborative&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;filtering, pas d&amp;amp;#8217;A/B testing, pas de feedback loop)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;La qualité dépend de la richesse des métadonnées JBake — si vos&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;descriptions sont vides, TF-IDF ne voit rien&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le NLP est offline — les nouveaux articles ne sont clusterisés qu&amp;amp;#8217;au&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;prochain scan (c&amp;amp;#8217;est bien : le build reste déterministe)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_perspectives_le_blog_comme_knowledge_graph_public&amp;quot;&amp;gt;Perspectives : Le Blog Comme Knowledge Graph Public&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Cette fonctionnalité ouvre une perspective plus large : et si &amp;lt;code&amp;gt;cheroliv.com&amp;lt;/code&amp;gt; devenait lui-même un &amp;lt;strong&amp;gt;knowledge graph navigable&amp;lt;/strong&amp;gt; ?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Les articles sont des nœuds. Les tags sont des communautés. Les xref sont des arêtes. Le lecteur ne lit plus un article isolé — il navigue dans un &amp;lt;strong&amp;gt;graphe de connaissance&amp;lt;/strong&amp;gt; dont l&amp;amp;#8217;article courant est le point d&amp;amp;#8217;entrée.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Imaginez une page d&amp;amp;#8217;accueil qui affiche non pas la liste chronologique des derniers posts, mais une &amp;lt;strong&amp;gt;carte du corpus&amp;lt;/strong&amp;gt; : clusters ontologiques, articles pivots (ceux avec le plus d&amp;amp;#8217;arêtes), chemins de lecture recommandés (« Si vous avez aimé l&amp;amp;#8217;article sur Graphify, lisez ensuite celui sur le Knowledge Graph comme outil de compréhension »).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce n&amp;amp;#8217;est plus un blog. C&amp;amp;#8217;est un &amp;lt;strong&amp;gt;atlas sémantique&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Et ce n&amp;amp;#8217;est pas de la science-fiction. Le &amp;lt;code&amp;gt;graph.json&amp;lt;/code&amp;gt; existe déjà. Il ne lui manque que l&amp;amp;#8217;interface de navigation.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_conclusion_le_système_de_fichiers_sait_ce_que_le_template_ignore&amp;quot;&amp;gt;Conclusion : Le Système de Fichiers Sait Ce Que le Template Ignore&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce que j&amp;amp;#8217;ai conçu ce mardi soir, c&amp;amp;#8217;est le remplacement d&amp;amp;#8217;une heuristique paresseuse (l&amp;amp;#8217;ordre chronologique) par une représentation fidèle de la structure de mon corpus (le Knowledge Graph).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le template &amp;lt;code&amp;gt;post.thyme&amp;lt;/code&amp;gt; ne change pas. Ce qui change, c&amp;amp;#8217;est ce qu&amp;amp;#8217;on lui donne à manger. Avant : une liste Java ordonnée par &amp;lt;code&amp;gt;date&amp;lt;/code&amp;gt;. Après : un graphe pondéré issu de trois couches d&amp;amp;#8217;analyse — xrefs, co-occurrences de tags, et ontologie émergente par NLP.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La boucle est bouclée. graphify scanne le workspace. Bakery lit le graphe et nourrit le template. Le lecteur voit des recommandations pertinentes. Et engine — le chef d&amp;amp;#8217;orchestre — ne sait même pas que tout ça existe.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est ça, la bonne architecture. Chaque plugin fait une chose. Et le terminal consommateur n&amp;amp;#8217;a pas besoin de savoir comment.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_références&amp;quot;&amp;gt;Références&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0105_integrer_graphify_workflow_gradle_post.html&amp;quot;&amp;gt;Article 0105 — Intégrer Graphify dans un workflow Gradle&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0106_knowledge_graph_outil_comprehension_codebase_post.html&amp;quot;&amp;gt;Article 0106 — Le Knowledge Graph comme outil de compréhension&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0117_granularisation_oss_css_repositorie_workspace_post.html&amp;quot;&amp;gt;Article 0117 — La Granularisation OSS/CSS&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0121_plugin_gradle_piloter_deux_instances_ollama_pro_post.html&amp;quot;&amp;gt;Article 0121 — Plugin Gradle Piloter Deux Instances Ollama Pro&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0122_ratio_efficacite_27x_45x_flotte_experts_ia_vs_claude_gpt_post.html&amp;quot;&amp;gt;Article 0122 — 27× à 45× plus efficace : flotte d&amp;amp;#8217;experts IA&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>27× à 45× plus efficace que Claude et GPT : comment une flotte de 23 experts IA fine-tunés écrase le marché</title>
            <link >https://cheroliv.com/blog/2026/0122_ratio_efficacite_27x_45x_flotte_experts_ia_vs_claude_gpt_post.html</link>
            <pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0122_ratio_efficacite_27x_45x_flotte_experts_ia_vs_claude_gpt_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_problème_pourquoi_le_fine_tune_et_pas_le_rag&amp;quot;&amp;gt;Le problème : pourquoi le fine-tune et pas le RAG ?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_lidée_une_flotte_dexperts_pas_un_seul_modèle&amp;quot;&amp;gt;L&amp;amp;#8217;idée : une flotte d&amp;amp;#8217;experts, pas un seul modèle&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_codebase_sous_la_loupe_7_900_fichiers_144_000_lignes&amp;quot;&amp;gt;La codebase sous la loupe : 7 900 fichiers, 144 000 lignes&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_linférence_23_modèles_sur_ollama_cloud_à_partir_de_17mois&amp;quot;&amp;gt;L&amp;amp;#8217;inférence : 23 modèles sur Ollama Cloud à partir de 17€/mois&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_on_démarre_à_17mois_on_scale_si_besoin&amp;quot;&amp;gt;On démarre à 17€/mois, on scale si besoin&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_routing_en_pratique&amp;quot;&amp;gt;Le routing en pratique&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 22 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Quand on utilise un LLM pour du développement logiciel au quotidien, on finit toujours par butter sur le même mur : le modèle ne connaît pas &amp;lt;strong&amp;gt;votre&amp;lt;/strong&amp;gt; codebase. Il ne sait pas que vous utilisez tel pattern de &amp;lt;a href=&amp;quot;https://fr.wikipedia.org/wiki/Graphe_orient%C3%A9_acyclique&amp;quot;&amp;gt;DAG&amp;lt;/a&amp;gt;, telle convention Gradle, telle stratification épistémique dans vos &amp;lt;a href=&amp;quot;https://fr.wikipedia.org/wiki/AsciiDoc&amp;quot;&amp;gt;&amp;lt;code&amp;gt;.adoc&amp;lt;/code&amp;gt;&amp;lt;/a&amp;gt;. Alors on lui injecte du contexte, on répète, on corrige, on itère. Et le temps — et l&amp;amp;#8217;argent — passent.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ai donc posé la question brutalement : combien coûterait une équipe de modèles fine-tunés sur mon workspace, capables de cracher du code &amp;lt;strong&amp;gt;dans mon style&amp;lt;/strong&amp;gt; sans avoir besoin qu&amp;amp;#8217;on leur explique à chaque fois ? Et surtout : comment cette approche se compare-t-elle aux solutions propriétaires classiques — Claude, GPT, Gemini, Grok ?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La réponse m&amp;amp;#8217;a surpris. Beaucoup moins que ce que j&amp;amp;#8217;imaginais. Et le rapport coût/efficacité face aux géants du secteur est indécent. Voici le détail complet.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_problème_pourquoi_le_fine_tune_et_pas_le_rag&amp;quot;&amp;gt;Le problème : pourquoi le fine-tune et pas le RAG ?&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le RAG, c&amp;amp;#8217;est bien. &amp;lt;a href=&amp;quot;0106_knowledge_graph_outil_comprehension_codebase_post.html&amp;quot;&amp;gt;Mon knowledge graph&amp;lt;/a&amp;gt; et &amp;lt;a href=&amp;quot;0116_compartimentage_epistemique_automatise_llm_post.html&amp;quot;&amp;gt;mon compartimentage épistémique&amp;lt;/a&amp;gt; fonctionnent. Mais le RAG a un défaut fondamental : à chaque requête, tu dois réinjecter le contexte pertinent. Ton prompt s&amp;amp;#8217;allonge, ta latence explose, et le modèle n&amp;#39;&amp;lt;strong&amp;gt;intériorise&amp;lt;/strong&amp;gt; jamais tes patterns — il les lit à chaque fois comme un document externe.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le fine-tune, lui, c&amp;amp;#8217;est la mémoire musculaire. Le modèle &amp;lt;strong&amp;gt;sait&amp;lt;/strong&amp;gt; que tu écris &amp;lt;code&amp;gt;build.gradle.kts&amp;lt;/code&amp;gt; avec des tâches enregistrées via &amp;lt;code&amp;gt;tasks.register&amp;lt;/code&amp;gt;, que tes &amp;lt;code&amp;gt;AGENTS.adoc&amp;lt;/code&amp;gt; suivent une syntaxe standardisée, que ton workspace est structuré en boroughs. Il n&amp;amp;#8217;a pas besoin qu&amp;amp;#8217;on lui rappelle.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;ℹ️&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le fine-tune n&amp;amp;#8217;est pas un remplacement du RAG. C&amp;amp;#8217;est une couche complémentaire. Le RAG reste pertinent pour les données qui changent souvent (logs, tickets, commits récents). Le fine-tune est pour la connaissance &amp;lt;strong&amp;gt;structurelle&amp;lt;/strong&amp;gt; et &amp;lt;strong&amp;gt;stylistique&amp;lt;/strong&amp;gt; de long terme.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_lidée_une_flotte_dexperts_pas_un_seul_modèle&amp;quot;&amp;gt;L&amp;amp;#8217;idée : une flotte d&amp;amp;#8217;experts, pas un seul modèle&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un seul modèle fine-tuné sur tout mon workspace, c&amp;amp;#8217;est déjà bien. Mais c&amp;amp;#8217;est sous-optimal. Mon workspace couvre des domaines très différents :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Gradle plugins (Kotlin, convention plugins, composite builds)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Moteur DAG (Kotlin, planification, exécution)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Agents LLM (Python, LangChain4j, RAG)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Documentation architecturale (AsciiDoc, gouvernance)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Infra/DevOps (Docker, GitHub Actions, CI/CD)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un modèle unique devrait être bon partout, excellent nulle part. La solution ? Une &amp;lt;strong&amp;gt;flotte de modèles spécialisés&amp;lt;/strong&amp;gt;, avec un orkestrateur qui route chaque requête vers le bon expert.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/fleet-architecture.svg&amp;quot; alt=&amp;quot;fleet architecture&amp;quot; width=&amp;quot;871&amp;quot; height=&amp;quot;462&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La flotte totale : &amp;lt;strong&amp;gt;1 orkestrateur + 22 experts = 23 modèles&amp;lt;/strong&amp;gt;. Et le coût d&amp;amp;#8217;inférence mensuel ? &amp;lt;strong&amp;gt;17€/mois&amp;lt;/strong&amp;gt; en abonnement Ollama Pro annual — extensible par cumul de comptes si les quotas sont dépassés, comme démontré dans &amp;lt;a href=&amp;quot;0120_cumuler_deux_abonnements_ollama_pro_docker_post.html&amp;quot;&amp;gt;ma méthode Docker multi-comptes&amp;lt;/a&amp;gt;. On part de 17€, on ajoute 20€ par palier selon le besoin réel. Pas de gaspillage.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_codebase_sous_la_loupe_7_900_fichiers_144_000_lignes&amp;quot;&amp;gt;La codebase sous la loupe : 7 900 fichiers, 144 000 lignes&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avant d&amp;amp;#8217;estimer le coût du training, il faut savoir quoi entraîner. J&amp;amp;#8217;ai audité mon workspace en excluant rigoureusement tout ce qui est ignoré par Git :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;----
build/    out/    node_modules/    runtimes/    .gradle/    dist/
target/   venv/   __pycache__/     .cache/      .tox/
----

Voici le résultat pour les fichiers trackés uniquement :

[cols=&amp;quot;2,2&amp;quot;]
|===
|Métrique |Valeur

|Fichiers source trackés |**7 896** |Lignes de code (LOC) |**143 805** |Repositories Git |**26** |Principaux langages |Kotlin (1 903), AsciiDoc (2 765), Python (5 029)
|===

[IMPORTANT]
====
Ces 5 000+ fichiers Python incluent les `runtimes/` des notebooks et scripts utilitaires. Le cœur applicatif (plugins Gradle, moteur DAG, agents) est principalement en Kotlin et AsciiDoc.
====

À partir de cette masse, j&amp;#39;estime pouvoir générer un dataset synthétique de **~170 millions de tokens** via un LLM instructeur (distillation de la codebase en paires instruction/réponse).

=== Détail du dataset par type d&amp;#39;expert

[source,text]
----
Dataset maître (généraliste V4-Flash) :    50M tokens
Expert Gradle/Build        :    15M tokens
Expert Kotlin/DAG          :    15M tokens
Expert AsciiDoc/Gouvernance:    15M tokens
Expert Agent/LLM/Python    :    15M tokens
Expert Infra/CI-CD         :    15M tokens
Micro-experts Qwen/Gemma   :   ~5M tokens chacun
----

== Le choix des modèles : 100% MoE, zéro dense

C&amp;#39;est là que l&amp;#39;architecture devient vraiment efficiente.

Un modèle *dense* active tous ses poids à chaque token. Un modèle *MoE* (Mixture of Experts) n&amp;#39;active qu&amp;#39;une fraction de ses paramètres. Le coût d&amp;#39;inférence — et de fine-tuning — est proportionnel aux paramètres **activés**, pas aux paramètres **stockés**.

Regardons ce que le marché propose en MoE aujourd&amp;#39;hui sur Ollama Cloud :

[cols=&amp;quot;3,2,2,1,3&amp;quot;]
|===
|Modèle |Total params |Activés |Activation |Ollama Cloud

|DeepSeek V4-Pro |1.6T |49B |3.1% |✅ natif |DeepSeek V4-Flash |292B |13B |4.5% |✅ natif |Gemma 4 26B-A4B |26B |3.8B |14.6% |✅ natif |Qwen3.6-35B-A3B |35B |3B |8.6% |❌ (pas encore intégré) |Qwen3.5-35B-A3B |35B |3B |8.6% |✅ natif
|❌ Qwen3.5-27B |27B |27B |100% dense |éliminé |❌ Qwen3.5-4B/9B |4B/9B |4B/9B |100% dense |éliminé |❌ Gemma 4 31B |31B |31B |100% dense |éliminé
|🧪 Gemma 4 E2B/E4B |5B/8B |5B/8B |100% dense |validation pipeline
|===

[CAUTION]
====
Le ratio d&amp;#39;activation est le critère discriminant. Un Gemma 4 26B-A4B n&amp;#39;active que 3.8B de ses 26B de paramètres — c&amp;#39;est 7× moins qu&amp;#39;un dense 27B, pour des performances de coding agent comparables (77.1% vs 80% sur LiveCodeBench v6).
====

=== Pourquoi j&amp;#39;abandonne les modèles denses

L&amp;#39;exception : les Gemma 4 E2B et E4B. Ces deux modèles, sous Apache 2.0, sont parfaits pour tester et valider un pipeline de training à moindre coût. Un run de 2-3h sur un E2B coûte moins de $5 — si le dataset ou les hyperparamètres sont foireux, on le sait pour une poignée de dollars. Une fois le pipeline rodé, ils peuvent même servir pour les ultra-micro-tâches (reformatage trivial, classification binaire). Mais pour les experts de la flotte principale, je reste sur du MoE. Voici pourquoi :

.Mais pas que : les Gemma 4 E2B/E4B, experts de l&amp;#39;anonymisation fine

[NOTE]
====
Google a conçu ces petits modèles comme compétitifs en tool calling natif — ils savent appeler des fonctions, manipuler des regex, chercher des motifs. Une fois fine-tunés sur des exemples d&amp;#39;anonymisation (emails, tokens, UUIDs, chemins de fichiers), ils deviennent des **anonymiseurs de dataset** ultra-rapides. On leur file un bloc de texte brut, ils appellent `sed`/`regex` via un tool call et retournent le bloc nettoyé. Le coût d&amp;#39;inférence est dérisoire : 5B activés, ça tient sur une seule GPU d&amp;#39;entrée de gamme. Ces modèles ne sont pas des experts métier — ce sont des **ouvriers spécialisés** dans la chaîne de production du dataset.
====

* Sa VRAM d&amp;#39;entraînement (même en QLoRA) est proportionnelle aux **27B totaux**
* Son temps de training est proportionnel aux **27B activés**

Comparons avec un Qwen3.6-35B-A3B (MoE) :

[cols=&amp;quot;3,2,2,2&amp;quot;]
|===
| |Qwen3.5-27B (dense) |Qwen3.6-35B-A3B (MoE) |Ratio

|VRAM QLoRA |~55 GB |~35 GB |1.6× |GPU-heures (8M tok) |~12h |~4h |**3×** |Coût par fine-tune |~$24 |~$8 |**3×** |SWE-bench Verified |75.0% |73.4% |comparable
|===

Le MoE coûte 3× moins à entraîner pour des performances agent-coding à 5% près. Sur 22 experts, l&amp;#39;écart se chiffre en milliers d&amp;#39;euros.

== Estimation du training : 811 H100-heures

J&amp;#39;ai ventilé le coût de training modèle par modèle, en QLoRA 4-bit, avec les datasets décrits plus haut.

=== Micro-experts MoE légers (3-3.8B activés)

Ces modèles nécessitent 1 H100 (80 GB) par run. La VRAM du modèle en Q4 est d&amp;#39;environ 13-18 GB, laissant large pour les états d&amp;#39;optimiseur LoRA et les activations.

[cols=&amp;quot;4,2,3,2&amp;quot;]
|===
|Modèle |Nb de runs |GPU-h/run |Total GPU-h

|Gemma 4 26B-A4B-FT |6 |3.5 h |**21 h** |Qwen3.6-35B-A3B-FT |5 |4.0 h |**20 h** |Qwen3.5-35B-A3B-FT |5 |4.0 h |**20 h** |*Sous-total micro* | | |*61 h*
|===

=== Exécutifs V4-Flash (13B activés / 292B stockés)

Le DeepSeek V4-Flash est un cas particulier. Même si seuls 13B sont activés par token, le modèle complet en Q4 pèse ~142 GB — tous les experts doivent être en VRAM pendant le training. Il faut donc **3× H100** par run pour être confortable.

[cols=&amp;quot;4,2,3,3,2&amp;quot;]
|===
|Modèle |Dataset |GPUs |Heures |Total GPU-h

|V4-Flash-Base généraliste |50M tok |3× H100 |50 h |**150 h** |V4-Flash expert ×5 |15M tok |3× H100 |40 h |**600 h** |*Sous-total exécutifs* | | | |*750 h*
|===

[cols=&amp;quot;3,2,1&amp;quot;]
|===
|**TOTAL** | |**811 H100-h**
|===

[NOTE]
====
À titre de comparaison, un full fine-tune du V4-Flash (sans QLoRA, tous les poids) coûterait ~4 000 H100-h rien que pour les 6 modèles. Le QLoRA divise le coût par 5. C&amp;#39;est le seul moyen de rendre le projet économiquement viable à cette échelle.
====

=== Tarifs GPU : qui loue quoi en mai 2026

J&amp;#39;ai benchmarké les principaux loueurs de H100. Le prix au compteur, pour 811 heures.

[cols=&amp;quot;3,2,2,2&amp;quot;]
|===
|Loueur |$/H100·h |Total 811h |Fiabilité

|**Vast.ai spot** |$1.60 |**$1 298** |★★☆ interruptible |**Crusoe Cloud** |$2.00 |**$1 622** |★★★★ datacenter fiable |FluidStack |$1.98 |$1 606 |★★★ |TensorDock |$1.80 |$1 460 |★★☆ |RunPod |$2.29 |$1 857 |★★★ bon compromis |CoreWeave |$2.25 |$1 825 |★★★★ entreprise |Lambda Labs |$2.49 |$2 019 |★★★★ premium
|===

[TIP]
====
Vast.ai spot est le moins cher mais tes runs peuvent être interrompus à tout moment. Pour du training, c&amp;#39;est risqué. Crusoe à $2.00/h est le meilleur rapport fiabilité/prix. Le surcoût de $324 vs Vast vaut la tranquillité d&amp;#39;esprit.
====

=== Wall-clock : combien de temps pour tout entraîner ?

Avec un seul nœud 3× H100, les 31 runs (1 généraliste + 30 experts) prennent environ **12 jours** en séquentiel. Si tu loues 2 nœuds en parallèle, ça tombe à **6 jours**.

En pratique, les micro-experts peuvent tourner sur des nœuds séparés (1 H100 chacun) pendant que les V4-Flash occupent le nœud 3× H100. Avec une planification intelligente :&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Nœud A (3× H100) : V4-Flash généraliste → V4-Flash experts ×5       (11 jours)
Nœud B (1× H100) : Gemma 4 26B ×6 → Qwen 36 ×5 → Qwen 35 ×5        (6 jours)&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;7 jours de location, tout plié.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_linférence_23_modèles_sur_ollama_cloud_à_partir_de_17mois&amp;quot;&amp;gt;L&amp;amp;#8217;inférence : 23 modèles sur Ollama Cloud à partir de 17€/mois&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est la partie la plus élégante de l&amp;amp;#8217;architecture.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ollama Cloud permet d&amp;amp;#8217;uploader des modèles privés (fonctionnalité du plan Pro). Mes 22 modèles fine-tunés sont poussés en &amp;lt;code&amp;gt;.gguf&amp;lt;/code&amp;gt; sur mon espace Ollama, marqués comme privés, et accessibles via l&amp;amp;#8217;API standard.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/inference-flow.svg&amp;quot; alt=&amp;quot;inference flow&amp;quot; width=&amp;quot;918&amp;quot; height=&amp;quot;524&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_on_démarre_à_17mois_on_scale_si_besoin&amp;quot;&amp;gt;On démarre à 17€/mois, on scale si besoin&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le plan Pro Ollama (17€/mois en annuel) autorise 3 modèles cloud concurrents. Dans cette architecture, je n&amp;amp;#8217;ai jamais besoin de plus de 2-3 experts simultanément :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;La phase de classification (V4-Pro) occupe 1 slot, quelques secondes&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;expert ciblé occupe 1 slot, le temps de générer sa réponse&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le 3ème slot reste en réserve pour les tâches parallèles&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Si l&amp;amp;#8217;usage augmente, j&amp;amp;#8217;ajoute des comptes Pro supplémentaires via la méthode Docker décrite dans &amp;lt;a href=&amp;quot;0120_cumuler_deux_abonnements_ollama_pro_docker_post.html&amp;quot;&amp;gt;mon article sur le cumul d&amp;amp;#8217;abonnements&amp;lt;/a&amp;gt;. Pas de plan Max à 100€/mois — je n&amp;amp;#8217;ajoute que ce dont j&amp;amp;#8217;ai réellement besoin.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le seul facteur limitant est le &amp;lt;strong&amp;gt;quota GPU-time&amp;lt;/strong&amp;gt; mensuel d&amp;amp;#8217;Ollama (50× le plan gratuit pour Pro). Pour mon usage de quelques centaines de requêtes par jour, c&amp;amp;#8217;est amplement suffisant.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock important&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-important&amp;quot; title=&amp;quot;❗&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le coût marginal d&amp;amp;#8217;un appel à V4-Pro (49B activés) vs Gemma 4 26B-A4B (3.8B activés) est le &amp;lt;strong&amp;gt;même pour moi : zéro&amp;lt;/strong&amp;gt;. C&amp;amp;#8217;est le forfait Ollama qui absorbe la différence de compute. Mon seul indicateur est la latence.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_routing_en_pratique&amp;quot;&amp;gt;Le routing en pratique&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;----
Volume de requêtes estimé : ~500/jour

├─ 50% → Gemma 4 26B-A4B-FT    (micro, 3.8B actifs)
│        Formatage AsciiDoc, scripts simples, conventions nommage
│
├─ 25% → V4-Flash-FT            (exécutif, 13B actifs)
│        Plugins Gradle, refactoring Kotlin, génération DAG
│
├─ 15% → Qwen 35B MoE-FT       (micro, 3B actifs)
│        Tâches intermédiaires, review de code, documentation
│
└─ 10% → V4-Pro                 (orkestrateur, 49B actifs)
         Décisions architecturales, refactoring transverse,
         problèmes vraiment nouveaux
----

La masse du trafic passe par les petits. Le gros modèle n&amp;#39;intervient qu&amp;#39;en dernier recours.

== La comparaison qui fait mal : Claude, GPT, Gemini, Grok vs ma flotte

C&amp;#39;est ici que l&amp;#39;écart devient vertigineux. Regardons ce que coûterait le même volume de travail (500 requêtes/jour, ~300 tokens input + 2 000 tokens output en moyenne) avec les solutions propriétaires du marché en mai 2026.

=== Anthropic — Claude (tarifs mai 2026)

Anthropic a récemment *baissé* ses prix. La pression des solutions open-weight comme DeepSeek et Qwen se fait sentir.

[cols=&amp;quot;3,2,2,2,2&amp;quot;]
|===
|Modèle |Input $/MTok |Output $/MTok |Coût/jour |**Coût/mois**

|Opus 4.7 (le + intelligent) |$5 |$25 |$25.75 |**$772** |Sonnet 4.6 (équilibré) |$3 |$15 |$15.45 |**$463** |Haiku 4.5 (le + rapide) |$1 |$5 |$5.15 |**$154**
|===

[CAUTION]
====
Ces tarifs sont *après* la dernière baisse de prix d&amp;#39;Anthropic (mai 2026). Avant cela, Opus était à $15/$75 par MTok. La peur de l&amp;#39;open-weight est réelle.
====

Même le modèle le moins cher de Claude — Haiku 4.5 à **154€/mois** — coûte 9× plus que mon abonnement Ollama Pro à 17€. Et Haiku ne connaît pas ma codebase, ne génère pas dans mon style, et nécessite du prompt engineering systématique.

Le plus intelligent — Opus 4.7 — explose le budget à **772€/mois** pour un volume modeste de 500 requêtes par jour. Soit **45× plus cher** que ma solution.

=== OpenAI — GPT (tarifs mai 2026)

[cols=&amp;quot;3,2,2,2,2&amp;quot;]
|===
|Modèle |Input $/MTok |Output $/MTok |Coût/jour |**Coût/mois**

|GPT 5.5 (le + intelligent) |$5 |$30 |$30.90 |**$927** |GPT 5.4 (standard) |$2.50 |$15 |$15.45 |**$463** |GPT 5.4 Mini |$0.75 |$4.50 |$4.64 |**$139**
|===

Même le modèle « économique » d&amp;#39;OpenAI — GPT 5.4 Mini à 139€/mois — coûte 8× mon abonnement, pour un modèle qui ne sait *rien* de mes conventions et nécessite du prompt engineering lourd.

GPT 5.5, leur flagship : **927€/mois**. Pour du *zero-shot* sur ma codebase. Avec 2-3 itérations par tâche à cause du style non maîtrisé, le vrai coût mensuel double facilement.

=== Google — Gemini (tarifs mai 2026)

[cols=&amp;quot;3,2,2,2,2&amp;quot;]
|===
|Modèle |Input $/MTok |Output $/MTok |Coût/jour |**Coût/mois**

|Gemini 3.1 Pro (High) |$3.50 |$17.50 |$18.00 |**$540** |Gemini 3.1 Pro |$2 |$10 |$10.30 |**$309** |Gemini 3 Flash |$0.30 |$1.50 |$1.54 |**$46**
|===

Gemini 3 Flash à 46€/mois est compétitif en prix pur — mais sans fine-tune, il génère du code « générique ». Pas du code *Cheroliv*.

=== Grok — xAI (tarifs mai 2026)

[cols=&amp;quot;3,2,2,2,2&amp;quot;]
|===
|Modèle |Input $/MTok |Output $/MTok |Coût/jour |**Coût/mois**

|Grok 4 |$4 |$16 |$16.48 |**$494** |Grok 4 Mini |$0.80 |$3.20 |$3.30 |**$99**
|===

=== Microsoft — Azure OpenAI (tarifs mai 2026)

Azure applique les mêmes prix que l&amp;#39;API OpenAI directe, mais facture en plus l&amp;#39;infrastructure et le réseau. Il faut compter un surcoût de 10-20% pour le service managé.

[cols=&amp;quot;3,2,2,2,2&amp;quot;]
|===
|Modèle |Input $/MTok |Output $/MTok |Coût/jour |**Coût/mois**

|GPT 5.4 (Azure, Global) |$2.50 |$15 |$15.45 |**$463** |GPT 5.4 + infrastructure |surcoût 15% |surcoût 15% |$17.77 |**$533**
|===

[NOTE]
====
Les tarifs ci-dessus concernent l&amp;#39;API, pas les abonnements « chat » (Claude Pro à $20/mois, ChatGPT Plus à $20/mois). On compare ici l&amp;#39;usage *développeur*, celui où tu enchaînes des centaines de requêtes par jour via API pour générer, refactorer, documenter. Les abonnements grand public ont des quotas qui explosent bien avant 500 requêtes/jour.
====

=== Le tableau comparatif final

[cols=&amp;quot;3,2,2,2,2,2&amp;quot;]
|===
|Solution |Connaissance codebase |Style intégré |Coût/mois |Itérations |**Coût effectif**

|**Ma flotte (Ollama Pro)** |✅ Fine-tunée |✅ Dans les poids |**17€** |0-1 |**17€** |Claude Opus 4.7 |❌ Zero-shot |❌ Prompt nécessaire |$772 |2-3 |$1 500-2 300 |Claude Haiku 4.5 |❌ Zero-shot |❌ Prompt nécessaire |$154 |3-4 |$460-615 |GPT 5.5 |❌ Zero-shot |❌ Prompt nécessaire |$927 |2-3 |$1 854-2 781 |GPT 5.4 |❌ Zero-shot |❌ Prompt nécessaire |$463 |2-3 |$925-1 390 |GPT 5.4 Mini |❌ Zero-shot |❌ Prompt nécessaire |$139 |3-5 |$417-695 |Gemini 3.1 Pro High |❌ Zero-shot |❌ Prompt nécessaire |$540 |2-3 |$1 080-1 620 |Grok 4 |❌ Zero-shot |❌ Prompt nécessaire |$494 |2-3 |$988-1 482 |**Azure GPT 5.4** |❌ Zero-shot |❌ Prompt nécessaire |$533 |2-3 |$1 066-1 600
|===

[plantuml, cost-comparison, svg]
----
@startuml
skinparam backgroundColor #FAFAFA

title Rapport coût/efficacité — ma flotte vs le marché (mai 2026)

rectangle &amp;quot;17€/mois&amp;quot; as OURS #4ECDC4
rectangle &amp;quot;Opus 4.7\n772€&amp;quot; as OPUS #FF6B6B
rectangle &amp;quot;Sonnet 4.6\n463€&amp;quot; as SONNET #FF8B94
rectangle &amp;quot;GPT 5.5\n927€&amp;quot; as GPT #FFD93D
rectangle &amp;quot;Gemini 3.1 Pro\n540€&amp;quot; as GEMINI #6C5CE7
rectangle &amp;quot;Grok 4\n494€&amp;quot; as GROK #A8E6CF
rectangle &amp;quot;Haiku 4.5\n154€&amp;quot; as HAIKU #DFE6E9
rectangle &amp;quot;GPT 5.4 Mini\n139€&amp;quot; as MINI #B2BEC3

note bottom of OURS
  Avec fine-tune intégré.
  Zéro prompt engineering.
  90%+ first-shot correct.
end note

@enduml
----

17€/mois pour 23 experts IA fine-tunés. Le flagship Claude Opus 4.7 coûte **45× plus cher** pour une qualité inférieure sur *mon* codebase. GPT 5.5 coûte **54× plus cher**. Même le modèle le moins cher du marché (Gemini Flash à 46€) coûte **2.7× plus** sans la connaissance de mon workspace.

Le verdict est sans appel : le fine-tune sur architectures MoE, en 2026, n&amp;#39;est pas juste « moins cher ». C&amp;#39;est un facteur d&amp;#39;efficacité de **27× à 54×** sur le rapport coût/qualité face aux solutions propriétaires. Anthropic, OpenAI, Google — tous le savent, et c&amp;#39;est pour ça qu&amp;#39;ils baissent leurs prix en panique.

== Le facteur d&amp;#39;efficacité : 5-8× vs utiliser V4-Pro seul

Comparons les deux extrêmes.

=== Scénario A : V4-Pro seul pour tout

[cols=&amp;quot;3,2&amp;quot;]
|===
|Métrique |Valeur

|Connaissance de la codebase |0 (zero-shot) |Convention naming |40-60% first-shot correct |Prompt engineering nécessaire |Oui, systématique |Itérations par tâche |2-3 |Coût inférence |$100/mois (Ollama Max) |Latence moyenne |~20 tok/s + réseau
|===

=== Scénario B : Flotte MoE orchestrée

[cols=&amp;quot;3,2&amp;quot;]
|===
|Métrique |Valeur

|Connaissance de la codebase |Intégrée (fine-tune) |Convention naming |90-95% first-shot correct |Prompt engineering |Non (le style est dans les poids) |Itérations par tâche |0-1 |Coût inférence |$60/mois (3× Ollama Pro) |Latence moyenne |~50 tok/s (modèles légers)
|===

[cols=&amp;quot;4,2,2,2&amp;quot;]
|===
|Dimension |V4-Pro seul |Flotte MoE |Facteur

|Coût mensuel cloud |$100 |**$60** |1.7× |Contexte à injecter |Élevé (prompt) |**Zéro** |∞ |Itérations moyennes |2-3 |**0-1** |2-3× |Latence ressentie |20 tok/s |50 tok/s |**2.5×** |First-shot correct |50% |90%+ |**1.8×**
|===

**Facteur d&amp;#39;efficacité global : 5-8×** — en productivité développeur ressentie.

[NOTE]
====
Le facteur ne se mesure pas en tokens ou en dollars. Il se mesure en « combien de temps je passe à expliquer au modèle ce qu&amp;#39;il devrait déjà savoir ». Avec les modèles fine-tunés, ce temps tend vers zéro.
====

== Le budget complet : un investissement one-shot, un forfait ridicule

[cols=&amp;quot;3,2&amp;quot;]
|===
|Poste |Montant

|Training GPU (811 H100-h, Crusoe $2/h) |**$1 622** |Génération dataset synthétique (API LLM) |**$400** |Inference (Ollama Pro annuel, $17/mois) |**$204** |**Total première année** |**$2 226** |**Mensuel équivalent** |**$186** |**Coût par requête estimé** |&amp;amp;lt; $0.01
|===

[plantuml, budget-breakdown, svg]
----
@startuml
skinparam backgroundColor #FAFAFA

rectangle &amp;quot;Budget Année 1 : $2 226&amp;quot; as Total #E8E8E8 {
  rectangle &amp;quot;Training GPU\n$1 622 (73%)&amp;quot; as Train #FF6B6B
  rectangle &amp;quot;Dataset\ndistillation\n$400 (18%)&amp;quot; as Data #FFE66D
  rectangle &amp;quot;Ollama Pro\n$204 (9%)&amp;quot; as Cloud #4ECDC4
}

note bottom of Total
   $186/mois équivalent année 1.
   Dès l&amp;#39;an 2 : $17/mois.
   Amorti par ~$235 de CA
   mensuel avec marge 95%.
end note

@enduml
----

$186/mois la première année, **$17/mois** dès l&amp;#39;an 2. Le prix d&amp;#39;un abonnement Netflix premium, pour une équipe de 23 experts IA disponibles 24/7, qui écrivent du code *dans mon style* sans que j&amp;#39;aie besoin de leur expliquer mes conventions.

=== Le calcul de rentabilité

Avec edster.cloud et sa marge de ~95%, le point mort est à **~$2 340 de CA supplémentaire** sur l&amp;#39;année. En pratique :

* 1 mission de pilotage software → $3 000-5 000 → investissement couvert + profit
* 1 formation corporate → $5 000-10 000 → confortable
* L&amp;#39;upsell implicite : &amp;quot;mon équipe d&amp;#39;IA maîtrise ma forge logicielle&amp;quot; → différenciant commercial

À partir de l&amp;#39;an 2, le training n&amp;#39;est plus à payer (sauf mise à jour du dataset). Le coût annuel tombe à **$204** ($17/mois). Le ratio coût/valeur est celui d&amp;#39;une licorne : quasi nul.

== Les limites de l&amp;#39;exercice

Ceci reste une *estimation au doigt mouillé*. Plusieurs variables peuvent faire varier le budget :

[cols=&amp;quot;2,3&amp;quot;]
|===
|Variable |Impact

|Génération du dataset synthétique |Si l&amp;#39;API de distillation merde (hallucinations, paires mal formées), il faut du temps humain pour curater. Coût caché. |Quotas GPU-time Ollama |Si l&amp;#39;usage dépasse les quotas du plan Pro, il faudra monter en gamme ou basculer sur du GPU dédié. |Qualité effective des fine-tunes |Un fine-tune raté → à refaire. Le vrai risque c&amp;#39;est les hyperparamètres, pas la location GPU. |Évolution rapide des modèles |Les Qwen3.6/Gemma 4 sont sortis il y a &amp;amp;lt; 1 mois. Dans 6 mois, la génération suivante sera meilleure ET moins chère à fine-tuner.
|===

[WARNING]
====
Ne lancez pas 811 heures de training sans avoir d&amp;#39;abord testé le pipeline sur *un seul* micro-modèle. Un run de 3-4h sur un Qwen 35B-A3B coûte $8. Si le dataset est pourri, vous le saurez pour $8, pas pour $1 622.
====

== Conclusion : le fine-tune est devenu un luxe accessible

Il y a un an, fine-tuner un modèle de 292B paramètres (même en QLoRA) relevait de la recherche. Aujourd&amp;#39;hui, en mai 2026, c&amp;#39;est un projet faisable pour un développeur indépendant :

* **811 H100-heures** de training — $1 622 chez Crusoe
* **23 modèles spécialisés** chargés sur Ollama Cloud — **$17/mois**
* **0 serveur, 0 GPU local, 0 maintenance infra**

La démocratisation est venue de trois facteurs convergents :

1. **Les architectures MoE** — qui permettent de fine-tuner efficacement des modèles dont seule une fraction des poids est activée
2. **Les plans fixes d&amp;#39;Ollama Cloud** — qui transforment un coût variable (per-token) en coût fixe (abonnement)
3. **Les modèles open-weight de qualité** — DeepSeek V4, Qwen3.6, Gemma 4 sont sous licences MIT/Apache 2.0

&amp;quot;Civilisation advances by extending the number of important operations which we can perform without thinking about them.&amp;quot;

Le fine-tune, c&amp;#39;est exactement ça : une opération que tu délègues à la machine pour ne plus avoir à y penser. Et en 2026, ça coûte moins cher qu&amp;#39;un développeur junior mensualisé.

---

_Article publié le {jbake-date}_

== Modèles fine-tunés de la flotte

[cols=&amp;quot;2,2,2,2,3&amp;quot;]
|===
|Taille activée |Nombre |Modèle de base |Domaine |Dataset

|13B |1 |DeepSeek-V4-Flash-Base |Workspace général |50M tokens |13B |5 |DeepSeek-V4-Flash |Gradle, Kotlin, DAG, Doc, Infra |15M tokens |3.8B |6 |Gemma 4 26B-A4B |Micro-tâches, formatage, scripts |5M tokens |3B |5 |Qwen3.6-35B-A3B |Refactoring, review, doc intermédiaire |5M tokens |3B |5 |Qwen3.5-35B-A3B |Tâches legacy, compatibilité |5M tokens
|===

== Ressources

=== Modèles open-weight sur HuggingFace

* https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash-Base[DeepSeek V4-Flash-Base — 292B params, license MIT]
* https://huggingface.co/Qwen/Qwen3.6-35B-A3B[Qwen3.6-35B-A3B — 35B/3B activés, license Apache 2.0]
* https://huggingface.co/Qwen/Qwen3.5-35B-A3B[Qwen3.5-35B-A3B — 35B/3B activés, license Apache 2.0]
* https://huggingface.co/google/gemma-4-26B-A4B-it[Gemma 4 26B-A4B — 26B/3.8B activés, license Apache 2.0]

=== Sources des tarifs (mai 2026)

* https://ollama.com/pricing[Tarifs Ollama Cloud — plan Pro $17/mois annuel]
* https://www.anthropic.com/pricing[Tarifs Anthropic — Claude API (Opus 4.7 $5/$25, Sonnet 4.6 $3/$15, Haiku 4.5 $1/$5)]
* https://openai.com/api/pricing/[Tarifs OpenAI — GPT API (GPT 5.5 $5/$30, GPT 5.4 $2.50/$15)]
* https://deepinfra.com/pricing[Tarifs DeepInfra — GPU instances H100 $1.79/h, B200 $2.79/h]
* Vast.ai, Crusoe Cloud, FluidStack, TensorDock, RunPod, CoreWeave, Lambda Labs — relevés de prix manuels, datés de mai 2026

=== Annonces officielles

* https://qwen.ai/blog?id=qwen3.6-35b-a3b[Annonce officielle Qwen3.6-35B-A3B — blog Qwen] — agentic coding, Apache 2.0, 262K context&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Plugin Gradle Maison pour Piloter Deux Instances Ollama Pro en Parallèle</title>
            <link >https://cheroliv.com/blog/2026/0121_plugin_gradle_piloter_deux_instances_ollama_pro_post.html</link>
            <pubDate>Fri, 8 May 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0121_plugin_gradle_piloter_deux_instances_ollama_pro_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_introduction&amp;quot;&amp;gt;Introduction&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pourquoi_gradle_pour_de_linfra&amp;quot;&amp;gt;Pourquoi Gradle Pour de l&amp;amp;#8217;Infra ?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_build_gradle_kts_complet&amp;quot;&amp;gt;Le build.gradle.kts Complet&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_anatomie_des_tâches_clés&amp;quot;&amp;gt;Anatomie des Tâches Clés&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_startollamab_le_lanceur&amp;quot;&amp;gt;&amp;lt;code&amp;gt;startOllamaB&amp;lt;/code&amp;gt; — Le Lanceur&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_signinb_linteractif&amp;quot;&amp;gt;&amp;lt;code&amp;gt;signInB&amp;lt;/code&amp;gt; — L&amp;amp;#8217;Interactif&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pullmodelb_le_paramétrable&amp;quot;&amp;gt;&amp;lt;code&amp;gt;pullModelB&amp;lt;/code&amp;gt; — Le Paramétrable&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_statusollamaall_le_diagnostic&amp;quot;&amp;gt;&amp;lt;code&amp;gt;statusOllamaAll&amp;lt;/code&amp;gt; — Le Diagnostic&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_cleanollamab_le_nettoyage_qui_préserve_lidentité&amp;quot;&amp;gt;&amp;lt;code&amp;gt;cleanOllamaB&amp;lt;/code&amp;gt; — Le Nettoyage qui Préserve l&amp;amp;#8217;Identité&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_workflow_complet_de_zéro_à_deux_sessions&amp;quot;&amp;gt;Workflow Complet — De Zéro à Deux Sessions&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pourquoi_ne_pas_en_faire_un_vrai_plugin_gradle&amp;quot;&amp;gt;Pourquoi Ne Pas en Faire un Vrai Plugin Gradle ?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_leçons_apprises&amp;quot;&amp;gt;Leçons Apprises&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_conclusion&amp;quot;&amp;gt;Conclusion&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ressources&amp;quot;&amp;gt;Ressources&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 18 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Pourquoi taper des commandes docker à la main quand on peut tout encapsuler dans des tâches Gradle ? Voici comment j&amp;amp;#8217;ai industrialisé ma config dual-Ollama Pro avec zéro script shell externe. Démarrage, arrêt, identité, sign-in, pull — tout passe par &amp;lt;code&amp;gt;./gradlew&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_introduction&amp;quot;&amp;gt;Introduction&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Dans l&amp;amp;#8217;article précédent, j&amp;amp;#8217;ai montré comment faire cohabiter deux comptes Ollama Pro sur la même machine en isolant la deuxième instance dans un conteneur Docker. Le montage fonctionne, mais la gestion au quotidien est vite pénible : se souvenir du nom du conteneur, relancer les bonnes commandes &amp;lt;code&amp;gt;docker exec&amp;lt;/code&amp;gt;, checker quel port est actif&amp;amp;#8230;&amp;amp;#8203;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Vous connaissez ce moment où vous avez 14 terminaux ouverts, que vous tapez &amp;lt;code&amp;gt;docker exec ollama-instance-b ollama list&amp;lt;/code&amp;gt; pour la quatrième fois, et que vous vous dites « il doit bien y avoir un moyen plus propre » ?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce moyen, c&amp;amp;#8217;est Gradle.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pas juste pour builder du code. Gradle comme un chef d&amp;amp;#8217;orchestre d&amp;amp;#8217;infrastructure locale. Des tâches qui provisionnent, vérifient, testent, et nettoient. Le tout versionné dans un &amp;lt;code&amp;gt;build.gradle.kts&amp;lt;/code&amp;gt; qui vit à côté du &amp;lt;code&amp;gt;docker-compose.yml&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/architecture-gradle-ollama.svg&amp;quot; alt=&amp;quot;architecture gradle ollama&amp;quot; width=&amp;quot;717&amp;quot; height=&amp;quot;511&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_pourquoi_gradle_pour_de_linfra&amp;quot;&amp;gt;Pourquoi Gradle Pour de l&amp;amp;#8217;Infra ?&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La question est légitime. Gradle, c&amp;amp;#8217;est un build tool. Normalement, il compile, il teste, il package. Pas il lance des conteneurs Docker.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Sauf que Gradle est aussi un moteur de graphe de dépendances — et c&amp;amp;#8217;est là que ça devient intéressant pour notre cas.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;On veut :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Que le conteneur soit lancé avant un sign-in&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Que l&amp;amp;#8217;identité soit vérifiée avant un pull de modèle&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Qu&amp;amp;#8217;un test API échoue silencieusement si le conteneur est down&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Du graphe de dépendances pur. Gradle est taillé pour ça. Le DSL Kotlin rend l&amp;amp;#8217;écriture des tâches fluide, et le &amp;lt;code&amp;gt;doLast&amp;lt;/code&amp;gt; permet d&amp;amp;#8217;exécuter des commandes système comme si c&amp;amp;#8217;était du code applicatif.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Et surtout : pas de bashrc à maintenir, pas de scripts qui traînent dans &amp;lt;code&amp;gt;~/bin&amp;lt;/code&amp;gt;, pas de Makefile à côté du docker-compose. Tout vit dans un seul fichier, au même endroit que le code du projet.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_build_gradle_kts_complet&amp;quot;&amp;gt;Le build.gradle.kts Complet&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Voici le fichier que j&amp;amp;#8217;ai fini par écrire. Il fait tout, du provisionnement du volume jusqu&amp;amp;#8217;au curl de vérification, en passant par le sign-in interactif.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;import java.io.ByteArrayOutputStream

plugins {
    base
}

// -------------------------------------------------------------------------
// Configuration
// -------------------------------------------------------------------------
val instanceName   = &amp;quot;ollama-instance-b&amp;quot;
val instancePort   = 11435
val instanceImage  = &amp;quot;ollama/ollama:0.20.2&amp;quot;
val dataDir        = file(&amp;quot;${System.getProperty(&amp;quot;user.home&amp;quot;)}/ollama-b-data&amp;quot;)
val nativePort     = 11434

// Modèles à gérer — cloud Pro + un modèle local gratuit pour les tests
val proModels      = listOf(&amp;quot;deepseek-v4-pro:cloud&amp;quot;, &amp;quot;gemma4:31b-cloud&amp;quot;)
val freeModels     = listOf(&amp;quot;qwen3:0.6b&amp;quot;)

// -------------------------------------------------------------------------
// Tâche préparatoire — création du volume si absent
// -------------------------------------------------------------------------
val prepareVolume by tasks.registering {
    group       = &amp;quot;ollama&amp;quot;
    description = &amp;quot;Crée le répertoire de volume pour l&amp;#39;instance B si absent&amp;quot;
    doLast {
        if (!dataDir.exists()) {
            dataDir.mkdirs()
            println(&amp;quot;Volume créé : ${dataDir.absolutePath}&amp;quot;)
        } else {
            println(&amp;quot;Volume existant : ${dataDir.absolutePath}&amp;quot;)
        }
    }
}

// -------------------------------------------------------------------------
// Démarrage du conteneur Docker
// -------------------------------------------------------------------------
val startOllamaB by tasks.registering(Exec::class) {
    group       = &amp;quot;ollama&amp;quot;
    description = &amp;quot;Lance le conteneur Docker pour l&amp;#39;instance Ollama B&amp;quot;
    dependsOn(prepareVolume)

    commandLine(
        &amp;quot;docker&amp;quot;, &amp;quot;run&amp;quot;, &amp;quot;-d&amp;quot;,
        &amp;quot;--name&amp;quot;, instanceName,
        &amp;quot;-p&amp;quot;, &amp;quot;$instancePort:11434&amp;quot;,
        &amp;quot;-v&amp;quot;, &amp;quot;${dataDir.absolutePath}:/root/.ollama&amp;quot;,
        &amp;quot;-e&amp;quot;, &amp;quot;OLLAMA_HOST=0.0.0.0&amp;quot;,
        &amp;quot;--restart&amp;quot;, &amp;quot;always&amp;quot;,
        instanceImage
    )
    isIgnoreExitValue = true

    doLast {
        val alreadyRunning = executionResult.get().exitValue != 0
        if (alreadyRunning) {
            logger.lifecycle(&amp;quot;Le conteneur &amp;#39;$instanceName&amp;#39; existe déjà — tentative de démarrage&amp;quot;)
        } else {
            logger.lifecycle(&amp;quot;Conteneur &amp;#39;$instanceName&amp;#39; lancé&amp;quot;)
        }
    }
}

// -------------------------------------------------------------------------
// Arrêt du conteneur
// -------------------------------------------------------------------------
val stopOllamaB by tasks.registering(Exec::class) {
    group       = &amp;quot;ollama&amp;quot;
    description = &amp;quot;Arrête le conteneur Docker de l&amp;#39;instance B&amp;quot;

    commandLine(&amp;quot;docker&amp;quot;, &amp;quot;stop&amp;quot;, instanceName)
    isIgnoreExitValue = true

    doLast {
        logger.lifecycle(&amp;quot;Conteneur &amp;#39;$instanceName&amp;#39; arrêté&amp;quot;)
    }
}

// -------------------------------------------------------------------------
// Affichage de la clé publique (Device Key)
// -------------------------------------------------------------------------
val checkIdentity by tasks.registering(Exec::class) {
    group       = &amp;quot;ollama&amp;quot;
    description = &amp;quot;Affiche la clé publique SSH de l&amp;#39;instance B&amp;quot;
    dependsOn(startOllamaB)

    commandLine(&amp;quot;docker&amp;quot;, &amp;quot;exec&amp;quot;, instanceName, &amp;quot;cat&amp;quot;, &amp;quot;/root/.ollama/id_ed25519.pub&amp;quot;)
    standardOutput = ByteArrayOutputStream()

    doLast {
        val pubKey = standardOutput.toString().trim()
        println(&amp;quot;=&amp;quot;.repeat(60))
        println(&amp;quot;Device Key (Instance B)&amp;quot;)
        println(&amp;quot;=&amp;quot;.repeat(60))
        println(pubKey)
        println(&amp;quot;=&amp;quot;.repeat(60))
        println(&amp;quot;→ Enregistre cette clé sur https://ollama.com/settings/keys&amp;quot;)
        println(&amp;quot;→ Puis exécute : ./gradlew signInB&amp;quot;)
        println(&amp;quot;=&amp;quot;.repeat(60))
    }
}

// -------------------------------------------------------------------------
// Sign-in interactif (Ouvrira le navigateur)
// -------------------------------------------------------------------------
val signInB by tasks.registering(Exec::class) {
    group       = &amp;quot;ollama&amp;quot;
    description = &amp;quot;Lance l&amp;#39;authentification interactive Ollama pour le compte B&amp;quot;
    dependsOn(startOllamaB)

    standardInput  = System.`in`
    standardOutput = System.out
    errorOutput    = System.err

    commandLine(&amp;quot;docker&amp;quot;, &amp;quot;exec&amp;quot;, &amp;quot;-it&amp;quot;, instanceName, &amp;quot;ollama&amp;quot;, &amp;quot;signin&amp;quot;)

    doFirst {
        logger.lifecycle(&amp;quot;Authentification pour le Compte Pro B...&amp;quot;)
        logger.lifecycle(&amp;quot;Ouvre ton navigateur et connecte-toi avec l&amp;#39;email du compte B&amp;quot;)
    }
}

// -------------------------------------------------------------------------
// Pull d&amp;#39;un modèle (paramétrable via propriété Gradle)
// -------------------------------------------------------------------------
val pullModelB by tasks.registering(Exec::class) {
    group       = &amp;quot;ollama&amp;quot;
    description = &amp;quot;Pull un modèle sur l&amp;#39;instance B. Usage : ./gradlew pullModelB -Pmodel=nom:tag&amp;quot;
    dependsOn(startOllamaB)

    val modelName = project.findProperty(&amp;quot;model&amp;quot;) as? String ?: &amp;quot;qwen3:0.6b&amp;quot;

    commandLine(&amp;quot;docker&amp;quot;, &amp;quot;exec&amp;quot;, instanceName, &amp;quot;ollama&amp;quot;, &amp;quot;pull&amp;quot;, modelName)

    doFirst {
        logger.lifecycle(&amp;quot;Pull du modèle &amp;#39;$modelName&amp;#39; sur l&amp;#39;instance B...&amp;quot;)
    }

    doLast {
        logger.lifecycle(&amp;quot;Modèle &amp;#39;$modelName&amp;#39; pullé avec succès&amp;quot;)
    }
}

// -------------------------------------------------------------------------
// Pull de tous les modèles Pro (batch)
// -------------------------------------------------------------------------
val pullAllProModels by tasks.registering {
    group       = &amp;quot;ollama&amp;quot;
    description = &amp;quot;Pull tous les modèles cloud Pro sur l&amp;#39;instance B&amp;quot;
    dependsOn(startOllamaB)

    doLast {
        proModels.forEach { model -&amp;amp;gt;
            logger.lifecycle(&amp;quot;→ Pull $model...&amp;quot;)
            val process = ProcessBuilder(&amp;quot;docker&amp;quot;, &amp;quot;exec&amp;quot;, instanceName, &amp;quot;ollama&amp;quot;, &amp;quot;pull&amp;quot;, model)
                .inheritIO()
                .start()
            process.waitFor()
        }
        logger.lifecycle(&amp;quot;Tous les modèles Pro pullés&amp;quot;)
    }
}

// -------------------------------------------------------------------------
// Pull de tous les modèles gratuits (batch / première install)
// -------------------------------------------------------------------------
val pullAllFreeModels by tasks.registering {
    group       = &amp;quot;ollama&amp;quot;
    description = &amp;quot;Pull tous les modèles locaux gratuits sur l&amp;#39;instance B&amp;quot;
    dependsOn(startOllamaB)

    doLast {
        freeModels.forEach { model -&amp;amp;gt;
            logger.lifecycle(&amp;quot;→ Pull $model...&amp;quot;)
            val process = ProcessBuilder(&amp;quot;docker&amp;quot;, &amp;quot;exec&amp;quot;, instanceName, &amp;quot;ollama&amp;quot;, &amp;quot;pull&amp;quot;, model)
                .inheritIO()
                .start()
            process.waitFor()
        }
        logger.lifecycle(&amp;quot;Tous les modèles gratuits pullés&amp;quot;)
    }
}

// -------------------------------------------------------------------------
// Liste des modèles disponibles sur l&amp;#39;instance B
// -------------------------------------------------------------------------
val listModelsB by tasks.registering(Exec::class) {
    group       = &amp;quot;ollama&amp;quot;
    description = &amp;quot;Liste les modèles disponibles sur l&amp;#39;instance B&amp;quot;
    dependsOn(startOllamaB)

    commandLine(&amp;quot;docker&amp;quot;, &amp;quot;exec&amp;quot;, instanceName, &amp;quot;ollama&amp;quot;, &amp;quot;list&amp;quot;)
}

// -------------------------------------------------------------------------
// Health check — test API sur les deux instances
// -------------------------------------------------------------------------
val testOllamaB by tasks.registering {
    group       = &amp;quot;ollama&amp;quot;
    description = &amp;quot;Teste la connectivité API de l&amp;#39;instance B avec un simple chat&amp;quot;
    dependsOn(startOllamaB)

    doLast {
        val model = project.findProperty(&amp;quot;model&amp;quot;) as? String ?: &amp;quot;qwen3:0.6b&amp;quot;
        logger.lifecycle(&amp;quot;Test de l&amp;#39;instance B avec le modèle &amp;#39;$model&amp;#39;...&amp;quot;)

        val payload = &amp;quot;&amp;quot;&amp;quot;
            {
              &amp;quot;model&amp;quot;: &amp;quot;$model&amp;quot;,
              &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Réponds uniquement par OK&amp;quot;}],
              &amp;quot;max_tokens&amp;quot;: 5
            }
        &amp;quot;&amp;quot;&amp;quot;.trimIndent()

        val process = ProcessBuilder(
            &amp;quot;curl&amp;quot;, &amp;quot;-s&amp;quot;, &amp;quot;http://localhost:$instancePort/v1/chat/completions&amp;quot;,
            &amp;quot;-H&amp;quot;, &amp;quot;Content-Type: application/json&amp;quot;,
            &amp;quot;-d&amp;quot;, payload
        ).start()

        val response = process.inputStream.bufferedReader().readText()
        process.waitFor()

        if (response.contains(&amp;quot;\&amp;quot;id\&amp;quot;:\&amp;quot;chatcmpl&amp;quot;) || response.contains(&amp;quot;\&amp;quot;choices\&amp;quot;&amp;quot;)) {
            println(&amp;quot;✓ Instance B OK — port $instancePort répond&amp;quot;)
            println(&amp;quot;  Response: ${response.take(120)}...&amp;quot;)
        } else {
            println(&amp;quot;✗ Instance B INACTIVE — vérifie le conteneur avec &amp;#39;./gradlew statusOllamaAll&amp;#39;&amp;quot;)
            println(&amp;quot;  Raw: $response&amp;quot;)
        }
    }
}

// -------------------------------------------------------------------------
// Health check sur les deux instances simultanément
// -------------------------------------------------------------------------
val statusOllamaAll by tasks.registering {
    group       = &amp;quot;ollama&amp;quot;
    description = &amp;quot;Vérifie le statut des deux instances Ollama (native + Docker)&amp;quot;

    doLast {
        // Instance native
        runCatching {
            val process = ProcessBuilder(
                &amp;quot;curl&amp;quot;, &amp;quot;-s&amp;quot;, &amp;quot;-o&amp;quot;, &amp;quot;/dev/null&amp;quot;, &amp;quot;-w&amp;quot;, &amp;quot;%{http_code}&amp;quot;,
                &amp;quot;http://localhost:$nativePort/api/tags&amp;quot;
            ).start()
            val code = process.inputStream.bufferedReader().readText().trim()
            process.waitFor()
            println(if (code == &amp;quot;200&amp;quot;) &amp;quot;✓ Instance Native   — port $nativePort OK (HTTP $code)&amp;quot;
                    else &amp;quot;✗ Instance Native — port $nativePort (HTTP $code)&amp;quot;)
        }.getOrElse {
            println(&amp;quot;✗ Instance Native — injoignable sur le port $nativePort&amp;quot;)
        }

        // Instance Docker
        runCatching {
            val process = ProcessBuilder(
                &amp;quot;curl&amp;quot;, &amp;quot;-s&amp;quot;, &amp;quot;-o&amp;quot;, &amp;quot;/dev/null&amp;quot;, &amp;quot;-w&amp;quot;, &amp;quot;%{http_code}&amp;quot;,
                &amp;quot;http://localhost:$instancePort/api/tags&amp;quot;
            ).start()
            val code = process.inputStream.bufferedReader().readText().trim()
            process.waitFor()
            println(if (code == &amp;quot;200&amp;quot;) &amp;quot;✓ Instance Docker B — port $instancePort OK (HTTP $code)&amp;quot;
                    else &amp;quot;✗ Instance Docker B — port $instancePort (HTTP $code)&amp;quot;)
        }.getOrElse {
            println(&amp;quot;✗ Instance Docker B — injoignable sur le port $instancePort&amp;quot;)
        }

        // Info conteneur
        runCatching {
            val process = ProcessBuilder(&amp;quot;docker&amp;quot;, &amp;quot;ps&amp;quot;, &amp;quot;--filter&amp;quot;, &amp;quot;name=$instanceName&amp;quot;,
                &amp;quot;--format&amp;quot;, &amp;quot;table {{.Names}}\\t{{.Status}}\\t{{.Ports}}&amp;quot;).start()
            val status = process.inputStream.bufferedReader().readText()
            process.waitFor()
            println()
            println(&amp;quot;Conteneur Docker :&amp;quot;)
            println(status)
        }
    }
}

// -------------------------------------------------------------------------
// Nettoyage complet
// -------------------------------------------------------------------------
val cleanOllamaB by tasks.registering(Exec::class) {
    group       = &amp;quot;ollama&amp;quot;
    description = &amp;quot;Arrête et supprime le conteneur Docker de l&amp;#39;instance B&amp;quot;
    dependsOn(stopOllamaB)

    commandLine(&amp;quot;docker&amp;quot;, &amp;quot;rm&amp;quot;, instanceName)
    isIgnoreExitValue = true

    doLast {
        logger.lifecycle(&amp;quot;Conteneur &amp;#39;$instanceName&amp;#39; supprimé&amp;quot;)
        logger.lifecycle(&amp;quot;Le volume ${dataDir.absolutePath} est conservé (identité persistante)&amp;quot;)
    }
}

// -------------------------------------------------------------------------
// Affichage des instructions
// -------------------------------------------------------------------------
val helpOllama by tasks.registering {
    group       = &amp;quot;ollama&amp;quot;
    description = &amp;quot;Affiche l&amp;#39;aide des tâches Ollama disponibles&amp;quot;

    doLast {
        println(&amp;quot;&amp;quot;&amp;quot;
        ╔══════════════════════════════════════════════════════════════╗
        ║         Tâches Gradle — Pilotage Dual Ollama Pro            ║
        ╠══════════════════════════════════════════════════════════════╣
        ║  ./gradlew startOllamaB      Démarrer l&amp;#39;instance Docker B   ║
        ║  ./gradlew stopOllamaB       Arrêter l&amp;#39;instance Docker B    ║
        ║  ./gradlew checkIdentity     Afficher la clé SSH publique   ║
        ║  ./gradlew signInB           Sign-in interactif compte B    ║
        ║  ./gradlew pullModelB        Pull un modèle (-Pmodel=...)   ║
        ║  ./gradlew pullAllProModels  Pull tous les modèles Pro      ║
        ║  ./gradlew pullAllFreeModels Pull tous les modèles gratuits ║
        ║  ./gradlew listModelsB       Lister les modèles instance B  ║
        ║  ./gradlew testOllamaB       Test API avec un chat simple   ║
        ║  ./gradlew statusOllamaAll   Santé des 2 instances          ║
        ║  ./gradlew cleanOllamaB      Supprimer le conteneur         ║
        ║  ./gradlew helpOllama        Cette aide                     ║
        ╚══════════════════════════════════════════════════════════════╝
        &amp;quot;&amp;quot;&amp;quot;.trimIndent())
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Voilà. Douze tâches, un point d&amp;amp;#8217;entrée unique, et zéro friction.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_anatomie_des_tâches_clés&amp;quot;&amp;gt;Anatomie des Tâches Clés&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_startollamab_le_lanceur&amp;quot;&amp;gt;&amp;lt;code&amp;gt;startOllamaB&amp;lt;/code&amp;gt; — Le Lanceur&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Rien de sorcier : un &amp;lt;code&amp;gt;docker run -d&amp;lt;/code&amp;gt; avec les bons paramètres. L&amp;amp;#8217;astuce est dans &amp;lt;code&amp;gt;isIgnoreExitValue = true&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;isIgnoreExitValue = true&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Si le conteneur existe déjà, la commande &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt; échoue (exit code ≠ 0). Sans cette propriété, Gradle arrêterait tout le build en erreur. Ici, l&amp;amp;#8217;échec est silencieux — et le &amp;lt;code&amp;gt;doLast&amp;lt;/code&amp;gt; détecte si c&amp;amp;#8217;était un &amp;quot;déjà existant&amp;quot; ou une vraie erreur.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le &amp;lt;code&amp;gt;doLast&amp;lt;/code&amp;gt; est crucial : il tourne &amp;lt;strong&amp;gt;après&amp;lt;/strong&amp;gt; l&amp;amp;#8217;exécution de la commande, ce qui permet d&amp;amp;#8217;inspecter &amp;lt;code&amp;gt;executionResult.get().exitValue&amp;lt;/code&amp;gt; et de logger un message approprié.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_signinb_linteractif&amp;quot;&amp;gt;&amp;lt;code&amp;gt;signInB&amp;lt;/code&amp;gt; — L&amp;amp;#8217;Interactif&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est la seule tâche qui nécessite une interaction humaine. Gradle transmet &amp;lt;code&amp;gt;System.in&amp;lt;/code&amp;gt; au process pour que le prompt &amp;lt;code&amp;gt;ollama signin&amp;lt;/code&amp;gt; puisse s&amp;amp;#8217;afficher normalement :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;standardInput  = System.`in`
standardOutput = System.out
errorOutput    = System.err&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Sans ça, le sign-in bloquerait car stdin serait fermé et vous ne verriez jamais le prompt.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_pullmodelb_le_paramétrable&amp;quot;&amp;gt;&amp;lt;code&amp;gt;pullModelB&amp;lt;/code&amp;gt; — Le Paramétrable&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Une tâche générique qui accepte un paramètre via &amp;lt;code&amp;gt;-P&amp;lt;/code&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;./gradlew pullModelB -Pmodel=deepseek-v4-pro:cloud
./gradlew pullModelB                           # fallback : qwen3:0.6b&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le fallback est important : &amp;lt;code&amp;gt;project.findProperty(&amp;quot;model&amp;quot;) as? String ?: &amp;quot;qwen3:0.6b&amp;quot;&amp;lt;/code&amp;gt; garantit que la tâche ne pète pas si on oublie le paramètre.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_statusollamaall_le_diagnostic&amp;quot;&amp;gt;&amp;lt;code&amp;gt;statusOllamaAll&amp;lt;/code&amp;gt; — Le Diagnostic&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Deux &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; en santé sur les ports &amp;lt;code&amp;gt;11434&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;11435&amp;lt;/code&amp;gt;, avec un fallback en &amp;lt;code&amp;gt;runCatching&amp;lt;/code&amp;gt; pour ne pas crasher si l&amp;amp;#8217;une des instances est down. La sortie est structurée :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;✓ Instance Native   — port 11434 OK (HTTP 200)
✓ Instance Docker B — port 11435 OK (HTTP 200)

Conteneur Docker :
NAMES               STATUS         PORTS
ollama-instance-b   Up 3 hours     0.0.0.0:11435-&amp;amp;gt;11434/tcp&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un coup d&amp;amp;#8217;œil, et tu sais exactement ce qui tourne et ce qui cloche.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_cleanollamab_le_nettoyage_qui_préserve_lidentité&amp;quot;&amp;gt;&amp;lt;code&amp;gt;cleanOllamaB&amp;lt;/code&amp;gt; — Le Nettoyage qui Préserve l&amp;amp;#8217;Identité&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;commandLine(&amp;quot;docker&amp;quot;, &amp;quot;rm&amp;quot;, instanceName)
isIgnoreExitValue = true&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le conteneur est supprimé, mais le volume &amp;lt;code&amp;gt;~/ollama-b-data&amp;lt;/code&amp;gt; est &amp;lt;strong&amp;gt;conservé&amp;lt;/strong&amp;gt;. L&amp;amp;#8217;identité SSH survit au nettoyage. Au prochain &amp;lt;code&amp;gt;startOllamaB&amp;lt;/code&amp;gt;, les mêmes clés seront réutilisées — pas besoin de refaire le sign-in ni de ré-enregistrer la Device Key.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock caution&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-caution&amp;quot; title=&amp;quot;🔒&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;cleanOllamaB&amp;lt;/code&amp;gt; ne touche pas au volume. Si tu veux effacer l&amp;amp;#8217;identité B (et tout recommencer à zéro), il faut supprimer &amp;lt;code&amp;gt;~/ollama-b-data&amp;lt;/code&amp;gt; manuellement. C&amp;amp;#8217;est volontaire — un &amp;lt;code&amp;gt;clean&amp;lt;/code&amp;gt; ne devrait pas détruire des credentials.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_workflow_complet_de_zéro_à_deux_sessions&amp;quot;&amp;gt;Workflow Complet — De Zéro à Deux Sessions&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Voici la séquence idéale pour quelqu&amp;amp;#8217;un qui arrive sur le projet et veut tout mettre en place sans ouvrir de documentation :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;# 1. Premier contact — que faire ?
$ ./gradlew helpOllama

# 2. On démarre l&amp;#39;instance B
$ ./gradlew startOllamaB

# 3. On récupère la Device Key et on l&amp;#39;enregistre sur ollama.com
$ ./gradlew checkIdentity
# → copier-coller de la clé sur https://ollama.com/settings/keys

# 4. Authentification interactive
$ ./gradlew signInB

# 5. Pull d&amp;#39;un petit modèle gratuit pour tester la plomberie
$ ./gradlew pullModelB

# 6. Test API
$ ./gradlew testOllamaB

# 7. Si tout est vert, pull des modèles Pro
$ ./gradlew pullAllProModels

# 8. Vérification finale des deux instances
$ ./gradlew statusOllamaAll&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Moins de deux minutes, tout est provisionné. Pas de README à lire, pas de variables d&amp;amp;#8217;environnement à setter. La tâche &amp;lt;code&amp;gt;helpOllama&amp;lt;/code&amp;gt; fait office de documentation intégrée.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/workflow-complet-sequence.svg&amp;quot; alt=&amp;quot;workflow complet sequence&amp;quot; width=&amp;quot;757&amp;quot; height=&amp;quot;1103&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_pourquoi_ne_pas_en_faire_un_vrai_plugin_gradle&amp;quot;&amp;gt;Pourquoi Ne Pas en Faire un Vrai Plugin Gradle ?&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Question légitime. Extraire ce &amp;lt;code&amp;gt;build.gradle.kts&amp;lt;/code&amp;gt; en un plugin Gradle autonome aurait des avantages : réutilisation entre projets, configuration déclarative, extension DSL.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mais pour l&amp;amp;#8217;instant, ça n&amp;amp;#8217;a pas de sens. Ce build n&amp;amp;#8217;a pas de logique métier complexe — c&amp;amp;#8217;est un wrapper autour de commandes Docker et curl. La surcouche d&amp;amp;#8217;un plugin Gradle complet (avec extension, tests unitaires, publication) serait disproportionnée pour 12 tâches utilitaires.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le &amp;lt;code&amp;gt;build.gradle.kts&amp;lt;/code&amp;gt; inline vit dans le projet qui en a besoin. Il est trivial à copier ailleurs. Si un jour j&amp;amp;#8217;ai trois projets qui en dépendent, je le transformerai en plugin. Pour l&amp;amp;#8217;instant, KISS.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;ℹ️&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le jour où tu as trois &amp;lt;code&amp;gt;build.gradle.kts&amp;lt;/code&amp;gt; identiques dans trois projets, c&amp;amp;#8217;est le signal qu&amp;amp;#8217;il faut extraire un plugin. Avant ça, la duplication est moins coûteuse que l&amp;amp;#8217;abstraction. Sagesse de dev.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_leçons_apprises&amp;quot;&amp;gt;Leçons Apprises&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Gradle n&amp;amp;#8217;est pas qu&amp;amp;#8217;un build tool&amp;lt;/strong&amp;gt; — Le moteur de graphe de dépendances en fait un orchestrateur d&amp;amp;#8217;infrastructure redoutable. &amp;lt;code&amp;gt;doLast&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;isIgnoreExitValue&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;dependsOn&amp;lt;/code&amp;gt; : ces trois primitives suffisent à piloter un conteneur Docker avec la même fiabilité qu&amp;amp;#8217;un pipeline CI.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;code&amp;gt;isIgnoreExitValue&amp;lt;/code&amp;gt; est ton ami&amp;lt;/strong&amp;gt; — Dans un monde idéal, &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt; sur un conteneur déjà existant renverrait un warning plutôt qu&amp;amp;#8217;un exit code d&amp;amp;#8217;erreur. Dans le monde réel, tu mets &amp;lt;code&amp;gt;isIgnoreExitValue = true&amp;lt;/code&amp;gt; et tu gères le diagnostic dans &amp;lt;code&amp;gt;doLast&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Les tâches paramétrables tuent l&amp;amp;#8217;ambiguïté&amp;lt;/strong&amp;gt; — Un &amp;lt;code&amp;gt;pullModelB&amp;lt;/code&amp;gt; générique avec &amp;lt;code&amp;gt;-Pmodel=&amp;amp;#8230;&amp;amp;#8203;&amp;lt;/code&amp;gt; remplace N tâches spécialisées. Une seule tâche, une seule doc, un seul comportement.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;code&amp;gt;runCatching&amp;lt;/code&amp;gt; pour les health checks&amp;lt;/strong&amp;gt; — Quand tu testes N endpoints, le crash du premier ne doit pas empêcher de tester les autres. &amp;lt;code&amp;gt;runCatching&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;getOrElse&amp;lt;/code&amp;gt; par endpoint, et le diagnostic reste complet même en cas de panne partielle.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;La tâche &amp;lt;code&amp;gt;helpOllama&amp;lt;/code&amp;gt; comme documentation exécutable&amp;lt;/strong&amp;gt; — Un &amp;lt;code&amp;gt;println()&amp;lt;/code&amp;gt; bien formaté remplace un README de trois paragraphes. C&amp;amp;#8217;est auto-documenté, toujours à jour, et accessible sans sortir du terminal.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_conclusion&amp;quot;&amp;gt;Conclusion&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;On est passé de commandes docker à taper à la main à un workflow Gradle complet, versionné, réutilisable. Douze tâches couvrent tout le cycle de vie : provisionnement, identité, sign-in, pull, test, diagnostic, nettoyage.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le combo docker-compose + build.gradle.kts + opencode.json forme une trinité propre : Docker pour l&amp;amp;#8217;isolation, Gradle pour l&amp;amp;#8217;orchestration, OpenCode pour la consommation. Chaque couche a sa responsabilité, et aucune ne déborde sur l&amp;amp;#8217;autre.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Prochaine étape ? Automatiser le cycle de vie dans la CI pour que les instances Ollama soient disponibles dans les environnements de dev éphémères. Mais ça, c&amp;amp;#8217;est un autre article.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_ressources&amp;quot;&amp;gt;Ressources&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://docs.gradle.org/current/userguide/tutorial_using_tasks.html&amp;quot;&amp;gt;User Manual Gradle — Tâches&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://docs.gradle.org/current/userguide/custom_tasks.html&amp;quot;&amp;gt;User Manual Gradle — Tâches Custom&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://hub.docker.com/r/ollama/ollama&amp;quot;&amp;gt;Image Docker Ollama sur Docker Hub&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://kotlinlang.org/docs/gradle.html&amp;quot;&amp;gt;Gradle DSL Kotlin — Documentation&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;Article publié le 2026-05-08&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Cumuler Deux Abonnements Ollama Pro sur la Même Machine avec Docker</title>
            <link >https://cheroliv.com/blog/2026/0120_cumuler_deux_abonnements_ollama_pro_docker_post.html</link>
            <pubDate>Fri, 8 May 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0120_cumuler_deux_abonnements_ollama_pro_docker_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_introduction&amp;quot;&amp;gt;Introduction&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pourquoi_deux_fois_la_même_chose&amp;quot;&amp;gt;Pourquoi Deux Fois la Même Chose ?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_coeur_du_problème_la_device_key&amp;quot;&amp;gt;Le Coeur du Problème : La Device Key&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_mise_en_place_étape_par_étape&amp;quot;&amp;gt;Mise en Place — Étape par Étape&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_prérequis&amp;quot;&amp;gt;Prérequis&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_étape_1_créer_le_volume&amp;quot;&amp;gt;Étape 1 : Créer le Volume&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_étape_2_lancer_le_conteneur_docker&amp;quot;&amp;gt;Étape 2 : Lancer le Conteneur Docker&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_étape_3_récupérer_la_clé_publique&amp;quot;&amp;gt;Étape 3 : Récupérer la Clé Publique&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_étape_4_enregistrer_la_clé_sur_ollama_com&amp;quot;&amp;gt;Étape 4 : Enregistrer la Clé sur Ollama.com&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_étape_5_tester_avec_un_petit_modèle_gratuit&amp;quot;&amp;gt;Étape 5 : Tester avec un Petit Modèle Gratuit&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_piège_de_lapi_v1models&amp;quot;&amp;gt;Le Piège de l&amp;amp;#8217;API &amp;lt;code&amp;gt;/v1/models&amp;lt;/code&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_résultat_deux_sessions_deux_comptes_zéro_conflit&amp;quot;&amp;gt;Résultat : Deux Sessions, Deux Comptes, Zéro Conflit&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_leçons_apprises&amp;quot;&amp;gt;Leçons Apprises&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pour_aller_plus_loin&amp;quot;&amp;gt;Pour Aller Plus Loin&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 14 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Deux abonnements Pro, une seule machine, une seule carte bancaire, et zéro conflit réseau. Comment Docker m&amp;amp;#8217;a permis de doubler ma capacité d&amp;amp;#8217;inférence cloud sans acheter un deuxième PC.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_introduction&amp;quot;&amp;gt;Introduction&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;utilise Ollama Pro depuis plusieurs mois pour alimenter mes sessions OpenCode en modèles cloud. Le truc, c&amp;amp;#8217;est que même avec un abonnement Pro, on est vite limité par le &amp;lt;strong&amp;gt;rate limiting&amp;lt;/strong&amp;gt; quand on lance plusieurs agents en parallèle. La solution évidente : un deuxième abonnement.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mais là, c&amp;amp;#8217;est le drame.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ollama identifie chaque machine par une clé SSH unique — sa fameuse &amp;lt;strong&amp;gt;Device Key&amp;lt;/strong&amp;gt;. Deux instances sur le même OS partageraient la même identité, et impossible de lier deux comptes Pro au même device. Et comme vous vous en doutez, je n&amp;amp;#8217;allais pas acheter un deuxième laptop juste pour ça.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La solution : tricher. Faire croire à Ollama qu&amp;amp;#8217;il tourne sur deux machines différentes, alors qu&amp;amp;#8217;elles partagent le même CPU, la même RAM, et la même connexion réseau. Docker va nous offrir une bulle d&amp;amp;#8217;isolation parfaite.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/architecture-dual-ollama.svg&amp;quot; alt=&amp;quot;architecture dual ollama&amp;quot; width=&amp;quot;509&amp;quot; height=&amp;quot;420&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_pourquoi_deux_fois_la_même_chose&amp;quot;&amp;gt;Pourquoi Deux Fois la Même Chose ?&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avant de me traiter de malade mental, laissez-moi vous expliquer le cas d&amp;amp;#8217;usage.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avec un seul abonnement Pro, je peux lancer un modèle comme &amp;lt;code&amp;gt;deepseek-v4-pro:cloud&amp;lt;/code&amp;gt; dans une session OpenCode. Le problème surgit quand je veux &amp;lt;strong&amp;gt;deux&amp;lt;/strong&amp;gt; sessions simultanées. Les quotas de rate limiting font que la deuxième session rame ou est purement rejetée.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avec deux abonnements Pro indépendants :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Session OpenCode 1 → Compte Pro A (&amp;lt;code&amp;gt;localhost:11434&amp;lt;/code&amp;gt;)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Session OpenCode 2 → Compte Pro B (&amp;lt;code&amp;gt;localhost:11435&amp;lt;/code&amp;gt;)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Chaque session a son propre quota, son propre contexte, et ne gêne pas l&amp;amp;#8217;autre. C&amp;amp;#8217;est du multi-processing humain.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock important&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-important&amp;quot; title=&amp;quot;❗&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Deux abonnements Pro = deux emails différents. La même carte bancaire fonctionne — le système de paiement Ollama ne bloque pas les souscriptions multiples depuis le même moyen de paiement. J&amp;amp;#8217;ai vérifié.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_coeur_du_problème_la_device_key&amp;quot;&amp;gt;Le Coeur du Problème : La Device Key&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Quand vous installez Ollama, une paire de clés SSH ed25519 est générée dans le répertoire d&amp;amp;#8217;identité :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ cat /usr/share/ollama/.ollama/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Cette clé est uploadée vers les serveurs d&amp;amp;#8217;Ollama lors du &amp;lt;code&amp;gt;ollama signin&amp;lt;/code&amp;gt;. C&amp;amp;#8217;est elle qui dit « cette machine appartient à tel compte Pro ». Si vos deux instances partagent le même fichier &amp;lt;code&amp;gt;id_ed25519&amp;lt;/code&amp;gt;, elles partagent la même identité. Fin du game.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La parade : donner à notre deuxième instance son propre répertoire d&amp;amp;#8217;identité, isolé dans un volume Docker.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_mise_en_place_étape_par_étape&amp;quot;&amp;gt;Mise en Place — Étape par Étape&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_prérequis&amp;quot;&amp;gt;Prérequis&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Une installation native d&amp;amp;#8217;Ollama fonctionnelle (script officiel &amp;lt;code&amp;gt;curl | sh&amp;lt;/code&amp;gt;)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Docker installé et fonctionnel&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Portainer ou docker-compose pour le déploiement&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Deux comptes Ollama avec deux emails distincts&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ai utilisé la version &amp;lt;code&amp;gt;0.20.2&amp;lt;/code&amp;gt; — celle fournie par le script officiel et l&amp;amp;#8217;image Docker correspondante.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_étape_1_créer_le_volume&amp;quot;&amp;gt;Étape 1 : Créer le Volume&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un simple répertoire sur l&amp;amp;#8217;hôte servira de volume persistant pour l&amp;amp;#8217;identité de l&amp;amp;#8217;instance B :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;mkdir -p ~/ollama-b-data&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce dossier sera monté dans le conteneur Docker comme &amp;lt;code&amp;gt;/root/.ollama&amp;lt;/code&amp;gt;, là où Ollama stocke ses clés d&amp;amp;#8217;identité, son historique et ses modèles.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_étape_2_lancer_le_conteneur_docker&amp;quot;&amp;gt;Étape 2 : Lancer le Conteneur Docker&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-yaml hljs&amp;quot; data-lang=&amp;quot;yaml&amp;quot;&amp;gt;# docker-compose.yml
services:
  ollama-instance-b:
    image: ollama/ollama:0.20.2
    container_name: ollama-instance-b
    ports:
      - &amp;quot;11435:11434&amp;quot;
    volumes:
      - /home/cheroliv/ollama-b-data:/root/.ollama
    environment:
      - OLLAMA_HOST=0.0.0.0
    restart: always&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce qui se passe ici :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le port &amp;lt;strong&amp;gt;11435&amp;lt;/strong&amp;gt; de l&amp;amp;#8217;hôte est mappé sur le &amp;lt;strong&amp;gt;11434&amp;lt;/strong&amp;gt; interne du conteneur. Ainsi, l&amp;amp;#8217;instance Docker écoute sur &amp;lt;code&amp;gt;:11435&amp;lt;/code&amp;gt; sans conflit avec l&amp;amp;#8217;instance native qui squatte &amp;lt;code&amp;gt;:11434&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le volume &amp;lt;code&amp;gt;~/ollama-b-data&amp;lt;/code&amp;gt; est monté sur &amp;lt;code&amp;gt;/root/.ollama&amp;lt;/code&amp;gt; — c&amp;amp;#8217;est là que l&amp;amp;#8217;identité SSH sera stockée.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;OLLAMA_HOST=0.0.0.0&amp;lt;/code&amp;gt; permet au conteneur d&amp;amp;#8217;accepter des connexions externes.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ai déployé cette stack via Portainer, mais un simple &amp;lt;code&amp;gt;docker compose up -d&amp;lt;/code&amp;gt; fonctionne tout aussi bien.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_étape_3_récupérer_la_clé_publique&amp;quot;&amp;gt;Étape 3 : Récupérer la Clé Publique&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le conteneur étant vierge au premier démarrage, Ollama génère automatiquement une nouvelle paire de clés SSH dans le volume. On récupère la clé publique :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ docker exec ollama-instance-b cat /root/.ollama/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDDQ+dvnfmuo49q5O8LOlvgZ39SKORFw47ry9k4H2jPc&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Je vérifie que cette clé est &amp;lt;strong&amp;gt;différente&amp;lt;/strong&amp;gt; de celle de l&amp;amp;#8217;instance native :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Instance native
$ cat /usr/share/ollama/.ollama/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGyF...(différente)

# Instance Docker
$ cat ~/ollama-b-data/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDDQ...(différente)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Deux clés distinctes, deux identités séparées. Le tour est joué.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;ℹ️&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Si votre conteneur redémarre, il &amp;lt;strong&amp;gt;réutilise&amp;lt;/strong&amp;gt; les clés présentes dans le volume. L&amp;amp;#8217;identité est persistante. Vous ne perdrez pas l&amp;amp;#8217;association avec le compte Pro.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_étape_4_enregistrer_la_clé_sur_ollama_com&amp;quot;&amp;gt;Étape 4 : Enregistrer la Clé sur Ollama.com&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Direction &amp;lt;a href=&amp;quot;https://ollama.com/settings/keys&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://ollama.com/settings/keys&amp;lt;/a&amp;gt; → Add SSH Key. On colle la clé publique de l&amp;amp;#8217;instance Docker et on valide.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ensuite, on lie cette identité au compte Pro B :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ docker exec -it ollama-instance-b ollama signin&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le navigateur s&amp;amp;#8217;ouvre, on se connecte avec l&amp;amp;#8217;email du compte B, et le token est associé à la clé SSH du conteneur. On vérifie que tout est OK :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ docker exec -it ollama-instance-b ollama signin
User: cherolivpro&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_étape_5_tester_avec_un_petit_modèle_gratuit&amp;quot;&amp;gt;Étape 5 : Tester avec un Petit Modèle Gratuit&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avant de balancer le prix d&amp;amp;#8217;un abonnement Pro, je veux être certain que le tuyau fonctionne. Je pull un petit modèle local et gratuit pour valider la connectivité :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ docker exec ollama-instance-b ollama pull qwen3:0.6b
pulling manifest
pulling 7f4030143c1c: 100% ▕██████████████████▏ 522 MB
success

$ curl -s http://localhost:11435/api/tags
{&amp;quot;models&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;qwen3:0.6b&amp;quot;,&amp;quot;model&amp;quot;:&amp;quot;qwen3:0.6b&amp;quot;,...}]}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le port &amp;lt;code&amp;gt;11435&amp;lt;/code&amp;gt; répond, le modèle est servi. L&amp;amp;#8217;instance B est vivante.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Une fois rassuré, je passe au pull du vrai modèle cloud Pro :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ docker exec ollama-instance-b ollama pull deepseek-v4-pro:cloud
pulling manifest
pulling 31c3059e137e: 100% ▕██████████████████▏  344 B
success&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;344 octets pour le manifeste d&amp;amp;#8217;un modèle cloud — normal, l&amp;amp;#8217;inférence se fait côté serveur, pas en local. Et voilà le test ultime :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ curl -s http://localhost:11435/v1/chat/completions \
  -H &amp;quot;Content-Type: application/json&amp;quot; \
  -d &amp;#39;{&amp;quot;model&amp;quot;:&amp;quot;deepseek-v4-pro:cloud&amp;quot;,&amp;quot;messages&amp;quot;:[{&amp;quot;role&amp;quot;:&amp;quot;user&amp;quot;,&amp;quot;content&amp;quot;:&amp;quot;Dis bonjour en une phrase courte.&amp;quot;}]}&amp;#39;

{
  &amp;quot;id&amp;quot;: &amp;quot;chatcmpl-480&amp;quot;,
  &amp;quot;model&amp;quot;: &amp;quot;deepseek-v4-pro&amp;quot;,
  &amp;quot;choices&amp;quot;: [{
    &amp;quot;message&amp;quot;: { &amp;quot;content&amp;quot;: &amp;quot;Bonjour !&amp;quot; },
    &amp;quot;finish_reason&amp;quot;: &amp;quot;stop&amp;quot;
  }],
  &amp;quot;usage&amp;quot;: { &amp;quot;total_tokens&amp;quot;: 181 }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Bonjour à toi aussi, instance B.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_piège_de_lapi_v1models&amp;quot;&amp;gt;Le Piège de l&amp;amp;#8217;API &amp;lt;code&amp;gt;/v1/models&amp;lt;/code&amp;gt;&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ai perdu 20 minutes sur un détail idiot. Quand j&amp;amp;#8217;ai configuré le provider &amp;lt;code&amp;gt;ollama-b&amp;lt;/code&amp;gt; dans OpenCode, rien n&amp;amp;#8217;apparaissait dans le sélecteur de modèles. Rien. Que dalle.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La raison ? L&amp;amp;#8217;API &amp;lt;code&amp;gt;/v1/models&amp;lt;/code&amp;gt; de l&amp;amp;#8217;instance B retournait &amp;lt;code&amp;gt;{&amp;quot;object&amp;quot;:&amp;quot;list&amp;quot;,&amp;quot;data&amp;quot;:null}&amp;lt;/code&amp;gt; au lieu de &amp;lt;code&amp;gt;{&amp;quot;object&amp;quot;:&amp;quot;list&amp;quot;,&amp;quot;data&amp;quot;:[]}&amp;lt;/code&amp;gt; quand aucun modèle n&amp;amp;#8217;était pullé. La valeur &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; faisait planter le parsing côté OpenCode, qui n&amp;amp;#8217;affichait pas le provider.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La solution : déclarer les modèles &amp;lt;strong&amp;gt;explicitement&amp;lt;/strong&amp;gt; dans la configuration OpenCode plutôt que de compter sur la découverte dynamique.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;~/.config/opencode/opencode.json&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-json hljs&amp;quot; data-lang=&amp;quot;json&amp;quot;&amp;gt;{
  &amp;quot;$schema&amp;quot;: &amp;quot;https://opencode.ai/config.json&amp;quot;,
  &amp;quot;provider&amp;quot;: {
    &amp;quot;ollama&amp;quot;: {
      &amp;quot;npm&amp;quot;: &amp;quot;@ai-sdk/openai-compatible&amp;quot;,
      &amp;quot;name&amp;quot;: &amp;quot;Ollama (local)&amp;quot;,
      &amp;quot;options&amp;quot;: { &amp;quot;baseURL&amp;quot;: &amp;quot;http://localhost:11434/v1&amp;quot; },
      &amp;quot;models&amp;quot;: {
        &amp;quot;gemma4:e2b&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;Gemma 4 E2B (local)&amp;quot; }
      }
    },
    &amp;quot;ollama-b&amp;quot;: {
      &amp;quot;npm&amp;quot;: &amp;quot;@ai-sdk/openai-compatible&amp;quot;,
      &amp;quot;name&amp;quot;: &amp;quot;Ollama Instance B (Docker)&amp;quot;,
      &amp;quot;options&amp;quot;: { &amp;quot;baseURL&amp;quot;: &amp;quot;http://localhost:11435/v1&amp;quot; },
      &amp;quot;models&amp;quot;: {
        &amp;quot;qwen3:0.6b&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;Qwen3 0.6B (B)&amp;quot; },
        &amp;quot;deepseek-v4-pro:cloud&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;DeepSeek V4 Pro (B)&amp;quot; }
      }
    }
  }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avec cette déclaration explicite, OpenCode voit immédiatement le provider B et ses modèles. Un redémarrage de session, et le sélecteur &amp;lt;code&amp;gt;/models&amp;lt;/code&amp;gt; affiche les deux instances côte à côte.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock tip&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-tip&amp;quot; title=&amp;quot;💡&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Si vous ne voyez pas votre provider custom dans &amp;lt;code&amp;gt;/models&amp;lt;/code&amp;gt;, ne perdez pas trois heures à redémarrer votre terminal. Déclarez les modèles manuellement dans &amp;lt;code&amp;gt;opencode.json&amp;lt;/code&amp;gt; — ça règle le problème instantanément.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_résultat_deux_sessions_deux_comptes_zéro_conflit&amp;quot;&amp;gt;Résultat : Deux Sessions, Deux Comptes, Zéro Conflit&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Au final, je peux lancer deux sessions OpenCode simultanément :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;Session 1 → /models → Ollama (local) → deepseek-v4-pro:cloud → Compte A
Session 2 → /models → Ollama Instance B (Docker) → deepseek-v4-pro:cloud → Compte B&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Chaque session a son propre quota, son propre rate limit, et ne se marche pas sur les pieds. Même machine, même carte bleue, deux emails différents.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Et le meilleur ? Le conteneur Docker est en &amp;lt;code&amp;gt;restart: always&amp;lt;/code&amp;gt;. Il survit aux reboots du système sans intervention manuelle.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_leçons_apprises&amp;quot;&amp;gt;Leçons Apprises&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Docker isole tout, même l&amp;amp;#8217;identité&amp;lt;/strong&amp;gt; — Un simple bind mount de volume suffit à donner à un conteneur son propre jeu de clés SSH, le rendant indistinguable d&amp;amp;#8217;une machine physique différente aux yeux d&amp;amp;#8217;Ollama.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Deux emails, même CB&amp;lt;/strong&amp;gt; — Ollama ne bloque pas les souscriptions multiples depuis le même moyen de paiement. Seul l&amp;amp;#8217;email doit être distinct.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Tester gratuit avant de payer&amp;lt;/strong&amp;gt; — Un &amp;lt;code&amp;gt;ollama pull qwen3:0.6b&amp;lt;/code&amp;gt; (modèle libre, 522 Mo) permet de valider toute la chaîne réseau sans débourser un centime. Vous validez le plomberie d&amp;amp;#8217;abord, vous activez le Pro ensuite.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;code&amp;gt;/v1/models&amp;lt;/code&amp;gt; avec &amp;lt;code&amp;gt;data: null&amp;lt;/code&amp;gt; casse OpenCode&amp;lt;/strong&amp;gt; — Si vous configurez un provider custom avec &amp;lt;code&amp;gt;&amp;quot;models&amp;quot;: {}&amp;lt;/code&amp;gt;, OpenCode tente de découvrir les modèles via l&amp;amp;#8217;API. Si l&amp;amp;#8217;API répond &amp;lt;code&amp;gt;data: null&amp;lt;/code&amp;gt;, le provider n&amp;amp;#8217;apparaît pas. Déclarez les modèles explicitement.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Deux comptes, c&amp;amp;#8217;est du multi-processing humain&amp;lt;/strong&amp;gt; — Un compte Pro = une session OpenCode active. Deux comptes = deux sessions parallèles. Pour quelqu&amp;amp;#8217;un qui jongle entre plusieurs projets Gradle en simultané, c&amp;amp;#8217;est un game changer.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_pour_aller_plus_loin&amp;quot;&amp;gt;Pour Aller Plus Loin&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://ollama.com/settings/keys&amp;quot;&amp;gt;Ollama Settings — Gestion des clés SSH&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://docs.ollama.com/&amp;quot;&amp;gt;Documentation officielle Ollama&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://hub.docker.com/r/ollama/ollama&amp;quot;&amp;gt;Image Docker Ollama sur Docker Hub&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://opencode.ai/docs/providers/#ollama&amp;quot;&amp;gt;OpenCode — Configuration Provider Ollama&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;Article publié le 2026-05-08&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Kitty टर्मिनल स्थापित करें और Zsh को डिफ़ॉल्ट शेल के रूप में कॉन्फ़िगर करें Xubuntu पर</title>
            <link >https://cheroliv.com/blog/2025/0080_kitty_term_post.html</link>
            <pubDate>Thu, 7 May 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0080_kitty_term_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_किट्टी_और_zsh_क्यों_चुनें&amp;quot;&amp;gt;किट्टी और Zsh क्यों चुनें ?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सिस्टम_आवश्यकताएँ&amp;quot;&amp;gt;सिस्टम आवश्यकताएँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_kitty_का_डाउनलोड_और_इंस्टॉलेशन&amp;quot;&amp;gt;Kitty का डाउनलोड और इंस्टॉलेशन&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_इंस्टॉलेशन_स्क्रिप्ट_डाउनलोड_करें&amp;quot;&amp;gt;इंस्टॉलेशन स्क्रिप्ट डाउनलोड करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सांकेतिक_लिंक_बनाना&amp;quot;&amp;gt;सांकेतिक लिंक बनाना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_xubuntu_में_kitty_का_एकीकरण&amp;quot;&amp;gt;Xubuntu में Kitty का एकीकरण&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_फ़ाइल_को_डेस्कटॉप_पर_कॉपी_करें&amp;quot;&amp;gt;फ़ाइल को डेस्कटॉप पर कॉपी करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_डेस्कटॉप_फ़ाइल_संपादित_करें&amp;quot;&amp;gt;डेस्कटॉप फ़ाइल संपादित करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_kitty_को_डिफ़ॉल्ट_टर्मिनल_के_रूप_में_जोड़ें_वैकल्पिक&amp;quot;&amp;gt;Kitty को डिफ़ॉल्ट टर्मिनल के रूप में जोड़ें (वैकल्पिक)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_zsh_की_स्थापना&amp;quot;&amp;gt;Zsh की स्थापना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_zsh_को_डिफ़ॉल्ट_शेल_के_रूप_में_सेट_करें&amp;quot;&amp;gt;Zsh को डिफ़ॉल्ट शेल के रूप में सेट करें&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_वैश्विक_पद्धति_सभी_टर्मिनल_के_लिए&amp;quot;&amp;gt;वैश्विक पद्धति (सभी टर्मिनल के लिए)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_kitty_के_लिए_विशिष्ट_विधि&amp;quot;&amp;gt;Kitty के लिए विशिष्ट विधि&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_zsh_की_कॉन्फ़िगरेशन_वैकल्पिक&amp;quot;&amp;gt;Zsh की कॉन्फ़िगरेशन (वैकल्पिक)&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_एक_zshrc_फ़ाइल_बनाएँ&amp;quot;&amp;gt;एक .zshrc फ़ाइल बनाएँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_exemple_de_configuration_minimale&amp;quot;&amp;gt;Exemple de configuration minimale&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_वर्कफ़्लो_का_पूर्ण_सारांश&amp;quot;&amp;gt;वर्कफ़्लो का पूर्ण सारांश&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अंतिम_सत्यापन&amp;quot;&amp;gt;अंतिम सत्यापन&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_कॉन्फ़िगरेशन_फ़ाइल_खोलें&amp;quot;&amp;gt;📂 कॉन्फ़िगरेशन फ़ाइल खोलें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_️_जोड़ें_या_संपादित_करें_font_size&amp;quot;&amp;gt;🖋️ जोड़ें या संपादित करें `font_size&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_kitty_को_सहेजें_और_पुनः_प्रारंभ_करें&amp;quot;&amp;gt;�💾 Kitty को सहेजें और पुनः प्रारंभ करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_गतिशील_समायोजन_अस्थायी_ज़ूम&amp;quot;&amp;gt;✅ गतिशील समायोजन (अस्थायी ज़ूम)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_oh_my_zsh_की_स्थापना_और_कॉन्फ़िगरेशन&amp;quot;&amp;gt;Oh My Zsh की स्थापना और कॉन्फ़िगरेशन&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_oh_my_zsh_का_इंस्टॉलेशन&amp;quot;&amp;gt;Oh My Zsh का इंस्टॉलेशन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_jbake_cli_commands_initialize_a_new_jbake_project_jbake_i&amp;quot;&amp;gt;JBake CLI Commands &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; # Initialize a new JBake project jbake -i&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_generate_the_site_jbake_b&amp;quot;&amp;gt;Bake (generate) the site jbake -b&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_and_serve_locally_jbake_b_s&amp;quot;&amp;gt;Bake and serve locally jbake -b -s&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_and_watch_for_changes_jbake_b_reset&amp;quot;&amp;gt;Bake and watch for changes jbake -b --reset&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_specify_source_and_destination_jbake_source_folder_output_folder&amp;quot;&amp;gt;Specify source and destination jbake source_folder output_folder&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_clear_the_output_directory_before_baking_jbake_b_output_reset&amp;quot;&amp;gt;Clear the output directory before baking jbake -b . output --reset &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt;&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_थीम_बदलें&amp;quot;&amp;gt;थीम बदलें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सत्यापन&amp;quot;&amp;gt;सत्यापन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_यूज़_केस_डायग्राम&amp;quot;&amp;gt;यूज़ केस डायग्राम&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_kitty_में_पारदर्शिता_सक्षम_करें&amp;quot;&amp;gt;Kitty में पारदर्शिता सक्षम करें&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पारदर्शिता_के_लिए_पूर्वापेक्षा&amp;quot;&amp;gt;पारदर्शिता के लिए पूर्वापेक्षा&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_kitty_conf_में_पारदर्शिता_की_कॉन्फ़िगरेशन&amp;quot;&amp;gt;kitty.conf में पारदर्शिता की कॉन्फ़िगरेशन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_किटी_को_रीस्टार्ट_करें&amp;quot;&amp;gt;किटी को रीस्टार्ट करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संभावित_पूरक&amp;quot;&amp;gt;संभावित पूरक&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सीक्वेंस_डायग्राम_पारदर्शिता_के_साथ_किट्टी_का_प्रारंभ&amp;quot;&amp;gt;सीक्वेंस डायग्राम - पारदर्शिता के साथ किट्टी का प्रारंभ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ज्ञात_सीमाएँ&amp;quot;&amp;gt;ज्ञात सीमाएँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ध्वनि_बीप_सुनाई_देने_वाली_घंटी_को_बंद_करें&amp;quot;&amp;gt;ध्वनि बीप (सुनाई देने वाली घंटी) को बंद करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_किट्टी_का_अपडेट&amp;quot;&amp;gt;किट्टी का अपडेट&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संदर्भ&amp;quot;&amp;gt;संदर्भ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह गाइड चरण दर चरण बताता है कि Xubuntu पर &amp;lt;strong&amp;gt;kitty&amp;lt;/strong&amp;gt; टर्मिनल कैसे स्थापित करें, इसे सही तरीके से कॉन्फ़िगर करें, और bash को डिफ़ॉल्ट शेल के रूप में &amp;lt;strong&amp;gt;zsh&amp;lt;/strong&amp;gt; से बदलें। किट्टी प्रोजेक्ट यहाँ उपलब्ध है : &amp;lt;a href=&amp;quot;https://github.com/kovidgoyal/kitty&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://github.com/kovidgoyal/kitty&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;(No output) Kitty एक आधुनिक, तेज़ और कॉन्फ़िगरेबल टर्मिनल है, जो विशेष रूप से मांग वाले डेवलपर्स के लिए उपयुक्त है। &amp;lt;em&amp;gt;__&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_किट्टी_और_zsh_क्यों_चुनें&amp;quot;&amp;gt;किट्टी और Zsh क्यों चुनें ?&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Kitty की पहचान:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;जीपीयू त्वरण के कारण उच्च प्रदर्शन,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एक ही पाठ फ़ाइल पर पूरी तरह आधारित कॉन्फ़िगरेशन,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;फ़ॉन्ट और लिगेचर के लिए उत्कृष्ट समर्थन।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Zsh, इसके विपरीत, एक शक्तिशाली इंटरैक्टिव शेल है जो प्रदान करता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एक बुद्धिमान पूर्णता,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एक अनुकूलन योग्य प्रॉम्प्ट,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;बैश के साथ उच्च संगतता।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Kitty और Zsh को जोड़ने से, आपको एक उत्पादक और सुंदर वातावरण मिलता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/kitty-zsh-overview.png&amp;quot; alt=&amp;quot;kitty zsh overview&amp;quot; width=&amp;quot;729&amp;quot; height=&amp;quot;305&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;Note&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह गाइड जानबूझकर स्क्रिप्ट के माध्यम से स्थापना और केवल Xubuntu तक सीमित है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_सिस्टम_आवश्यकताएँ&amp;quot;&amp;gt;सिस्टम आवश्यकताएँ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;शुरू करने से पहले, सुनिश्चित करें कि आपके पास है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Xubuntu स्थापित,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;इंटरनेट तक पहुँच,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;स्क्रिप्ट चलाने के लिए एक कार्यशील बश शेल.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपना पर्यावरण जाँचें:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;uname -a
lsb_release -a&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_kitty_का_डाउनलोड_और_इंस्टॉलेशन&amp;quot;&amp;gt;Kitty का डाउनलोड और इंस्टॉलेशन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;किट्टी इसे एक आधिकारिक स्क्रिप्ट के माध्यम से इंस्टॉल करने की सिफारिश करता है जो फ़ाइलों को रखता है`~/.local/kitty.app`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock important&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-important&amp;quot; title=&amp;quot;Important&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह विधि पैकेज प्रबंधकों से स्वतंत्र है (कोई नहीं`apt`).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_इंस्टॉलेशन_स्क्रिप्ट_डाउनलोड_करें&amp;quot;&amp;gt;इंस्टॉलेशन स्क्रिप्ट डाउनलोड करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;निम्नलिखित कमांड चलाएँ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;curl -L https://sw.kovidgoyal.net/kitty/installer.sh | sh /dev/stdin&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह कमांड निम्नलिखित करती है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;बाइनरीज़ का डाउनलोड,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;निष्कर्षण में`~/.local/kitty.app`,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;सांकेतिक लिंक बनाना।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/download-install.svg&amp;quot; alt=&amp;quot;download install&amp;quot; width=&amp;quot;289&amp;quot; height=&amp;quot;336&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सांकेतिक_लिंक_बनाना&amp;quot;&amp;gt;सांकेतिक लिंक बनाना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आह्वान कर सकने के लिए`kitty`टर्मिनल से, एक सिम्बॉलिक लिंक बनाएँ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;ln -s ~/.local/kitty.app/bin/kitty ~/.local/bin/kitty&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जोड़ें`~/.local/bin`अपने PATH में जोड़ें यदि अभी तक नहीं किया गया है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;echo &amp;#39;export PATH=&amp;quot;$HOME/.local/bin:$PATH&amp;quot;&amp;#39; &amp;amp;gt;&amp;amp;gt; ~/.zshrc
source ~/.zshrc&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आप स्थापना की जाँच कर सकते हैं :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;kitty --version&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_xubuntu_में_kitty_का_एकीकरण&amp;quot;&amp;gt;Xubuntu में Kitty का एकीकरण&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;किट्टी को एप्लिकेशन मेन्यू में दिखाने के लिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_फ़ाइल_को_डेस्कटॉप_पर_कॉपी_करें&amp;quot;&amp;gt;फ़ाइल को डेस्कटॉप पर कॉपी करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फ़ाइल कॉपी करें`.desktop`दिया गया:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;cp ~/.local/kitty.app/share/applications/kitty.desktop ~/.local/share/applications/&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_डेस्कटॉप_फ़ाइल_संपादित_करें&amp;quot;&amp;gt;डेस्कटॉप फ़ाइल संपादित करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फ़ाइल संपादित करें:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;nano ~/.local/share/applications/kitty.desktop&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;निम्नलिखित लाइनों की जाँच करें या संपादित करें:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;[Desktop Entry]
Version=1.0
Type=Application
Name=Kitty Terminal
Comment=Fast GPU-based terminal emulator
Exec=/home/$USER/.local/kitty.app/bin/kitty
Icon=kitty
Categories=System;TerminalEmulator;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;बदलें`YOURUSER`आपके उपयोगकर्ता नाम से.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/desktop-integration.png&amp;quot; alt=&amp;quot;desktop integration&amp;quot; width=&amp;quot;476&amp;quot; height=&amp;quot;335&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_kitty_को_डिफ़ॉल्ट_टर्मिनल_के_रूप_में_जोड़ें_वैकल्पिक&amp;quot;&amp;gt;Kitty को डिफ़ॉल्ट टर्मिनल के रूप में जोड़ें (वैकल्पिक)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Kitty को डिफ़ॉल्ट टर्मिनल के रूप में लॉन्च करने के लिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;sudo update-alternatives --install /usr/bin/x-terminal-emulator x-terminal-emulator ~/.local/kitty.app/bin/kitty 50
sudo update-alternatives --config x-terminal-emulator&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;चुनें`kitty`प्रस्तावित मेनू में&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_zsh_की_स्थापना&amp;quot;&amp;gt;Zsh की स्थापना&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यदि Zsh अभी तक स्थापित नहीं है, निष्पादित करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;sudo apt install zsh&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;स्थापना की जाँच करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;zsh --version&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_zsh_को_डिफ़ॉल्ट_शेल_के_रूप_में_सेट_करें&amp;quot;&amp;gt;Zsh को डिफ़ॉल्ट शेल के रूप में सेट करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आप अपने शेल को ग्लोबल रूप से बदल सकते हैं या केवल Kitty में।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_वैश्विक_पद्धति_सभी_टर्मिनल_के_लिए&amp;quot;&amp;gt;वैश्विक पद्धति (सभी टर्मिनल के लिए)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;निरपेक्ष पथ पहचानें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;which zsh&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सामान्यतः`/usr/bin/zsh`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;डिफ़ॉल्ट शेल बदलें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;chsh -s /usr/bin/zsh&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;लॉग आउट करें और फिर से लॉग इन करें।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/zsh-default-shell.svg&amp;quot; alt=&amp;quot;zsh default shell&amp;quot; width=&amp;quot;546&amp;quot; height=&amp;quot;341&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_kitty_के_लिए_विशिष्ट_विधि&amp;quot;&amp;gt;Kitty के लिए विशिष्ट विधि&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यदि आप केवल किट्टी में शेल बदलना पसंद करते हैं, तो कॉन्फ़िगरेशन फ़ाइल को संपादित करें:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;nano ~/.config/kitty/kitty.conf&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस पंक्ति जोड़ें:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;shell zsh&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सहेजें और किट्टी को पुनः प्रारंभ करें।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_zsh_की_कॉन्फ़िगरेशन_वैकल्पिक&amp;quot;&amp;gt;Zsh की कॉन्फ़िगरेशन (वैकल्पिक)&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपने Zsh को अनुकूलित करने के लिए:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_एक_zshrc_फ़ाइल_बनाएँ&amp;quot;&amp;gt;एक .zshrc फ़ाइल बनाएँ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;touch ~/.zshrc
nano ~/.zshrc&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_exemple_de_configuration_minimale&amp;quot;&amp;gt;Exemple de configuration minimale&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;export ZSH_THEME=&amp;quot;robbyrussell&amp;quot;
export PATH=&amp;quot;$HOME/.local/bin:$PATH&amp;quot;
alias ll=&amp;quot;ls -la&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_वर्कफ़्लो_का_पूर्ण_सारांश&amp;quot;&amp;gt;वर्कफ़्लो का पूर्ण सारांश&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;नीचे दिया गया चित्र पूरे प्रक्रिया का सारांश प्रस्तुत करता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/full-workflow.png&amp;quot; alt=&amp;quot;full workflow&amp;quot; width=&amp;quot;333&amp;quot; height=&amp;quot;643&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_अंतिम_सत्यापन&amp;quot;&amp;gt;अंतिम सत्यापन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Kitty लॉन्च करें:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;kitty&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आपको वह देखना चाहिए`zsh`सक्रिय है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;echo $SHELL&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपेक्षित परिणाम:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;/usr/bin/zsh&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फ़ॉन्ट का आकार बदलने के लिए&amp;lt;strong&amp;gt;Kitty&amp;lt;/strong&amp;gt;, पैरामीटर को समायोजित करना होगा`font_size`कॉन्फ़िगरेशन फ़ाइल में. यहाँ विस्तृत प्रक्रिया है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_कॉन्फ़िगरेशन_फ़ाइल_खोलें&amp;quot;&amp;gt;📂 कॉन्फ़िगरेशन फ़ाइल खोलें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मुख्य कॉन्फ़िगरेशन फ़ाइल आमतौर पर स्थित होती है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;~/.config/kitty/kitty.conf&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यदि यह फ़ाइल अभी तक मौजूद नहीं है, तो आप इसे बना सकते हैं। उदाहरण:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;nano ~/.config/kitty/kitty.conf&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_️_जोड़ें_या_संपादित_करें_font_size&amp;quot;&amp;gt;🖋️ जोड़ें या संपादित करें `font_size&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;निम्नलिखित निर्देश जोड़ें, यदि यह पहले से मौजूद हो तो इसे संशोधित करें:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;font_size 14.0&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ`14.0`इच्छित आकार के अनुरूप है। आप कोई भी दशमलव मान डाल सकते हैं, उदाहरण के लिए`12.0`, &amp;lt;code&amp;gt;15.5&amp;lt;/code&amp;gt;, etc.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_kitty_को_सहेजें_और_पुनः_प्रारंभ_करें&amp;quot;&amp;gt;�💾 Kitty को सहेजें और पुनः प्रारंभ करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;सहेजें (&amp;lt;code&amp;gt;Ctrl + O&amp;lt;/code&amp;gt;, फिर`Entrée`) और बंद करें (&amp;lt;code&amp;gt;Ctrl + X&amp;lt;/code&amp;gt;) यदि आप उपयोग करते हैं`nano`.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;किट्टी की सभी विंडो बंद करें, फिर टर्मिनल को रीलॉन्च करें ताकि परिवर्तन प्रभावी हो सके।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_गतिशील_समायोजन_अस्थायी_ज़ूम&amp;quot;&amp;gt;✅ गतिशील समायोजन (अस्थायी ज़ूम)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यदि आप अस्थायी रूप से ज़ूम इन/आउट करना चाहते हैं बिना कॉन्फ़िगरेशन को संशोधित किए, डिफ़ॉल्ट कीबोर्ड शॉर्टकट्स का उपयोग करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;फ़ॉन्ट का आकार बढ़ाएँ&amp;lt;/strong&amp;gt;:&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;Ctrl + Shift + =&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;फ़ॉन्ट का आकार कम करें&amp;lt;/strong&amp;gt;:&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;Ctrl + Shift + -&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;आकार रीसेट करें&amp;lt;/strong&amp;gt;:&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;Ctrl + Shift + Backspace&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इन सेटिंग्स टर्मिनल बंद होने के बाद बनी नहीं रहती।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_oh_my_zsh_की_स्थापना_और_कॉन्फ़िगरेशन&amp;quot;&amp;gt;Oh My Zsh की स्थापना और कॉन्फ़िगरेशन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक बार जब Zsh स्थापित और डिफ़ॉल्ट शेल के रूप में कॉन्फ़िगर हो जाए, तो आप &amp;lt;strong&amp;gt;Oh My Zsh&amp;lt;/strong&amp;gt; के साथ अपने वातावरण को समृद्ध कर सकते हैं, जो Zsh कॉन्फ़िगरेशन प्रबंधन का एक फ्रेमवर्क है, जो प्रदान करता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;प्रॉम्प्ट के लिए विषयों का एक संग्रह,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;बहुत से प्लगइन,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कॉन्फ़िगरेशन की स्पष्ट व्यवस्था&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_oh_my_zsh_का_इंस्टॉलेशन&amp;quot;&amp;gt;Oh My Zsh का इंस्टॉलेशन&amp;lt;/h3&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_jbake_cli_commands_initialize_a_new_jbake_project_jbake_i&amp;quot;&amp;gt;JBake CLI Commands &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; # Initialize a new JBake project jbake -i&amp;lt;/h3&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;h1 id=&amp;quot;_bake_generate_the_site_jbake_b&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake (generate) the site jbake -b&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_and_serve_locally_jbake_b_s&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake and serve locally jbake -b -s&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_and_watch_for_changes_jbake_b_reset&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake and watch for changes jbake -b --reset&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_specify_source_and_destination_jbake_source_folder_output_folder&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Specify source and destination jbake source_folder output_folder&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_clear_the_output_directory_before_baking_jbake_b_output_reset&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Clear the output directory before baking jbake -b . output --reset &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt;&amp;lt;/h1&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;ज़ैश सक्रिय है सुनिश्चित करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;zsh --version&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यदि आवश्यक हो, तो लॉन्च करें&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;zsh&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फिर आधिकारिक इंस्टॉलेशन स्क्रिप्ट डाउनलोड करें और चलाएँ:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;sh -c &amp;quot;$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह स्क्रिप्ट :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;फ़ोल्डर बनाओ`~/.oh-my-zsh`,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आप संभवतः अपनी फ़ाइल को सेव कर सकते हैं`~/.zshrc`,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;नए प्रॉम्प्ट को स्वचालित रूप से सक्रिय करता है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_थीम_बदलें&amp;quot;&amp;gt;थीम बदलें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपने कॉन्फ़िगरेशन फ़ाइल खोलें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;nano ~/.zshrc&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Variable को संशोधित करें`ZSH_THEME`अन्य विषय चुनने के लिए (उदाहरण के लिए`agnoster`) :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;ZSH_THEME=&amp;quot;agnoster&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सहेजें और फिर कॉन्फ़िगरेशन को फिर से लोड करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;source ~/.zshrc&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सत्यापन&amp;quot;&amp;gt;सत्यापन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Kitty लॉन्च करें और जाँचें कि प्रॉम्प्ट ठीक से बदल गया है। आप Oh My Zsh के सक्रिय होने की पुष्टि निम्न कमांड चलाकर कर सकते हैं :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;echo $ZSH&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;परिणाम समान होना चाहिए:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;/home/आपका_उपयोगकर्ता/.oh-my-zsh&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_यूज़_केस_डायग्राम&amp;quot;&amp;gt;यूज़ केस डायग्राम&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/ohmyzsh-installation.png&amp;quot; alt=&amp;quot;ohmyzsh installation&amp;quot; width=&amp;quot;500&amp;quot; height=&amp;quot;480&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_kitty_में_पारदर्शिता_सक्षम_करें&amp;quot;&amp;gt;Kitty में पारदर्शिता सक्षम करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Kitty की सबसे सराहनीय सुविधाओं में से एक टर्मिनल के पृष्ठभूमि में &amp;lt;strong&amp;gt;पारदर्शिता&amp;lt;/strong&amp;gt; जोड़ने की क्षमता है। यह आपको अंतर्निहित वातावरण (खिड़की, डेस्कटॉप, आदि) को हल्के से देखने की अनुमति देता है, जो मल्टीटास्किंग में विशेष रूप से उपयोगी है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_पारदर्शिता_के_लिए_पूर्वापेक्षा&amp;quot;&amp;gt;पारदर्शिता के लिए पूर्वापेक्षा&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Kitty में पारदर्शिता पर आधारित है&amp;lt;strong&amp;gt;विंडो कंपोज़र&amp;lt;/strong&amp;gt;ग्राफिकल वातावरण द्वारा उपयोग किया गया। XFCE आधारित Xubuntu पर, सुनिश्चित करें कि वह&amp;lt;strong&amp;gt;संरचना सक्रिय है&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;जाँच करें :&amp;lt;/div&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;डेस्कटॉप पर राइट‑क्लिक &amp;amp;gt; सेटिंग्स &amp;amp;gt;&amp;lt;strong&amp;gt;विंडो प्रबंधक सेटिंग्स&amp;lt;/strong&amp;gt;,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;टैब&amp;lt;strong&amp;gt;संगीतकार&amp;lt;/strong&amp;gt;: बॉक्स &amp;lt;strong&amp;gt;&amp;quot;संयोजन सक्षम करें&amp;lt;/strong&amp;gt;&amp;quot; चेक किया जाना चाहिए।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/transparency-usecase.png&amp;quot; alt=&amp;quot;transparency usecase&amp;quot; width=&amp;quot;640&amp;quot; height=&amp;quot;235&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_kitty_conf_में_पारदर्शिता_की_कॉन्फ़िगरेशन&amp;quot;&amp;gt;kitty.conf में पारदर्शिता की कॉन्फ़िगरेशन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपनी कॉन्फ़िगरेशन फ़ाइल खोलें`~/.config/kitty/kitty.conf`:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;nano ~/.config/kitty/kitty.conf&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;निम्नलिखित पंक्तियों को जोड़ें या संशोधित करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-conf hljs&amp;quot; data-lang=&amp;quot;conf&amp;quot;&amp;gt;background_opacity 0.85&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह पैरामीटर मानों के बीच स्वीकार करता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;1.0&amp;lt;/code&amp;gt;→ अपरदर्शी (कोई पारदर्शिता नहीं),&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;0.0&amp;lt;/code&amp;gt;→ पूरी तरह से पारदर्शी (उपयोग नहीं किया जा सकता)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;मध्यवर्ती मान जैसे`0.90`, &amp;lt;code&amp;gt;0.75&amp;lt;/code&amp;gt;, etc.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक अच्छा दृश्य समझौता आमतौर पर बीच में होता है`0.85` et &amp;lt;code&amp;gt;0.95&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_किटी_को_रीस्टार्ट_करें&amp;quot;&amp;gt;किटी को रीस्टार्ट करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;किट्टी के सभी उदाहरण बंद करें, फिर एक नई विंडो लॉन्च करें ताकि परिवर्तन प्रभावी हो सकें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;kitty&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_संभावित_पूरक&amp;quot;&amp;gt;संभावित पूरक&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यदि आप एक कस्टम टर्मिनल पृष्ठभूमि का उपयोग करते हैं, तो आप एक पारदर्शी पृष्ठभूमि रंग (RGBA में) भी सेट कर सकते हैं :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-conf hljs&amp;quot; data-lang=&amp;quot;conf&amp;quot;&amp;gt;background #1e1e2eff&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अंतिम घटक(&amp;lt;code&amp;gt;ff&amp;lt;/code&amp;gt;) अपारदर्शिता दर्शाता है (de`00` à &amp;lt;code&amp;gt;ff&amp;lt;/code&amp;gt;).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सीक्वेंस_डायग्राम_पारदर्शिता_के_साथ_किट्टी_का_प्रारंभ&amp;quot;&amp;gt;सीक्वेंस डायग्राम - पारदर्शिता के साथ किट्टी का प्रारंभ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/transparency-sequence.png&amp;quot; alt=&amp;quot;transparency sequence&amp;quot; width=&amp;quot;752&amp;quot; height=&amp;quot;422&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ज्ञात_सीमाएँ&amp;quot;&amp;gt;ज्ञात सीमाएँ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock warning&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-warning&amp;quot; title=&amp;quot;Warning&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पारदर्शिता काम नहीं करती यदि: - XFCE कंपोज़र निष्क्रिय है, - असंगत विंडो प्रबंधक उपयोग किया जा रहा है, - आप Kitty का उपयोग कर रहे हैं बैकग्राउंड में एक &amp;lt;strong&amp;gt;tmux&amp;lt;/strong&amp;gt; मोड में, पारदर्शिता समर्थन के बिना।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_ध्वनि_बीप_सुनाई_देने_वाली_घंटी_को_बंद_करें&amp;quot;&amp;gt;ध्वनि बीप (सुनाई देने वाली घंटी) को बंद करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;डिफ़ॉल्ट रूप से, Kitty गलत कमांड दर्ज किए जाने या टर्मिनल घटना द्वारा ट्रिगर होने पर &amp;lt;strong&amp;gt;bip&amp;lt;/strong&amp;gt; ध्वनि उत्पन्न करता है। यह शोर तेजी से परेशान करने वाला हो सकता है, विशेषकर एक गहन विकास पर्यावरण में।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस व्यवहार को अक्षम करने के लिए, फ़ाइल में निम्नलिखित निर्देश जोड़ें।&amp;lt;code&amp;gt;~/.config/kitty/kitty.conf&amp;lt;/code&amp;gt;:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-conf hljs&amp;quot; data-lang=&amp;quot;conf&amp;quot;&amp;gt;audible_bell no&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;Note&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आप &amp;lt;strong&amp;gt;दृश्य प्रतिक्रिया&amp;lt;/strong&amp;gt; को भी ध्वनि बीप के बजाय सक्रिय कर सकते हैं:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-conf hljs&amp;quot; data-lang=&amp;quot;conf&amp;quot;&amp;gt;visual_bell yes&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_किट्टी_का_अपडेट&amp;quot;&amp;gt;किट्टी का अपडेट&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;क्योंकि Kitty को एक स्क्रिप्ट के माध्यम से स्थापित किया गया है और किसी पैकेज प्रबंधक के माध्यम से नहीं, अपडेट को आधिकारिक इंस्टॉलेशन स्क्रिप्ट को फिर से चलाकर किया जाता है। इससे आपको नवीनतम संस्करण डाउनलोड करने और अपनी मौजूदा स्थापना को अपडेट करने की अनुमति मिलती है में`~/.local/kitty.app`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;Note&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;प्रत्यय`.app`पथ में`~/.local/kitty.app`यह लिनक्स पर किट्टी की आधिकारिक स्क्रिप्ट के माध्यम से स्थापना की प्रथा है, और यह किसी भी तरह से मैकओएस के साथ विशेष संगतता को दर्शाता नहीं है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock important&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-important&amp;quot; title=&amp;quot;Important&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपडेट कमांड चलाने से पहले, सुनिश्चित करें कि आप अपने होम निर्देशिका में हैं (&amp;lt;code&amp;gt;~&amp;lt;/code&amp;gt;).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपने होम निर्देशिका से निम्नलिखित कमांड चलाएँ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;curl -L https://sw.kovidgoyal.net/kitty/installer.sh | sh /dev/stdin&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह स्क्रिप्ट संभालेगा :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;नए संस्करण के बाइनरी डाउनलोड करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Extraire les fichiers dans &amp;lt;code&amp;gt;~/.local/kitty.app&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;यदि आवश्यक हो तो सिम्बॉलिक लिंक को अपडेट करें।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अद्यतन के बाद, सभी किट्टी इंस्टेंस को बंद करने और उन्हें फिर से शुरू करने की सिफारिश की जाती है ताकि यह सुनिश्चित किया जा सके कि नया संस्करण सही ढंग से लागू हो।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_संदर्भ&amp;quot;&amp;gt;संदर्भ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यदि आप वैयक्तिकरण को गहरा करना चाहते हैं, तो आधिकारिक दस्तावेज़ देखें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;किट्टी : &amp;lt;a href=&amp;quot;https://sw.kovidgoyal.net/kitty/&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://sw.kovidgoyal.net/kitty/&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://sw.kovidgoyal.net/kitty/conf/#opt-kitty.background_opacity&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://sw.kovidgoyal.net/kitty/conf/#opt-kitty.background_opacity&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://sw.kovidgoyal.net/kitty/conf/#opt-kitty.audible_bell&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://sw.kovidgoyal.net/kitty/conf/#opt-kitty.audible_bell&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Zsh: &amp;lt;a href=&amp;quot;https://zsh.sourceforge.io/&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://zsh.sourceforge.io/&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;गिटहब: &amp;lt;a href=&amp;quot;https://github.com/kovidgoyal/kitty&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://github.com/kovidgoyal/kitty&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Zsh: &amp;lt;a href=&amp;quot;https://zsh.sourceforge.io/&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://zsh.sourceforge.io/&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://ohmyz.sh/&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://ohmyz.sh/&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/ohmyzsh/ohmyzsh/wiki&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://github.com/ohmyzsh/ohmyzsh/wiki&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://docs.xfce.org/xfce/xfwm4/compositor&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://docs.xfce.org/xfce/xfwm4/compositor&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अब आपके पास :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एक आधुनिक और उच्च प्रदर्शन वाला टर्मिनल (Kitty)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एक शक्तिशाली और अनुकूलन योग्य शेल (Zsh) का&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एक स्वच्छ कॉन्फ़िगरेशन जो सिस्टम पैकेज से स्वतंत्र है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एक सुंदर और कार्यात्मक टर्मिनल जो Oh My Zsh से सुसज्जित है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>DGX Spark vs Cloud vs Abonnements LLM — Le Benchmark Économique Qui Tue le Rêve du Hardware Local</title>
            <link >https://cheroliv.com/blog/2026/0119_benchmark_dgx_spark_vs_cloud_abonnement_llm_post.html</link>
            <pubDate>Wed, 6 May 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0119_benchmark_dgx_spark_vs_cloud_abonnement_llm_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_contexte_un_marché_qui_a_basculé&amp;quot;&amp;gt;Le Contexte : Un Marché Qui a Basculé&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_panel_des_options&amp;quot;&amp;gt;Le Panel des Options&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ce_que_jai_exclu_et_pourquoi&amp;quot;&amp;gt;Ce Que J&amp;amp;#8217;ai Exclu (et Pourquoi)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_inférence_simple_la_mort_du_hardware_local&amp;quot;&amp;gt;Inférence Simple : La Mort du Hardware Local&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_calcul&amp;quot;&amp;gt;Le Calcul&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_même_avec_un_usage_intensif&amp;quot;&amp;gt;Même avec un Usage Intensif&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_fine_tuning_le_cloud_est_imbattable&amp;quot;&amp;gt;Fine-Tuning : Le Cloud Est Imbattable&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_coût_réel_dun_fine_tune&amp;quot;&amp;gt;Le Coût Réel d&amp;amp;#8217;un Fine-Tune&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_les_acteurs_spécialisés&amp;quot;&amp;gt;Les Acteurs Spécialisés&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_seule_vraie_raison_la_souveraineté_des_données&amp;quot;&amp;gt;La Seule Vraie Raison : La Souveraineté des Données&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_vrai_calcul_de_la_confidentialité&amp;quot;&amp;gt;Le Vrai Calcul de la Confidentialité&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_synthèse_la_matrice_de_décision&amp;quot;&amp;gt;Synthèse : La Matrice de Décision&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_cas_particulier_labonnement_pro_face_aux_modèles_chinois&amp;quot;&amp;gt;Le Cas Particulier : L&amp;amp;#8217;Abonnement Pro Face aux Modèles Chinois&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pourquoi_les_modèles_chinois_changent_tout&amp;quot;&amp;gt;Pourquoi les Modèles Chinois Changent Tout&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ce_que_ça_veut_dire_pour_le_hardware&amp;quot;&amp;gt;Ce Que Ça Veut Dire pour le Hardware&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_et_huawei&amp;quot;&amp;gt;Et Huawei ?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_conclusion_le_luxe_de_la_proximité&amp;quot;&amp;gt;Conclusion : Le Luxe de la Proximité&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 14 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;NVIDIA vend le DGX Spark comme un « supercalculateur IA de bureau » à $4 699. Ollama propose ses modèles cloud à $20/mois. Un H100 se loue $1.38/h chez Vast.ai. Et les modèles chinois open-source — DeepSeek, Qwen, GLM — sont disponibles partout, gratuitement, sans avoir à acheter une carte. Alors, ce Spark, il sert à quoi au juste ? J&amp;amp;#8217;ai fait les maths.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;toc&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;[]&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_contexte_un_marché_qui_a_basculé&amp;quot;&amp;gt;Le Contexte : Un Marché Qui a Basculé&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;En mai 2026, le paysage de l&amp;amp;#8217;IA a radicalement changé par rapport à l&amp;amp;#8217;annonce du DGX Spark au CES 2025. Trois forces ont convergé pour rendre le hardware local de plus en plus difficile à justifier :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;L&amp;amp;#8217;effondrement des prix du cloud GPU&amp;lt;/strong&amp;gt; : un H100 se loue entre $1.38 et $3/h, contre $5-8/h il y a 18 mois&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;L&amp;amp;#8217;explosion des modèles chinois open-source&amp;lt;/strong&amp;gt; : DeepSeek-V4, Qwen-3, GLM-5 sont compétitifs avec les modèles occidentaux, disponibles gratuitement&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;La montée des plateformes d&amp;amp;#8217;inférence managée&amp;lt;/strong&amp;gt; : Ollama, Groq, Together AI proposent des API à des tarifs agressifs, avec des paliers gratuits généreux&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le DGX Spark, annoncé à $2 999 puis monté à $4 699, arrive dans un monde qui n&amp;amp;#8217;a plus besoin de lui.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_panel_des_options&amp;quot;&amp;gt;Le Panel des Options&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Voici les solutions disponibles en mai 2026 pour faire tourner des LLMs, de la plus légère à la plus lourde :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.5%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Option&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Coût&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;VRAM / Capacité&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Modèles accessibles&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Contrainte principale&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Ollama Free&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;$0/mois&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Cloud léger&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Tous modèles publics&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Usage limité, 1 modèle simultané&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Claude Pro&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;$20/mois (~$240/an)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;N/A (API fermée)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Claude 4.x uniquement&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Modèle unique, pas d&amp;amp;#8217;open-source&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Ollama Pro&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;$20/mois (~$200/an)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Cloud medium&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Tous modèles publics&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;3 modèles simultanés max&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Ollama Max&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;$100/mois (~$1 200/an)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Cloud heavy&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Tous modèles publics&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;10 modèles simultanés&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Cloud GPU (H100)&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;$1.38-3/h&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;80 Go HBM&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Tous modèles, fine-tuning&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Facturation horaire, setup requis&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;DGX Spark&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;$4 699 (achat)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;128 Go unifié&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Tous modèles &amp;amp;lt;128 Go&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Lent (~10x moins qu&amp;amp;#8217;un H100), fixe&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Mac Studio M3 Ultra&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;~$5 000+&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;192 Go unifié&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Tous modèles &amp;amp;lt;192 Go&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Pas CUDA, écosystème MLX&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock tip&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-tip&amp;quot; title=&amp;quot;💡&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Les prix cloud GPU cités sont ceux de Vast.ai et RunPod en mai 2026 — du spot/on-demand, pas du réservé. Les prix des hyperscalers (AWS, GCP, Azure) restent 2-3x plus élevés.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ce_que_jai_exclu_et_pourquoi&amp;quot;&amp;gt;Ce Que J&amp;amp;#8217;ai Exclu (et Pourquoi)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ai volontairement exclu les options suivantes de ce benchmark :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;API OpenAI / Anthropic / Google&amp;lt;/strong&amp;gt; : le sujet ici est de faire tourner des modèles &amp;lt;strong&amp;gt;open-source&amp;lt;/strong&amp;gt; qu&amp;amp;#8217;on peut choisir, fine-tuner, et ne pas être dépendant d&amp;amp;#8217;un vendor unique&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Huawei Ascend / Atlas&amp;lt;/strong&amp;gt; : Huawei ne commercialise pas d&amp;amp;#8217;équivalent desktop au DGX Spark. La gamme Ascend (910C, 910D) et Atlas (300I Duo, 350) est orientée datacenter — cartes PCIe, serveurs rack — pas des boîtiers compacts prêts à brancher. La puce Ascend 910C embarque 128 Go HBM mais c&amp;amp;#8217;est une puce serveur, pas un système autonome. L&amp;amp;#8217;Atlas 300I Duo offre 96 Go pour ~$1 400 mais nécessite une machine hôte&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_inférence_simple_la_mort_du_hardware_local&amp;quot;&amp;gt;Inférence Simple : La Mort du Hardware Local&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Commençons par le cas d&amp;amp;#8217;usage le plus commun : chatter avec un LLM, faire du code review, générer du texte. Pas de fine-tuning, pas de batch processing, juste de l&amp;amp;#8217;inférence interactive.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_calcul&amp;quot;&amp;gt;Le Calcul&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un DGX Spark à $4 699. Divisons par le coût annuel de chaque abonnement :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-breakeven&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-7447dcff18600cfcdb05c5212204ea1f.svg&amp;quot; alt=&amp;quot;Seuil de rentabilité du DGX Spark vs abonnements&amp;quot; width=&amp;quot;837&amp;quot; height=&amp;quot;219&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le verdict est brutal. Pour de l&amp;amp;#8217;inférence :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Ollama Pro&amp;lt;/strong&amp;gt; : il vous faudrait &amp;lt;strong&amp;gt;23 ans&amp;lt;/strong&amp;gt; pour amortir un DGX Spark. Le Spark sera obsolète depuis 20 ans.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Ollama Max&amp;lt;/strong&amp;gt; : &amp;lt;strong&amp;gt;4 ans&amp;lt;/strong&amp;gt; — à condition d&amp;amp;#8217;utiliser le Spark 24/7, ce que personne ne fait&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Claude Pro&amp;lt;/strong&amp;gt; : même problème, &amp;lt;strong&amp;gt;20 ans&amp;lt;/strong&amp;gt; pour du single-model fermé&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&amp;lt;em&amp;gt;_ La promesse du « supercalculateur IA de bureau » se heurte à une réalité comptable élémentaire : $4 699 / $20 par mois = jamais rentable pour un usage individuel. &amp;lt;/em&amp;gt;_&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_même_avec_un_usage_intensif&amp;quot;&amp;gt;Même avec un Usage Intensif&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Prenons le pire scénario pour le cloud : vous faites tourner un H100 8h/jour, 5 jours/semaine, 52 semaines/an.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;8 × 5 × 52 = 2 080 heures/an&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;2 080 × $2/h (prix moyen spot H100) = &amp;lt;strong&amp;gt;$4 160/an&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le Spark ($4 699) est rentabilisé en &amp;lt;strong&amp;gt;13 mois&amp;lt;/strong&amp;gt;. Sauf que :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le H100 est &amp;lt;strong&amp;gt;~10x plus rapide&amp;lt;/strong&amp;gt; que le GB10 du Spark. Vous faites en 1h ce que le Spark fait en 10h. Pour le même volume de travail, le H100 vous coûte $416/an, pas $4 160.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le H100 a 80 Go HBM à 3.35 To/s de bande passante. Le Spark a 128 Go LPDDR5X à 273 Go/s. Pour les gros modèles, la bande passante compte plus que la capacité.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock important&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-important&amp;quot; title=&amp;quot;❗&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Comparer 1h de H100 à 1h de Spark n&amp;amp;#8217;a pas de sens. Le H100 fait le travail 10x plus vite. Le vrai coût cloud pour un workload donné est donc ~10x inférieur au calcul naïf basé sur les heures.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_fine_tuning_le_cloud_est_imbattable&amp;quot;&amp;gt;Fine-Tuning : Le Cloud Est Imbattable&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;argument classique des défenseurs du Spark : « oui mais pour le fine-tuning, c&amp;amp;#8217;est différent ».&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Non, ça ne l&amp;amp;#8217;est pas.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_coût_réel_dun_fine_tune&amp;quot;&amp;gt;Le Coût Réel d&amp;amp;#8217;un Fine-Tune&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un fine-tune LoRA/QLoRA sur Unsloth d&amp;amp;#8217;un modèle 7B :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;~2-3h sur un H100 = &amp;lt;strong&amp;gt;$5 à $9&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Même chose sur le Spark = &amp;lt;strong&amp;gt;20-30h&amp;lt;/strong&amp;gt; (10x plus lent), bloque la machine&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avec les $4 699 du Spark, vous pouvez financer :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;~500 à ~900 fine-tunes&amp;lt;/strong&amp;gt; en cloud H100&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Ou &amp;lt;strong&amp;gt;~23 ans&amp;lt;/strong&amp;gt; d&amp;amp;#8217;Ollama Pro&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Ou &amp;lt;strong&amp;gt;~4 ans&amp;lt;/strong&amp;gt; d&amp;amp;#8217;Ollama Max&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Et pour des modèles plus gros (70B+) :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le Spark avec ses 128 Go peut charger un 70B en Q4 — mais le fine-tune sera extrêmement lent&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Un H100 avec 80 Go peut fine-tuner un 70B en QLoRA 4-bit en quelques heures&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Pour du full fine-tune, il faut du multi-GPU de toute façon — le Spark est hors course&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_les_acteurs_spécialisés&amp;quot;&amp;gt;Les Acteurs Spécialisés&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;En 2026, des plateformes comme Unsloth, Modal, Replicate, et Together AI proposent du fine-tuning serverless :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Pas de gestion de GPU&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Pas de configuration d&amp;amp;#8217;environnement&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Paiement à la minute&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Optimisations intégrées (flash attention, quantization automatique)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-fine-tuning-cost&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-00c27fa5b17d5b1836d28ea44e7aa323.svg&amp;quot; alt=&amp;quot;Comparaison des coûts de fine-tuning&amp;quot; width=&amp;quot;626&amp;quot; height=&amp;quot;244&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_seule_vraie_raison_la_souveraineté_des_données&amp;quot;&amp;gt;La Seule Vraie Raison : La Souveraineté des Données&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Après avoir éliminé l&amp;amp;#8217;inférence, le fine-tuning, et le rapport qualité/prix — que reste-t-il au Spark ?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;La confidentialité absolue.&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pas la confidentialité « je ne veux pas que mes prompts soient lus par un employé d&amp;amp;#8217;OpenAI ». Ça, c&amp;amp;#8217;est un faux problème en 2026 : Ollama, Groq, et la plupart des providers respectables ont des politiques de zéro log et zéro rétention.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La vraie confidentialité, c&amp;amp;#8217;est :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Air-gap réglementaire&amp;lt;/strong&amp;gt; : défense, diplomatie, santé — les données ne peuvent &amp;lt;strong&amp;gt;physiquement&amp;lt;/strong&amp;gt; pas quitter le bâtiment&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Données propriétaires critiques&amp;lt;/strong&amp;gt; : code source d&amp;amp;#8217;un produit non publié, secrets industriels, algorithmes de trading&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Résilience réseau&amp;lt;/strong&amp;gt; : l&amp;amp;#8217;IA doit continuer à fonctionner même si Internet tombe&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock caution&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-caution&amp;quot; title=&amp;quot;🔒&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mais soyons honnêtes : quel pourcentage des acheteurs de DGX Spark est réellement dans ce cas ? 1% ? Le reste, c&amp;amp;#8217;est du « nice to have » transformé en dépense à $4 699.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_vrai_calcul_de_la_confidentialité&amp;quot;&amp;gt;Le Vrai Calcul de la Confidentialité&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pour un usage individuel :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Ollama Pro&amp;lt;/strong&amp;gt; ($20/mois) + modèles open source chinois = solution pragmatique&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Si un prompt fuit chez Ollama, il se noie dans les millions de requêtes quotidiennes. C&amp;amp;#8217;est la goutte d&amp;amp;#8217;eau dans l&amp;amp;#8217;océan.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le risque réel n&amp;amp;#8217;est pas la fuite d&amp;amp;#8217;un prompt — c&amp;amp;#8217;est l&amp;amp;#8217;entraînement non consenti sur vos données. Et ça, les providers sérieux l&amp;amp;#8217;interdisent contractuellement.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&amp;lt;em&amp;gt;_ La peur de « distiller son prompt dans le LLM » est un niveau de propagation d&amp;amp;#8217;information personnel tellement dilué qu&amp;amp;#8217;il relève plus de l&amp;amp;#8217;anxiété que de la menace réelle. À l&amp;amp;#8217;échelle industrielle, c&amp;amp;#8217;est différent. Mais à l&amp;amp;#8217;échelle individuelle, c&amp;amp;#8217;est du bruit. &amp;lt;/em&amp;gt;_&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_synthèse_la_matrice_de_décision&amp;quot;&amp;gt;Synthèse : La Matrice de Décision&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;diag-decision-matrix&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-06638fe7c7dbec3c1cf02043ac672e9a.svg&amp;quot; alt=&amp;quot;Matrice de décision pour choisir sa solution LLM&amp;quot; width=&amp;quot;2012&amp;quot; height=&amp;quot;433&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2222%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2232%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Critère&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Ollama Free&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Ollama Pro&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Cloud GPU H100&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;DGX Spark&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Inférence&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅ Limitée&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅ Confortable&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅ Overkill&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;⚠️ Lent&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Fine-tuning&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;❌&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;❌&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅ Imbattable&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;⚠️ Possible mais lent&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Coût annuel&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;$0&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;$200&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Variable (~$416-2 080*)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;$4 699 upfront&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Confidentialité&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;⚠️ Cloud US&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;⚠️ Cloud US&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;⚠️ Cloud US (variable)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅ Totale&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Maintenance&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Aucune&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Aucune&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Setup unique&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Électricité, mises à jour&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Obsolescence&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Aucune&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Aucune&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Aucune&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;3-5 ans&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Écosystème logiciel&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Tous modèles open&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Tous modèles open&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Tous modèles open&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;CUDA (mais lent)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Veridict&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Occasionnel&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Recommandé&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Pros/Recherche&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Air-gap uniquement&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;*Variable selon volume de travail ; avec vitesse H100 ~10x &amp;amp;gt; Spark, le coût effectif pour un workload donné est bas.&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_cas_particulier_labonnement_pro_face_aux_modèles_chinois&amp;quot;&amp;gt;Le Cas Particulier : L&amp;amp;#8217;Abonnement Pro Face aux Modèles Chinois&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un point mérite d&amp;amp;#8217;être souligné : la combinaison &amp;lt;strong&amp;gt;Ollama Pro à $20/mois + modèles chinois open-source&amp;lt;/strong&amp;gt; est probablement le meilleur rapport qualité/prix de l&amp;amp;#8217;histoire de l&amp;amp;#8217;IA grand public.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_pourquoi_les_modèles_chinois_changent_tout&amp;quot;&amp;gt;Pourquoi les Modèles Chinois Changent Tout&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;DeepSeek-V4-Pro&amp;lt;/strong&amp;gt; : 1.6T params, CSA+HCA, 1M contexte, compétitif avec Claude 4 et GPT-5 pour le code&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Qwen-3&amp;lt;/strong&amp;gt; : 235B, 256K contexte, excellent en français et en raisonnement&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;GLM-5.1&amp;lt;/strong&amp;gt; : 744B, MLA+DSA, 200K contexte, taillé pour l&amp;amp;#8217;agentique&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Tous disponibles sur Ollama. Tous open-source (licences permissives). Tous utilisables sans restriction via un abonnement à $20/mois.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock tip&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-tip&amp;quot; title=&amp;quot;💡&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avec Ollama Pro, vous avez accès à ~5 modèles « frontier » open-source pour le prix d&amp;amp;#8217;un seul modèle fermé (Claude Pro). La valeur est tellement asymétrique que ça en devient presque absurde.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ce_que_ça_veut_dire_pour_le_hardware&amp;quot;&amp;gt;Ce Que Ça Veut Dire pour le Hardware&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Si le meilleur rapport qualité/prix est un abonnement cloud à $20/mois, le hardware local devient un choix de &amp;lt;strong&amp;gt;confort&amp;lt;/strong&amp;gt; ou de &amp;lt;strong&amp;gt;principe&amp;lt;/strong&amp;gt; — pas un choix économique.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un DGX Spark à $4 699, c&amp;amp;#8217;est l&amp;amp;#8217;équivalent de :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;235 mois d&amp;amp;#8217;Ollama Pro&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;23 jeux AAA jour de sortie&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;4 MacBook Air M4&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Un an de loyer d&amp;amp;#8217;un T2 à Lyon&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pour du calcul. Lent.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_et_huawei&amp;quot;&amp;gt;Et Huawei ?&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Puisque la question m&amp;amp;#8217;a été posée pendant mes recherches : non, Huawei ne commercialise pas d&amp;amp;#8217;équivalent au DGX Spark.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce qui existe :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Ascend 910C&amp;lt;/strong&amp;gt; : 128 Go HBM, 800 TFLOPS FP16 — mais c&amp;amp;#8217;est une puce serveur, pas un desktop&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Atlas 300I Duo&amp;lt;/strong&amp;gt; : 96 Go LPDDR4X, carte PCIe à ~$1 400 — nécessite un hôte&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Atlas 350&amp;lt;/strong&amp;gt; : 112 Go HBM, 1.56 PFLOPS FP4 — accélérateur datacenter, pas un boîtier compact&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Huawei reste focalisé sur le marché des serveurs et des centres de données. Pour un boîtier compact « prêt à brancher » avec 120+ Go de VRAM, le DGX Spark (128 Go unifié) et le Mac Studio M3 Ultra (192 Go unifié) sont les seules options en 2026. Et pour l&amp;amp;#8217;instant, aucun constructeur chinois n&amp;amp;#8217;a annoncé de produit équivalent dans ce format.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_conclusion_le_luxe_de_la_proximité&amp;quot;&amp;gt;Conclusion : Le Luxe de la Proximité&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le DGX Spark n&amp;amp;#8217;est pas un mauvais produit. C&amp;amp;#8217;est un mauvais investissement pour 99% des acheteurs potentiels.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-verdict&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-e8d62f731ea78fcb4f2978a3515b59c2.svg&amp;quot; alt=&amp;quot;Verdict final — quel modèle économique domine en 2026&amp;quot; width=&amp;quot;476&amp;quot; height=&amp;quot;617&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&amp;lt;em&amp;gt;_ Acheter un DGX Spark en 2026, c&amp;amp;#8217;est comme acheter un serveur mail en 2010 : techniquement possible, philosophiquement satisfaisant, économiquement absurde pour un individu. &amp;lt;/em&amp;gt;_&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le calcul est simple, et il ne ment pas :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;$0&amp;lt;/strong&amp;gt; pour chatter avec DeepSeek sur Ollama Free&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;$200/an&amp;lt;/strong&amp;gt; pour bosser sérieusement avec Ollama Pro&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;$5-9&amp;lt;/strong&amp;gt; pour un fine-tune ponctuel sur cloud GPU&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;$4 699&amp;lt;/strong&amp;gt; pour&amp;amp;#8230;&amp;amp;#8203; l&amp;amp;#8217;expérience d&amp;amp;#8217;avoir un boîtier NVIDIA sur son bureau ?&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le marché a tranché. Les abonnements cloud et les modèles open-source chinois ont gagné la bataille du prix. Le hardware local survit dans les niches réglementaires, pas dans les bureaux des développeurs.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&amp;lt;em&amp;gt;_ Le DGX Spark n&amp;amp;#8217;est pas un outil rentable. C&amp;amp;#8217;est un statement. « Je veux mon IA chez moi, pas dans le cloud de quelqu&amp;amp;#8217;un d&amp;amp;#8217;autre. » C&amp;amp;#8217;est respectable. Mais en 2026, quand Ollama te donne DeepSeek-V4-Pro dans le cloud pour $20/mois, c&amp;amp;#8217;est surtout un statement qui coûte très cher. &amp;lt;/em&amp;gt;_&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Cet article est issu d&amp;amp;#8217;une conversation avec mon agent IA sur la pertinence économique du DGX Spark, croisée avec une veille marché sur les prix cloud GPU (Vast.ai, RunPod), les grilles tarifaires Ollama/Claude, et l&amp;amp;#8217;écosystème des modèles chinois open-source. Les prix cités sont ceux de mai 2026 — ils auront probablement encore baissé quand vous lirez ces lignes.&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>La Matrice de Gouvernance LLM — Pourquoi la Sécurité de Votre IA Commence par l&#39;Arborescence</title>
            <link >https://cheroliv.com/blog/2026/0118_matrice_gouvernance_llm_zone_acces_workspace_post.html</link>
            <pubDate>Mon, 4 May 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0118_matrice_gouvernance_llm_zone_acces_workspace_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_problème_le_prompt_engineering_est_un_château_de_sable&amp;quot;&amp;gt;Le Problème : le Prompt Engineering est un Château de Sable&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ma_réponse_la_matrice_44&amp;quot;&amp;gt;Ma Réponse : la Matrice 4×4&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_les_cinq_zones_dimension_spatiale_rgpd&amp;quot;&amp;gt;Les Cinq Zones (Dimension Spatiale — RGPD)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_classification_épistémique_deuxième_dimension&amp;quot;&amp;gt;La Classification Épistémique (Deuxième Dimension)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_comment_le_llm_consomme_cette_matrice&amp;quot;&amp;gt;Comment le LLM Consomme Cette Matrice&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_implémentation_tâches_gradle_typées&amp;quot;&amp;gt;Implémentation : Tâches Gradle Typées&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pourquoi_cest_un_manifeste_pas_juste_une_spec&amp;quot;&amp;gt;Pourquoi C&amp;amp;#8217;est un Manifeste, Pas Juste une Spec&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_cascade_complète_du_brain_dump_à_larticle_de_blog&amp;quot;&amp;gt;La Cascade Complète — du Brain Dump à l&amp;amp;#8217;Article de Blog&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_procontra&amp;quot;&amp;gt;Pro/Contra&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_conclusion_rangez_vos_fichiers_pas_vos_prompts&amp;quot;&amp;gt;Conclusion : Rangez vos Fichiers, Pas vos Prompts&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_références&amp;quot;&amp;gt;Références&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 14 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Pendant des mois, j&amp;amp;#8217;ai empilé les règles de gouvernance agent. Des fichiers EAGER, des checklists LAZY, des protocoles de fin de session en six étapes. Et pourtant, une question restait en suspens : &amp;lt;strong&amp;gt;comment le LLM sait-il ce qu&amp;amp;#8217;il a le droit de faire avec un fichier ?&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La réponse n&amp;amp;#8217;est pas dans un prompt. Elle est dans le système de fichiers.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Voici la spécification d&amp;amp;#8217;architecture qui rend la réponse exploitable — la &amp;lt;strong&amp;gt;matrice de gouvernance LLM&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_problème_le_prompt_engineering_est_un_château_de_sable&amp;quot;&amp;gt;Le Problème : le Prompt Engineering est un Château de Sable&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Quand on donne un fichier à un LLM, on lui donne tout. Le contenu, oui — mais aussi l&amp;amp;#8217;absence de garde-fous. Le LLM ne sait pas si ce fichier contient un secret, une opinion spéculative, ou du code closed source. Il va l&amp;amp;#8217;indexer, le résumer, le citer, le mélanger avec d&amp;amp;#8217;autres données — et potentiellement le publier dans un embedding public ou une réponse utilisateur.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La parade classique, c&amp;amp;#8217;est le prompt :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;&amp;quot;Tu es un assistant sécurisé. Ne divulgue jamais d&amp;#39;informations confidentielles.
Si tu détectes un secret, ignore-le. Si tu détectes une opinion, ne la répète pas.&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce prompt a trois problèmes :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Il repose sur la bonne volonté du LLM.&amp;lt;/strong&amp;gt; Un modèle assez grand pour&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;résoudre des bugs complexes est assez grand pour contourner une instruction de sécurité noyée dans 200k tokens de contexte.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Il est contextuel, pas structurel.&amp;lt;/strong&amp;gt; Changez de prompt, changez de LLM,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;changez de session — et la règle disparaît.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Il ne scale pas.&amp;lt;/strong&amp;gt; Chaque nouveau type de fichier, chaque nouveau niveau&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;de confidentialité exige une nouvelle clause. Votre prompt devient un texte réglementaire que personne ne lit en entier.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock caution&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-caution&amp;quot; title=&amp;quot;🔒&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La sécurité d&amp;amp;#8217;un système ne doit jamais dépendre d&amp;amp;#8217;une instruction qu&amp;amp;#8217;on peut oublier, contourner, ou ne pas charger. Elle doit dépendre d&amp;amp;#8217;une barrière qu&amp;amp;#8217;on ne peut pas franchir sans le vouloir explicitement.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_ma_réponse_la_matrice_44&amp;quot;&amp;gt;Ma Réponse : la Matrice 4×4&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La solution que j&amp;amp;#8217;ai implémentée dans mon workspace est une &amp;lt;strong&amp;gt;matrice zone × droit d&amp;amp;#8217;accès LLM&amp;lt;/strong&amp;gt;. Elle ne demande pas au LLM d&amp;amp;#8217;être prudent. Elle rend l&amp;amp;#8217;imprudence structurellement impossible.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-matrix-overview&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-ff423528a76bb0bbfad06b9abbd23331.svg&amp;quot; alt=&amp;quot;Vue d&amp;amp;#8217;ensemble de la matrice de gouvernance LLM — 5 zones × 4 droits d&amp;amp;#8217;accès&amp;quot; width=&amp;quot;469&amp;quot; height=&amp;quot;800&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_les_cinq_zones_dimension_spatiale_rgpd&amp;quot;&amp;gt;Les Cinq Zones (Dimension Spatiale — RGPD)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Chaque zone du workspace a un niveau RGPD qui détermine &amp;lt;strong&amp;gt;où&amp;lt;/strong&amp;gt; le fichier peut être routé :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 4.1682%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Zone&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Niveau RGPD&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Contenu&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Droit d&amp;amp;#8217;accès RAG public&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Racine&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;0 — Intime&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Brain dumps, conversations LLM&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;INTERDIT&amp;lt;/strong&amp;gt; — jamais indexé&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;configuration/&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;1 — Restreint propriétaire&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Secrets, tokens, clés API&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;INTERDIT&amp;lt;/strong&amp;gt; — jamais indexé&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;2 — Restreint collaboratif&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Data éditoriale, cadrage, formations&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;FILTRÉ&amp;lt;/strong&amp;gt; — Vision uniquement&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;foundry/private/&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;3 — Ouvert conditionnel&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Code closed source, SaaS non public&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;INTERDIT&amp;lt;/strong&amp;gt; — dataset privé exclusivement&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;foundry/public/&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;4 — Public natif&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Code Apache 2.0, plugins publiés&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;LIBRE&amp;lt;/strong&amp;gt; — indexation complète&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La règle est simple : &amp;lt;strong&amp;gt;le chemin du fichier détermine ce que le LLM peut en faire.&amp;lt;/strong&amp;gt; Pas de métadonnées à maintenir, pas de tag à ajouter dans le frontmatter, pas de classification manuelle à chaque commit. Le fichier est dans &amp;lt;code&amp;gt;OSS/&amp;lt;/code&amp;gt; ? Il est public. Il est dans &amp;lt;code&amp;gt;configuration/&amp;lt;/code&amp;gt; ? Il est intouchable.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_la_classification_épistémique_deuxième_dimension&amp;quot;&amp;gt;La Classification Épistémique (Deuxième Dimension)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La dimension spatiale dit &amp;lt;strong&amp;gt;où&amp;lt;/strong&amp;gt; router. Mais il y a un deuxième axe, perpendiculaire : &amp;lt;strong&amp;gt;quoi&amp;lt;/strong&amp;gt; router. Certains fichiers dans une zone autorisée contiennent des informations qui ne devraient pas être diluées telles quelles :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-epistemic-filter&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-768538851f5f36f6e05c445dd02dc3ed.svg&amp;quot; alt=&amp;quot;Filtre épistémique Vision/Opinion/Stratégie appliqué aux zones 2 et 3&amp;quot; width=&amp;quot;1215&amp;quot; height=&amp;quot;558&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La grille de classification épistémique, gravée en Règle 2bis de ma gouvernance agent :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;| Statut | Définition | Signal LLM | Destination | | VISION | Architecture stabilisée, pattern testé | Langage déclaratif, références sessions/tests | Dilution complète + Blog | | STRATÉGIE | Positionnement business, pricing | Vocabulaire marché, concurrence | Docs racine uniquement | | OPINION | Spéculation, hypothèse non validée | Langage hypothétique, intuition | Confinement Cercle 0 |&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La combinaison des deux dimensions — zone physique × classification épistémique — forme la &amp;lt;strong&amp;gt;matrice complète&amp;lt;/strong&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-full-matrix&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-f6f9959b0f07e3bff0bf64c8e1c20ea4.svg&amp;quot; alt=&amp;quot;La matrice complète : 5 zones × 3 classifications épistémiques&amp;quot; width=&amp;quot;442&amp;quot; height=&amp;quot;132&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_comment_le_llm_consomme_cette_matrice&amp;quot;&amp;gt;Comment le LLM Consomme Cette Matrice&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La matrice n&amp;amp;#8217;est pas un document que le LLM lit. C&amp;amp;#8217;est une &amp;lt;strong&amp;gt;contrainte implicite&amp;lt;/strong&amp;gt; encodée dans le vecteur composite de contexte (EPIC 9 — en cours d&amp;amp;#8217;implémentation).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Voici ce que le LLM reçoit à chaque session :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;VECTEUR COMPOSITE DE CONTEXTE
├── RAG pgvector → OSS/ + office/Vision
│   (similarité sémantique sur contenu publiable)
├── Knowledge Graph graphify → OSS/
│   (relations exactes entre artéfacts publics)
├── Knowledge Graph privé → CSS/
│   (relations entre code closed source — jamais exporté)
├── Métadonnées de zone → chaque fichier taggé par zone physique
│   (le LLM sait s&amp;#39;il est dans office/ ou OSS/)
└── Historique des décisions → WORKSPACE_VISION.adoc
    (contexte temporel des arbitrages)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Concrètement, quand le LLM me dit :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;Je vais indexer le contenu de edster/ pour enrichir le knowledge graph...&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La métadonnée de zone répond avant même que le LLM ne finisse sa phrase : &amp;lt;code&amp;gt;edster/&amp;lt;/code&amp;gt; est dans &amp;lt;code&amp;gt;CSS/&amp;lt;/code&amp;gt;, niveau 3 → &amp;lt;strong&amp;gt;accès interdit au knowledge graph public.&amp;lt;/strong&amp;gt; Le RAG ne le voit pas. Le graphe ne le touche pas. La réponse utilisateur ne le cite pas.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock tip&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-tip&amp;quot; title=&amp;quot;💡&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;ontologie spatiale fonctionne comme une &amp;lt;strong&amp;gt;permission Unix&amp;lt;/strong&amp;gt; pour les LLM. Vous ne demandez pas à un processus d&amp;amp;#8217;être prudent avec &amp;lt;code&amp;gt;/etc/shadow&amp;lt;/code&amp;gt; — vous lui refusez l&amp;amp;#8217;accès en lecture. Même principe.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_implémentation_tâches_gradle_typées&amp;quot;&amp;gt;Implémentation : Tâches Gradle Typées&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La matrice n&amp;amp;#8217;est pas une philosophie. C&amp;amp;#8217;est du code. Voici le contrat de tâche Gradle qui l&amp;amp;#8217;implémente :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;abstract class ZoneAwareIndexer @Inject constructor(
    private val rootDir: DirectoryProperty,
    private val configServer: ConfigServerProperty  // → configuration/
) : DefaultTask() {

    @Input
    val zoneFilter: SetProperty&amp;amp;lt;Zone&amp;amp;gt; = project.objects.setProperty(Zone::class.java)

    @OutputFile
    val ragIndex: RegularFileProperty = project.objects.fileProperty()

    @TaskAction
    fun index() {
        val allowedPaths = zoneFilter.get().flatMap { it.resolve(rootDir.get()) }
        val forbiddenPaths = Zone.RESTRICTED.resolve(rootDir.get())
                            + Zone.INTIMATE.resolve(rootDir.get())
        // Le RAG ne voit jamais configuration/ ni la racine
        // CSS/ alimente un index privé, pas celui-ci
        // office/ est filtré par le classifieur Vision/Opinion
    }
}

enum class Zone {
    INTIMATE,      // Cercle 0 — racine
    RESTRICTED,    // Cercle 1 — configuration/
    EDITORIAL,     // Cercle 2 — office/
    CLOSED_SOURCE, // Cercle 3 — foundry/private/
    OPEN_SOURCE    // Cercle 3 — foundry/public/
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La tâche est &amp;lt;strong&amp;gt;testable&amp;lt;/strong&amp;gt;. Vous pouvez écrire un test qui vérifie :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;@Test
fun `le RAG n&amp;#39;indexe jamais configuration`() {
    val index = ZoneAwareIndexer(rootDir, configServer)
    index.zoneFilter.set(setOf(Zone.OPEN_SOURCE, Zone.EDITORIAL))
    index.index()

    assertThat(index.ragIndex).doesNotContain(&amp;quot;configuration/&amp;quot;)
}

@Test
fun `le code closed source est exclu du RAG public`() {
    val index = ZoneAwareIndexer(rootDir, configServer)
    index.zoneFilter.set(setOf(Zone.OPEN_SOURCE))  // OSS only

    assertThat(index.ragIndex).doesNotContain(&amp;quot;edster&amp;quot;)
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;380 tests, 380 PASS. Comme pour plantuml-gradle — la sécurité est testée, pas espérée.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_pourquoi_cest_un_manifeste_pas_juste_une_spec&amp;quot;&amp;gt;Pourquoi C&amp;amp;#8217;est un Manifeste, Pas Juste une Spec&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce document est une spécification d&amp;amp;#8217;architecture parce qu&amp;amp;#8217;il définit :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Des &amp;lt;strong&amp;gt;dimensions&amp;lt;/strong&amp;gt; (spatiale, épistémique)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Des &amp;lt;strong&amp;gt;règles déterministes&amp;lt;/strong&amp;gt; (zone → droit d&amp;amp;#8217;accès)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Un &amp;lt;strong&amp;gt;contrat de tâche&amp;lt;/strong&amp;gt; (Gradle typé, testable)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Une &amp;lt;strong&amp;gt;implémentation de référence&amp;lt;/strong&amp;gt; (mon workspace)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mais c&amp;amp;#8217;est aussi un &amp;lt;strong&amp;gt;manifeste&amp;lt;/strong&amp;gt; parce qu&amp;amp;#8217;il prend position sur un débat plus large : &amp;lt;strong&amp;gt;comment gouverner l&amp;amp;#8217;accès d&amp;amp;#8217;un LLM à des données ?&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La réponse de l&amp;amp;#8217;industrie, c&amp;amp;#8217;est le prompt engineering + les guardrails&amp;lt;br&amp;gt;
les classifiers post-hoc. Ma réponse, c&amp;amp;#8217;est : &amp;lt;strong&amp;gt;rangez vos fichiers dans les bons dossiers.&amp;lt;/strong&amp;gt; Le reste est automatique.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock important&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-important&amp;quot; title=&amp;quot;❗&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce manifeste ne dit pas &amp;quot;les LLM doivent être alignés&amp;quot;. Il dit : &amp;quot;l&amp;amp;#8217;alignement d&amp;amp;#8217;un LLM sur vos règles de sécurité est une conséquence de votre système de fichiers, pas de votre prompt.&amp;quot;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_cascade_complète_du_brain_dump_à_larticle_de_blog&amp;quot;&amp;gt;La Cascade Complète — du Brain Dump à l&amp;amp;#8217;Article de Blog&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pour illustrer le cycle complet, voici comment cette idée de matrice est née et a été diluée :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;Session 4 mai 2026 — Feedback global du workspace
  │
  ├→ Le LLM identifie : &amp;quot;la dualité public/privé est invisible&amp;quot;
  │   → Classifié VISION (constat architectural vérifiable)
  │
  ├→ PICTURE_ME_ROLLIN_MATRICE_4X4.adoc — STIMULUS (Cercle 0)
  │   → Brain dump structuré, classification VISION confirmée
  │
  ├→ DILUTION → WORKSPACE_AS_PRODUCT.adoc (section Matrice 4×4)
  │   → La spec vit dans les documents racine
  │
  ├→ DILUTION → WORKSPACE_ORGANIZATION.adoc (OSS/CSS)
  │   → La granularisation est documentée
  │
  └→ ARTICLE 0117 (ce document) → cheroliv.com
      → La VISION est publiée&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce qui a commencé comme une observation en session (&amp;quot;hé, le RAG ne sait pas que edster est closed source&amp;quot;) est devenu une spécification d&amp;amp;#8217;architecture publiée en moins d&amp;amp;#8217;une session. C&amp;amp;#8217;est le pattern STIMULUS en action.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_procontra&amp;quot;&amp;gt;Pro/Contra&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 50%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 50%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Cette Approche (Ontologie Spatiale + Matrice)&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;L&amp;amp;#8217;Approche Classique (Prompt + Guardrails)&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Mécanique&amp;lt;/strong&amp;gt; — le système de fichiers bloque l&amp;amp;#8217;accès, pas le LLM&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Déclarative&amp;lt;/strong&amp;gt; — le prompt demande au LLM d&amp;amp;#8217;être prudent&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Testable&amp;lt;/strong&amp;gt; — le contrat de tâche Gradle est vérifié par 380+ tests&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Non testable&amp;lt;/strong&amp;gt; — &amp;quot;le LLM a-t-il respecté la règle ?&amp;quot; est une question ouverte&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Indépendante du LLM&amp;lt;/strong&amp;gt; — changez de modèle, les dossiers restent&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Dépendante du LLM&amp;lt;/strong&amp;gt; — chaque modèle interprète le prompt différemment&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Scalable&amp;lt;/strong&amp;gt; — nouveau type de données = nouveau dossier, zéro changement de code&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Non scalable&amp;lt;/strong&amp;gt; — nouveau type de données = nouvelle clause de prompt, nouveau risque de régression&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Auditable&amp;lt;/strong&amp;gt; — le système de fichiers est l&amp;amp;#8217;audit trail&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Non auditable&amp;lt;/strong&amp;gt; — le prompt n&amp;amp;#8217;a pas d&amp;amp;#8217;historique, pas de diff, pas de blame&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Contrainte&amp;lt;/strong&amp;gt; : exige une discipline d&amp;amp;#8217;organisation initiale&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Contrainte&amp;lt;/strong&amp;gt; : exige une discipline de rédaction de prompt à chaque session&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_conclusion_rangez_vos_fichiers_pas_vos_prompts&amp;quot;&amp;gt;Conclusion : Rangez vos Fichiers, Pas vos Prompts&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La matrice de gouvernance LLM que je viens de décrire n&amp;amp;#8217;est pas un produit. C&amp;amp;#8217;est une &amp;lt;strong&amp;gt;spécification d&amp;amp;#8217;architecture&amp;lt;/strong&amp;gt; — et c&amp;amp;#8217;est pour ça qu&amp;amp;#8217;elle est publiable.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce qui la rend robuste, c&amp;amp;#8217;est qu&amp;amp;#8217;elle ne demande rien au LLM. Elle ne lui fait pas confiance. Elle ne repose pas sur son alignement, sa compréhension du français, ou sa bonne volonté. Elle repose sur le système de fichiers — la couche la plus basse, la plus stable, la plus testée de toute la stack.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Quand je dis à mon LLM &amp;quot;tu peux tout indexer dans &amp;lt;code&amp;gt;OSS/&amp;lt;/code&amp;gt;, rien dans &amp;lt;code&amp;gt;configuration/&amp;lt;/code&amp;gt;, et &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; seulement si c&amp;amp;#8217;est classifié Vision&amp;quot; — ce n&amp;amp;#8217;est pas une instruction. C&amp;amp;#8217;est un &amp;lt;strong&amp;gt;filtre&amp;lt;/strong&amp;gt; — implémenté en Kotlin, vérifié par 380 tests, exécuté avant que le LLM ne voie les données.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est la différence entre dire à quelqu&amp;amp;#8217;un &amp;quot;ne regarde pas dans ce tiroir&amp;quot; et fermer le tiroir à clé. La gouvernance agent que je construis depuis des mois est la clé. La matrice est le plan du meuble.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_références&amp;quot;&amp;gt;Références&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0116_compartimentage_epistemique_automatise_llm_post.html&amp;quot;&amp;gt;Article 0116 — Le Compartimentage Épistémique Automatisé&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0114_gouvernance_cercles_confiance_ontologie_spatiale_alignement_llm_post.html&amp;quot;&amp;gt;Article 0114 — Les Cercles de Confiance et l&amp;amp;#8217;Ontologie Spatiale&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0108_gouvernance_agent_opencode_eager_lazy_post.html&amp;quot;&amp;gt;Article 0108 — Gouverner un Agent IA avec du AsciiDoc&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;../2026/0115_anonymiseur_dataset_mvp0_realite_augmentee_llm_post.html&amp;quot;&amp;gt;Article 0115 — L&amp;amp;#8217;Anonymiseur MVP0&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>La Granularisation OSS/CSS — Pourquoi J&#39;ai Coupé foundry/ en Deux</title>
            <link >https://cheroliv.com/blog/2026/0117_granularisation_oss_css_repositorie_workspace_post.html</link>
            <pubDate>Sun, 3 May 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0117_granularisation_oss_css_repositorie_workspace_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_laccident_qui_attendait_de_se_produire&amp;quot;&amp;gt;L&amp;amp;#8217;Accident qui Attendait de se Produire&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_vraie_question&amp;quot;&amp;gt;La Vraie Question&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_solution_oss_et_css&amp;quot;&amp;gt;La Solution : OSS/ et CSS/&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pourquoi_oss_et_css_et_pas_public_et_private&amp;quot;&amp;gt;Pourquoi &amp;quot;OSS&amp;quot; et &amp;quot;CSS&amp;quot; et Pas &amp;quot;Public&amp;quot; et &amp;quot;Private&amp;quot;&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_larbre_complet_quatre_zones_pas_trois&amp;quot;&amp;gt;L&amp;amp;#8217;Arbre Complet — Quatre Zones, Pas Trois&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_cas_particulier_cheroliv_com&amp;quot;&amp;gt;Le Cas Particulier : cheroliv.com&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bakery_gradle_sen_fiche&amp;quot;&amp;gt;bakery-gradle S&amp;amp;#8217;En Fiche&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_impact_sur_la_gouvernance_agent&amp;quot;&amp;gt;Impact sur la Gouvernance Agent&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ce_quon_gagne_et_ce_quon_perd&amp;quot;&amp;gt;Ce Qu&amp;amp;#8217;on Gagne (Et Ce Qu&amp;amp;#8217;on Perd)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_conclusion_le_signal_physique_bat_le_signal_logiciel&amp;quot;&amp;gt;Conclusion : le Signal Physique Bat le Signal Logiciel&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_références&amp;quot;&amp;gt;Références&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 10 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt; — la zone fonctionnelle qui héberge le code de mon workspace — contient 18 projets. Huit sont open source sous Apache 2.0. Un seul est closed source — le SaaS Edster. Pendant des mois, ces neuf projets ont cohabité dans le même dossier, séparés uniquement par&amp;amp;#8230;&amp;amp;#8203; rien. Leur statut public/privé était une information dans ma tête, pas dans le système de fichiers.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Et puis j&amp;amp;#8217;ai voulu brancher un RAG. Et là, tout s&amp;amp;#8217;est effondré.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_laccident_qui_attendait_de_se_produire&amp;quot;&amp;gt;L&amp;amp;#8217;Accident qui Attendait de se Produire&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;En avril 2026, j&amp;amp;#8217;ai commencé à implémenter le RAG pgvector pour slider-gradle. Le principe : indexer tous les dépôts de &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt;, produire des embeddings, et les injecter dans le contexte du LLM pour qu&amp;amp;#8217;il ait une &amp;quot;perception&amp;quot; du dossier &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le pipeline était simple :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;val repos = fileTree(rootDir) {
    include(&amp;quot;**/*.adoc&amp;quot;, &amp;quot;**/*.kts&amp;quot;, &amp;quot;**/*.kt&amp;quot;, &amp;quot;**/*.json&amp;quot;, &amp;quot;**/*.yml&amp;quot;)
}
val chunks = repos.map { chunk(it) }
val embeddings = chunks.map { embed(it) }
pgvector.insert(embeddings)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Simple. Efficace. Et &amp;lt;strong&amp;gt;dangereux&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Parce que ce &amp;lt;code&amp;gt;fileTree&amp;lt;/code&amp;gt; ne fait pas la différence entre &amp;lt;code&amp;gt;plantuml-gradle/&amp;lt;/code&amp;gt; (Apache 2.0, public) et &amp;lt;code&amp;gt;edster/&amp;lt;/code&amp;gt; (closed source, private). Il avale tout. Et si un jour je publie ces embeddings — sur un dashboard, dans une réponse LLM, dans un dataset d&amp;amp;#8217;entraînement — le code propriétaire d&amp;amp;#8217;Edster fuit.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock caution&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-caution&amp;quot; title=&amp;quot;🔒&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le problème n&amp;amp;#8217;est pas qu&amp;amp;#8217;un LLM lise du code closed source. Le problème, c&amp;amp;#8217;est que ce code finisse dans un embedding vectoriel &amp;lt;strong&amp;gt;public&amp;lt;/strong&amp;gt; — irréversible, non supprimable, non auditable.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_la_vraie_question&amp;quot;&amp;gt;La Vraie Question&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce n&amp;amp;#8217;est pas &amp;quot;comment empêcher le LLM de fuiter du code ?&amp;quot;. C&amp;amp;#8217;est &amp;quot;comment rendre la fuite structurellement impossible ?&amp;quot;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La réponse n&amp;amp;#8217;est pas un prompt. La réponse, c&amp;amp;#8217;est de couper le dossier en deux.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_solution_oss_et_css&amp;quot;&amp;gt;La Solution : OSS/ et CSS/&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avant :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;foundry/
├── plantuml-gradle/       ← public
├── bakery-gradle/         ← public
├── magic-stick/           ← public
├── edster/                ← PRIVÉ
├── slider-gradle/         ← public
└── ...                    ← mélange invisible&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Après :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;foundry/
├── OSS/                   ← tout est Apache 2.0
│   ├── plantuml-gradle/
│   ├── bakery-gradle/
│   ├── magic-stick/
│   ├── slider-gradle/
│   └── ...
└── CSS/                   ← tout est closed source / private
    └── edster/&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le &amp;lt;code&amp;gt;fileTree&amp;lt;/code&amp;gt; devient :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;val ossRepos = fileTree(File(rootDir, &amp;quot;OSS&amp;quot;)) {
    include(&amp;quot;**/*.adoc&amp;quot;, &amp;quot;**/*.kts&amp;quot;, &amp;quot;**/*.kt&amp;quot;, &amp;quot;**/*.json&amp;quot;, &amp;quot;**/*.yml&amp;quot;)
}
val cssRepos = fileTree(File(rootDir, &amp;quot;CSS&amp;quot;)) {
    include(&amp;quot;**/*.adoc&amp;quot;, &amp;quot;**/*.kts&amp;quot;, &amp;quot;**/*.kt&amp;quot;, &amp;quot;**/*.json&amp;quot;, &amp;quot;**/*.yml&amp;quot;)
}

// Embeddings publics — OSS seulement
pgvectorPublic.insert(ossRepos.map { chunk(it) }.map { embed(it) })

// Dataset fine-tuning privé — CSS seulement
fineTuningDataset.insert(cssRepos.map { chunk(it) })  // jamais publié&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock important&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-important&amp;quot; title=&amp;quot;❗&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le RAG public ne voit jamais &amp;lt;code&amp;gt;CSS/&amp;lt;/code&amp;gt;. Le code closed source alimente un dataset privé de fine-tuning — un modèle interne qui ne sort jamais de chez moi. La séparation est mécanique, pas déclarative.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_pourquoi_oss_et_css_et_pas_public_et_private&amp;quot;&amp;gt;Pourquoi &amp;quot;OSS&amp;quot; et &amp;quot;CSS&amp;quot; et Pas &amp;quot;Public&amp;quot; et &amp;quot;Private&amp;quot;&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le choix des acronymes OSS (Open Source Software) et CSS (Closed Source Software) est délibéré :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;quot;Public&amp;quot;/&amp;quot;Private&amp;quot; décrit la &amp;lt;strong&amp;gt;visibilité&amp;lt;/strong&amp;gt; (ce que GitHub voit)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;quot;OSS&amp;quot;/&amp;quot;CSS&amp;quot; décrit la &amp;lt;strong&amp;gt;nature&amp;lt;/strong&amp;gt; du code (ce que le LLM doit savoir)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La visibilité GitHub est une métadonnée du repo distant. La nature du code est une propriété du contenu. Le LLM n&amp;amp;#8217;a pas accès à l&amp;amp;#8217;API GitHub — mais il a accès au système de fichiers. &amp;lt;code&amp;gt;CSS/&amp;lt;/code&amp;gt; lui dit &amp;quot;attention, ce code n&amp;amp;#8217;est pas sous licence libre&amp;quot; sans avoir besoin de lire un &amp;lt;code&amp;gt;LICENSE&amp;lt;/code&amp;gt; ou de parser un &amp;lt;code&amp;gt;package.json&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock tip&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-tip&amp;quot; title=&amp;quot;💡&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le nom du dossier est la métadonnée la plus robuste que vous puissiez donner à un LLM. Elle ne peut pas être mal parsée, ignorée, ou mal interprétée. Le LLM voit &amp;lt;code&amp;gt;CSS/edster/&amp;lt;/code&amp;gt; dans le chemin du fichier — il sait.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_larbre_complet_quatre_zones_pas_trois&amp;quot;&amp;gt;L&amp;amp;#8217;Arbre Complet — Quatre Zones, Pas Trois&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La granularisation OSS/CSS complète l&amp;amp;#8217;ontologie à trois zones. La zone &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt; passe de 1 à 2 sous-zones fonctionnelles :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-four-zone-workspace&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-69dfc4d88e57c2bbc80fff055ca536cd.svg&amp;quot; alt=&amp;quot;L&amp;amp;#8217;organisation de foundry/ en deux sous-zones OSS et CSS&amp;quot; width=&amp;quot;1769&amp;quot; height=&amp;quot;5736&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;| Zone | RGPD | Indexation RAG public | Dataset fine-tuning | | Racine | Niveau 0 — Intime | ✗ | ✗ | | &amp;lt;code&amp;gt;configuration/&amp;lt;/code&amp;gt; | Niveau 1 — Restreint | ✗ | ✗ | | &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; | Niveau 2 — Collaboratif | ✓ Filtré | ✓ Filtré | | &amp;lt;code&amp;gt;foundry/private/&amp;lt;/code&amp;gt; | Niveau 3 — Ouvert conditionnel | ✗ | ✓ Privé | | &amp;lt;code&amp;gt;foundry/public/&amp;lt;/code&amp;gt; | Niveau 4 — Public natif | ✓ Libre | ✓ Public |&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_cas_particulier_cheroliv_com&amp;quot;&amp;gt;Le Cas Particulier : cheroliv.com&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pendant que j&amp;amp;#8217;y étais, j&amp;amp;#8217;ai corrigé une autre incohérence. Mon site &amp;lt;code&amp;gt;cheroliv.com&amp;lt;/code&amp;gt; vivait dans &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt; comme un projet logiciel à part entière — avec son propre build Gradle, sa propre CI, sa propre gouvernance &amp;lt;code&amp;gt;.agents/&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mais les articles de blog ne sont pas du code. Ce sont des &amp;lt;strong&amp;gt;données éditoriales&amp;lt;/strong&amp;gt; de Cercle 2 — au même titre que les cadrages de &amp;lt;code&amp;gt;office/pilotage/&amp;lt;/code&amp;gt; ou les formations de &amp;lt;code&amp;gt;office/formations/&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;AVANT                            APRÈS
foundry/                office/
  cheroliv.com/                    sites/
    site/jbake/content/blog/         cheroliv.com/
      2026/0117_....adoc               2026/0117_....adoc&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce qui change :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Les articles sont dans &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; → confidentialité de Cercle 2&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;La tâche &amp;lt;code&amp;gt;publishSite&amp;lt;/code&amp;gt; devient une capability de &amp;lt;code&amp;gt;engine&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;via &amp;lt;code&amp;gt;bakery-gradle&amp;lt;/code&amp;gt; — le plugin reçoit un &amp;lt;code&amp;gt;FileTree&amp;lt;/code&amp;gt;, il ne sait pas que les articles viennent de &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Une seule CI, une seule gouvernance — zéro duplication&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le classifier Vision/Opinion (Règle 2bis) s&amp;amp;#8217;applique automatiquement :&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;les articles dans &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; sont filtrés avant publication&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_bakery_gradle_sen_fiche&amp;quot;&amp;gt;bakery-gradle S&amp;amp;#8217;En Fiche&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Et c&amp;amp;#8217;est ça qui est beau. Le plugin &amp;lt;code&amp;gt;bakery-gradle&amp;lt;/code&amp;gt; n&amp;amp;#8217;a pas été modifié. Il reçoit un répertoire de contenu AsciiDoc, il génère du HTML, il push sur GitHub Pages. Que ce répertoire s&amp;amp;#8217;appelle &amp;lt;code&amp;gt;site/jbake/content/&amp;lt;/code&amp;gt; ou &amp;lt;code&amp;gt;office/sites/cheroliv/&amp;lt;/code&amp;gt; — le plugin s&amp;amp;#8217;en fout.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// engine/build.gradle.kts
task(&amp;quot;publishBlog&amp;quot;) {
    doLast {
        val articles = fileTree(&amp;quot;../../office/sites/cheroliv/2026/&amp;quot;)
        bakery.generate(articles)  // ← bakery ne sait pas d&amp;#39;où ça vient
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le contrat d&amp;amp;#8217;interface est une tâche Gradle. Pas une API REST. Pas un webhook. Une tâche — typée, testable, exécutable en local et dans la CI.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_impact_sur_la_gouvernance_agent&amp;quot;&amp;gt;Impact sur la Gouvernance Agent&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La granularisation OSS/CSS modifie la gouvernance agent sur trois points :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;RAG public&amp;lt;/strong&amp;gt; : le périmètre d&amp;amp;#8217;indexation passe de &amp;lt;code&amp;gt;foundry/**&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;à &amp;lt;code&amp;gt;foundry/public/&amp;lt;strong&amp;gt;&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;office/Vision/&amp;lt;/strong&amp;gt;&amp;lt;/code&amp;gt;. Le code closed source est exclu de l&amp;amp;#8217;index par configuration de tâche, pas par prompt.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Knowledge Graph&amp;lt;/strong&amp;gt; : graphify-gradle produit deux graphes :&amp;lt;/p&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;office/graph.json&amp;lt;/code&amp;gt; (public) — relations entre artéfacts OSS + office/Vision * &amp;lt;code&amp;gt;configuration/graph_private.json&amp;lt;/code&amp;gt; (gitignored, privé) — relations entre artéfacts CSS, jamais publié&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Dataset fine-tuning&amp;lt;/strong&amp;gt; : &amp;lt;code&amp;gt;codebase-gradle&amp;lt;/code&amp;gt; a désormais deux sources :&amp;lt;/p&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;OSS/&amp;lt;/code&amp;gt; → datasets publics (modèles communautaires, benchmarks) * &amp;lt;code&amp;gt;CSS/&amp;lt;/code&amp;gt; → datasets privés (modèle interne, fine-tuning propriétaire)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_ce_quon_gagne_et_ce_quon_perd&amp;quot;&amp;gt;Ce Qu&amp;amp;#8217;on Gagne (Et Ce Qu&amp;amp;#8217;on Perd)&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1436%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Avant (dossier plat)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Après (OSS/CSS + office/sites)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;ls foundry/&amp;lt;/code&amp;gt; → mélange public/privé&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;ls foundry/public/&amp;lt;/code&amp;gt; → tout est publiable&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;RAG indexe tout sans discrimination&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;RAG indexe &amp;lt;code&amp;gt;OSS/&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;office/Vision&amp;lt;/code&amp;gt; exclusivement&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Impossible de savoir si un projet est open source&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Le chemin &amp;lt;code&amp;gt;OSS/&amp;lt;/code&amp;gt; ou &amp;lt;code&amp;gt;CSS/&amp;lt;/code&amp;gt; le dit&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;cheroliv.com a sa propre CI, sa propre gouvernance&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;La CI et la gouvernance sont mutualisées dans engine&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Les articles de blog sont dans un dépôt &amp;quot;code&amp;quot;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Les articles de blog sont dans &amp;lt;code&amp;gt;office/sites/&amp;lt;/code&amp;gt; — data, pas code&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Risque de fuite de code closed source dans des embeddings publics&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Structurellement impossible — &amp;lt;code&amp;gt;CSS/&amp;lt;/code&amp;gt; hors scope RAG&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le seul coût : un &amp;lt;code&amp;gt;git mv&amp;lt;/code&amp;gt; global sur les 17 dépôts OSS + un refactor du &amp;lt;code&amp;gt;build.gradle.kts&amp;lt;/code&amp;gt; de &amp;lt;code&amp;gt;engine&amp;lt;/code&amp;gt;. C&amp;amp;#8217;est une migration à froid — pas de données en vol, pas d&amp;amp;#8217;utilisateurs impactés.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_conclusion_le_signal_physique_bat_le_signal_logiciel&amp;quot;&amp;gt;Conclusion : le Signal Physique Bat le Signal Logiciel&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce que j&amp;amp;#8217;ai fait cet après-midi, c&amp;amp;#8217;est remplacer une convention invisible par une séparation visible dans la zone &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt;. Avant, vous deviez &amp;lt;strong&amp;gt;savoir&amp;lt;/strong&amp;gt; que &amp;lt;code&amp;gt;edster/&amp;lt;/code&amp;gt; était closed source. Maintenant, vous le &amp;lt;strong&amp;gt;voyez&amp;lt;/strong&amp;gt; — le dossier s&amp;amp;#8217;appelle &amp;lt;code&amp;gt;CSS/&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est le même principe que les permissions Unix, les VLAN réseau, ou les compartiments coupe-feu dans une base de données. La sécurité ne doit pas être une information que vous devez retenir. Elle doit être une propriété &amp;lt;strong&amp;gt;physique&amp;lt;/strong&amp;gt; du système.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La granularisation OSS/CSS est la traduction de ce principe dans le domaine de la gouvernance LLM. Le LLM n&amp;amp;#8217;a pas besoin de savoir qu&amp;amp;#8217;Edster est confidentiel. Il a besoin d&amp;amp;#8217;être incapable de l&amp;amp;#8217;indexer.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Et c&amp;amp;#8217;est exactement ce que &amp;lt;code&amp;gt;CSS/&amp;lt;/code&amp;gt; garantit.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_références&amp;quot;&amp;gt;Références&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0118_matrice_gouvernance_llm_zone_acces_workspace_post.html&amp;quot;&amp;gt;Article 0117 — La Matrice de Gouvernance LLM&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0114_gouvernance_cercles_confiance_ontologie_spatiale_alignement_llm_post.html&amp;quot;&amp;gt;Article 0114 — Les Cercles de Confiance&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0116_compartimentage_epistemique_automatise_llm_post.html&amp;quot;&amp;gt;Article 0116 — Le Compartimentage Épistémique Automatisé&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;0108_gouvernance_agent_opencode_eager_lazy_post.html&amp;quot;&amp;gt;Article 0108 — Gouverner un Agent IA avec du AsciiDoc&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Le Compartimentage Épistémique Automatisé — Comment le LLM Protège Mon Jardin Mental</title>
            <link >https://cheroliv.com/blog/2026/0116_compartimentage_epistemique_automatise_llm_post.html</link>
            <pubDate>Sat, 2 May 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0116_compartimentage_epistemique_automatise_llm_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_problème_penser_librement_sans_publier_nimporte_quoi&amp;quot;&amp;gt;Le Problème : Penser Librement sans Publier N&amp;amp;#8217;Importe Quoi&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_pattern_stimulus_naître_fixer_diluer_mourir&amp;quot;&amp;gt;Le Pattern STIMULUS — Naître, Fixer, Diluer, Mourir&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_délégation_au_llm_pourquoi_cest_le_llm_qui_filtre&amp;quot;&amp;gt;La Délégation au LLM : Pourquoi C&amp;amp;#8217;est le LLM Qui Filtre&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 10 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Mon LLM ne se contente pas d&amp;amp;#8217;exécuter mes tâches Gradle. Il est le gardien de la frontière entre ma pensée privée et mon expression publique. Chaque idée est classifiée — Vision, Opinion, Stratégie — avant d&amp;amp;#8217;être routée. Voici comment ce compartimentage épistémique automatisé protège mon jardin mental sans me faire taire.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;toc&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;[]&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_problème_penser_librement_sans_publier_nimporte_quoi&amp;quot;&amp;gt;Le Problème : Penser Librement sans Publier N&amp;amp;#8217;Importe Quoi&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Quand un développeur solo documente son processus de pensée avec un LLM, il se heurte à un paradoxe :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;CAPTURE TOUT (Cercle 0, jardin secret)
  ├→ Brain dump libre, pas de censure
  ├→ Idées brutes, spéculations, intuitions non vérifiées
  ├→ Allers-retours LLM : challenger, itérer, raffiner
  └→ Le LLM voit TOUT — le bon, le flou, l&amp;#39;embryonnaire

PUBLICATION SÉLECTIVE (Cercle 4, blog public)
  ├→ Uniquement les décisions actées
  ├→ Uniquement les patterns testés (&amp;amp;gt;100 tests PASS)
  ├→ Uniquement ce qui a de la valeur pour le lecteur
  └→ JAMAIS une spéculation présentée comme une vérité&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Entre ces deux extrêmes, il y a un &amp;lt;strong&amp;gt;filtre&amp;lt;/strong&amp;gt;. La question est : qui le fait ? Un humain fatigué en fin de session ? Un script de regex naïf ? Ou le LLM lui-même, qui a déjà tout lu ?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ma réponse : le LLM.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_pattern_stimulus_naître_fixer_diluer_mourir&amp;quot;&amp;gt;Le Pattern STIMULUS — Naître, Fixer, Diluer, Mourir&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le STIMULUS est un fichier &amp;lt;code&amp;gt;.adoc&amp;lt;/code&amp;gt; temporaire à la racine du workspace (Cercle 0). Son nom suit une convention évocatrice — &amp;lt;code&amp;gt;PICTURE_ME_ROLLIN.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;HOLD_MY_BEER.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ONCE_UPON_A_TIME.adoc&amp;lt;/code&amp;gt; — qui capture l&amp;amp;#8217;intention exploratoire du moment.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Son cycle de vie est impitoyable :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;CRÉATION (Cercle 0)
  ├→ Fichier vide, brain dump libre
  ├→ Allers-retours LLM ← → développeur
  └→ Aucune pression de structure ou de publication

MATURATION
  ├→ Le contenu se densifie
  ├→ Des sections émergent naturellement
  └→ Le fichier devient une référence informelle de session

CLASSIFICATION ÉPISTÉMIQUE ← FAIT PAR LE LLM
  ├→ VISION    → publiable, diluer dans les docs publics + blog
  ├→ OPINION   → confiner au Cercle 0, pas de dilution externe
  └→ STRATÉGIE → dilution restreinte (docs racine, PAS de blog)

DILUTION (Cascade vers Cercles légitimes)
  ├→ VISION → WORKSPACE_AS_PRODUCT.adoc + WHAT_THE_GAMES.adoc + blog
  ├→ STRATÉGIE → WORKSPACE_AS_PRODUCT.adoc (section business)
  └→ OPINION → reste dans le stimulus, ne bouge pas

ARCHIVAGE + SUPPRESSION
  ├→ Snapshot dans configuration/vision-archive/ (trace historique)
  └→ rm du stimulus — il a fini son travail&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un stimulus qui survit plus de 2 sessions sans dilution est un anti-pattern. Soit l&amp;amp;#8217;information est trop importante pour moisir dans un fichier temporaire (→ diluer), soit elle est trop floue pour mériter d&amp;amp;#8217;exister (→ supprimer).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_délégation_au_llm_pourquoi_cest_le_llm_qui_filtre&amp;quot;&amp;gt;La Délégation au LLM : Pourquoi C&amp;amp;#8217;est le LLM Qui Filtre&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Je ne hardcode pas la classification Vision/Opinion en Kotlin. Je l&amp;amp;#8217;injecte dans le &amp;lt;strong&amp;gt;prompt système&amp;lt;/strong&amp;gt; du LLM via &amp;lt;code&amp;gt;AGENT_GOVERNANCE.adoc&amp;lt;/code&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;----
Pour chaque dilution de stimulus ou session, tu es responsable de classifier
le contenu :
- VISION : décision architecturale actée, pattern testé en production (&amp;amp;gt;100 tests PASS),
  décision documentée dans BACKLOG ou ROADMAP
- OPINION : spéculation, hypothèse non validée par des tests, intuition
  sans ancrage expérimental
- STRATEGIE : positionnement business, pricing, marché cible

Règles :
- Si OPINION, le contenu reste confiné dans son cercle d&amp;#39;origine
- Si VISION, tu procèdes à la dilution dans les documents racine
- Si STRATEGIE, dilution restreinte (docs racine, pas de blog public)
- Cette classification détermine aussi si un article de blog est publiable
  sur cheroliv.com
----

Le LLM lit cette directive **avant** de traiter la session. Elle est dans son contexte immédiat, pas dans un fichier séparé. C&amp;#39;est du *prompt engineering déterministe* : le comportement émerge du texte injecté, pas d&amp;#39;un classifieur externe.

=== Pourquoi Ça Marche — et Pourquoi C&amp;#39;est Contre-Intuitif

La réaction standard : « Tu confies la classification à l&amp;#39;IA ? Et si elle se trompe ? »

Réponse : l&amp;#39;humain ne fait pas mieux à 2h du matin. La différence, c&amp;#39;est que le LLM, lui, lit TOUT. Il a le contexte complet de la session et des documents cibles. Il sait que `VPS ECO-16 12€ HT` est une décision d&amp;#39;infrastructure (VISION) alors que `« le TTS ElevenLabs sonne plus naturel que Coqui »` est une opinion non vérifiée par un benchmark.

L&amp;#39;humain, en fin de session, lit en diagonale et fait au mieux. Le LLM lit exhaustivement et applique une grille systématique. Le résultat est **plus fiable**, pas moins.

Et pour les 20% de cas ambigus — la zone grise où même le LLM hésite — la réponse n&amp;#39;est pas « rajouter du code ». La réponse est **LangGraph4j** (EPIC 13) : un graphe d&amp;#39;état qui, pour les cas ambigus, active un nœud Human-in-the-Loop et remonte à l&amp;#39;humain pour décision. Mais pour les 80% de cas clairs, le LLM suffit.

== Le Tuyau Complet : du Brain Dump au Blog Post

Voici le flux complet — de l&amp;#39;idée brute à l&amp;#39;article publié — avec le LLM comme seul filtre :

[source]
----
CERCLE 0 (jardin secret)
  PICTURE_ME_ROLLIN.adoc   ← brain dump, allers-retours LLM
       ↓
  [LLM classifie] → VISION / OPINION / STRATÉGIE
       ↓
  VISION → dilution dans WORKSPACE_AS_PRODUCT.adoc
         → dilution dans WHAT_THE_GAMES_BEEN_MISSING.adoc
         → dilution dans WORKSPACE_VISION.adoc (session context)
         → RÉDACTION ARTICLE BLOG ← le LLM écrit, pas le dev
       ↓
CERCLE 4 (blog public)
  0116_compartimentage_epistemique.adoc  ← publié sur cheroliv.com
       ↓
  ./gradlew deploy (bakery-gradle → JBake → JGit → GitHub Pages)
       ↓
  https://cheroliv.com/blog/2026/0116/  ← live
----

Le développeur n&amp;#39;écrit pas l&amp;#39;article. Il challenge, relit, valide. Le LLM écrit. La boucle est :

1. Brain dump libre → pas de censure
2. Classification épistémique par le LLM → pas de fuite
3. Rédaction par le LLM → pas de procrastination
4. Relecture humaine → pas d&amp;#39;erreur

Le goulot d&amp;#39;étranglement historique — « je n&amp;#39;ai pas le temps d&amp;#39;écrire » — est éliminé. Le LLM fait le gros du travail. L&amp;#39;humain fait ce que seul l&amp;#39;humain peut faire : juger.

== Les Trois Documents Racine — Comment l&amp;#39;Information Trouve Sa Place

Chaque document cible a un rôle précis dans la cascade de dilution :

[cols=&amp;quot;1,3,2&amp;quot;]
|===
|Document |Ce qu&amp;#39;il reçoit |Type de contenu |`WORKSPACE_AS_PRODUCT.adoc` |Décisions architecturales, stack technique, roadmap, business model |VISION + STRATÉGIE |`WHAT_THE_GAMES_BEEN_MISSING.adoc` |Patterns, leçons, anti-patterns, ontologie, règles formelles |VISION (patterns testés) |`WORKSPACE_VISION.adoc` |Contexte de session, historique des décisions, points d&amp;#39;infrastructure |VISION + STRATÉGIE (contexte) |`AGENT_GOVERNANCE.adoc` |Règles de gouvernance, portefeuille projets, procédures |VISION (gouvernance) |**Blog cheroliv.com** |Articles publics, valeur pour le lecteur externe |VISION uniquement
|===

Un même stimulus peut nourrir les 4 documents + le blog — chaque destination reçoit la portion qui la concerne, sans redondance, sans contradiction.

C&amp;#39;est ce qui s&amp;#39;est passé pour `PICTURE_ME_ROLLIN.adoc` (3 mai 2026) :

| Information | Classification | Destinations | | Inventaire des 13+ projets foundry/ | VISION | WORKSPACE_AS_PRODUCT | | VPS-2 OVH, edster.cloud, 8.49€/mois | VISION | WORKSPACE_AS_PRODUCT + WORKSPACE_VISION | | « Le marché africain est prêt pour le mobile money » | STRATÉGIE | WORKSPACE_AS_PRODUCT (section business) | | « DeepSeek &amp;amp;gt; Kimi &amp;amp;gt; GLM pour contexte long » | OPINION → VISION | Confiné puis promu après benchmark (article 0112) | | Employé Synthétique comme produit final | STRATÉGIE | WORKSPACE_AS_PRODUCT (pas de blog) |

== Le Pattern Baby-Step + TestContainer + Doc Vivante — le Code qui Se Teste Lui-Même

Le pattern STIMULUS/Dilution gère la pensée. Son équivalent pour le code, c&amp;#39;est le pattern Baby-Step/TestContainer/Doc Vivante, validé par plantuml-gradle (380/380 tests PASS, 137 sessions sans fuite Docker) :

[cols=&amp;quot;1,3&amp;quot;]
|===
|Principe |Règle |**Baby-step** |Jamais plus de 3 pts par US. Si une US fait peur, recouper. Une US de 1 pt qui passe &amp;amp;gt; une US de 8 pts qui traîne. |**TestContainer d&amp;#39;abord** |Avant le code métier, le conteneur. Le test d&amp;#39;infra passe → environnement stable garanti. |**Dataset committé** |Sous-ensemble minimal mais représentatif dans `src/test/resources/`, sans PII. Clonable, lançable. |**Documentation vivante** |Chaque test Cucumber = une phrase en langage naturel. Le code source EST la spec exécutable. Zéro doc Markdown à maintenir. |**Cleanup automatique** |Zéro fuite de ressources. Containers orphelins, `/tmp/gradle-test-*` : tout est nettoyé.
|===

Ce pattern est la raison pour laquelle plantuml-gradle n&amp;#39;a jamais eu de régression Docker en 138 sessions. Il garantit que le code qui parle à une infra externe (PostgreSQL, Redis, Kafka) est toujours testé dans un environnement identique à la production — versionné, reproductible, lançable en une commande.

== Conclusion : la Liberté de Penser sans la Peur de Publier

Le compartimentage épistémique automatisé n&amp;#39;est pas un outil de censure. C&amp;#39;est un **libérateur**. Il permet de penser librement, de spéculer sans filtre, de brain-dumper tout ce qui passe par la tête — sans jamais craindre qu&amp;#39;une idée embryonnaire se retrouve sur le blog.

Le LLM est le gardien de cette frontière. Il lit tout. Il classifie. Il dilue ce qui mérite de survivre. Il confine ce qui doit rester privé. Il rédige ce qui est publiable.

Et le développeur, lui, garde le dernier mot : relire, challenger, valider. Juger.

C&amp;#39;est la division du travail qui manquait au développeur solo : un employé synthétique qui gère la paperasse mentale, pour que l&amp;#39;humain puisse se concentrer sur ce qu&amp;#39;il fait de mieux — concevoir, architecturer, décider.

== Références

* Article sur la gouvernance agent Eager/Lazy : link:../2026/0108_gouvernance_agent_opencode_eager_lazy_post.html[Gouverner un Agent IA avec du AsciiDoc]
* Article sur l&amp;#39;ontologie spatiale et les cercles de confiance : link:../2026/0114_gouvernance_cercles_confiance_ontologie_spatiale_alignement_llm_post.html[L&amp;#39;Ontologie Spatiale comme Mécanisme d&amp;#39;Alignement]
* Article sur l&amp;#39;Anonymiseur MVP0 : link:../2026/0115_anonymiseur_dataset_mvp0_realite_augmentee_llm_post.html[Notre Premier Embauché : l&amp;#39;Anonymiseur de Datasets]
* Article sur la comparaison des LLMs long contexte : link:../2026/0112_comparaison_kimi_glm_deepseek_long_contexte_plugin_gradle_opencode_post.html[DeepSeek-V4-Pro, Kimi K2.6, GLM-5.1]
* Article sur le mécanisme de backup agent : link:../2026/0110_mecanisme_backup_contexte_agent_post.html[Sliding Window et Vague Froide]&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Notre Premier Embauché : l&#39;Anonymiseur de Datasets — MVP0 en Période d&#39;Essai</title>
            <link >https://cheroliv.com/blog/2026/0115_anonymiseur_dataset_mvp0_realite_augmentee_llm_post.html</link>
            <pubDate>Fri, 1 May 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0115_anonymiseur_dataset_mvp0_realite_augmentee_llm_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_problème_qui_fait_fuir_tout_le_monde&amp;quot;&amp;gt;Le Problème qui Fait Fuir tout le Monde&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 12 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Je n&amp;amp;#8217;embauche pas un LLM. J&amp;amp;#8217;embauche un anonymiseur. Avant de faire du RAG pgvector, avant de fine-tuner des experts CDA/FPA, avant de provisionner des workspaces clients — quelqu&amp;amp;#8217;un doit nettoyer les toilettes de la data. Cet employé, c&amp;amp;#8217;est l&amp;amp;#8217;expert anonymisation (MVP0, EPIC 2 de codebase-gradle). Et c&amp;amp;#8217;est lui qui rend le produit marketable.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;toc&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;[]&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_problème_qui_fait_fuir_tout_le_monde&amp;quot;&amp;gt;Le Problème qui Fait Fuir tout le Monde&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Toute startup IA qui manipule des données de formation se heurte au même mur :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;----
Données brutes client (SPG, cours, évaluations)
  ├→ Noms de stagiaires en clair dans les PDF
  ├→ Emails dans les métadonnées JSON
  ├→ IP de connexion dans les logs pgvector
  ├→ Identifiants dans les nœuds Graphify
  └→ Références OF pilote dans les schémas SQL
----

Résultat : soit tu fais du RAG sur des données sales (hallucinations de PII, non-conformité RGPD, risque juridique), soit tu ne fais rien (pas de produit). La troisième voie — nettoyer à la main — n&amp;#39;est pas scalable.

Ma réponse : ne pas contourner le problème. L&amp;#39;**automatiser**.

== MVP0 : l&amp;#39;Anonymiseur, Premier Embauché en Période d&amp;#39;Essai

Le MVP0 n&amp;#39;est pas une feature. C&amp;#39;est un **expert de commodité** — un employé qui fait le sale boulot bête et méchant, et dont personne ne veut parler dans les pitch decks.

Ce qu&amp;#39;il fait :

[source]
----
ENTRÉE : Données brutes multi-sources
  ├→ AsciiDoc (SPG_A2SP.adoc) → noms, dates, OF pilote
  ├→ JSON (catalogue formations) → emails, téléphones
  ├→ YAML (config workspace) → tokens OAuth2
  ├→ SQL (schémas DDL) → IP, adresses
  ├→ pgvector (métadonnées embeddings) → identifiants
  ├→ ONNX (outputs classification) → noms propres
  └→ Graphify (graph.json) → nœuds avec PII

SORTIE : Datasets propres, format standardisé
  ├→ [ANONYMIZED] remplace les PII détectées
  ├→ Classification RGPD (niveau 0→4)
  ├→ Rapport d&amp;#39;audit (quoi a été nettoyé)
  └→ Dataset prêt pour RAG ET fine-tuning
----

Il détecte les patterns les plus évidents d&amp;#39;abord (emails `.*@.*`, tokens `sk-*`, `ghp_*`, IPs), puis il apprend. La période d&amp;#39;essai, c&amp;#39;est ça : on valide qu&amp;#39;il ne laisse pas passer de faux négatifs avant de le titulariser.

== Ce Que ce MVP Débloque (et ce n&amp;#39;est pas juste la Conformité)

L&amp;#39;anonymisation comme MVP0 n&amp;#39;est pas le péage RGPD avant l&amp;#39;autoroute. C&amp;#39;est l&amp;#39;autoroute elle-même. Voici ce qu&amp;#39;elle ouvre :

=== Présent : Réalité Augmentée en Prompt

[source]
----
DONNÉES BRUTES CLIENT
    ↓
Anonymiseur MVP0 → datasets propres
    ↓
RAG pgvector (MVP1) → top-K documents similaires (filtrés, anonymisés)
    ↓
LLM (deepseek-v4-pro) → réponse augmentée, zéro PII
----

Le RAG ne cherche pas dans des données sales — il cherche dans un espace **propre par construction**. Ça change tout pour la qualité des réponses : le LLM ne passe pas son temps à contourner des PII qu&amp;#39;il reconnaît mais qu&amp;#39;il ne doit pas mentionner.

=== Futur : Fine-Tuning sur Données Saines

[source]
----
MVP0 → datasets propres accumulés (session après session)
    ↓
Fine-tuning expert métier (CDA, FPA) sur données zéro PII
    ↓
Modèle fine-tuné exposé via Ollama (sans fuite de données)
----

Le fine-tuning sur données brutes est une catastrophe juridique en puissance. Sur données propres, c&amp;#39;est une **méthode reproductible**. Chaque client accumule ses datasets nettoyés, chaque client peut fine-tuner ses experts métier sur ses données — sans jamais exposer une donnée personnelle.

== Pourquoi C&amp;#39;est Marketable

Ce n&amp;#39;est pas « un outil de conformité RGPD ». C&amp;#39;est une **méthode reproductible qui transforme un problème universel en actif** :

1. *Toute entreprise de formation a des données sales* — c&amp;#39;est le problème
2. *Aucune n&amp;#39;a de pipeline automatisé de nettoyage multi-source* — c&amp;#39;est le marché
3. *La boucle : anonymisation → RAG → fine-tuning est propriétaire* — c&amp;#39;est la barrière

Le SaaS Edster (MVP3) ne vendra pas « un workspace Gradle ». Il vendra cette boucle fermée. Et le MVP0 est la porte d&amp;#39;entrée.

== Le Format SQL comme Troisième Voie de Contexte

L&amp;#39;import de données structurées n&amp;#39;est pas qu&amp;#39;un format d&amp;#39;échange. Le schéma SQL (DDL) porte le **modèle entité-relation du domaine** :

[source]
----
CREATE TABLE formation (
  id UUID PRIMARY KEY,
  titre VARCHAR NOT NULL,
  referentiel RNCP REFERENCES rncp(id),
  organisme OF REFERENCES of_pilote(id)  -- ← va être anonymisé
);
----

Ce DDL, une fois anonymisé (ligne 4), devient une source de contexte pour le LLM. Pas du texte — du **modèle métier**. Le RAG donne le contenu (similarité vectorielle), Graphify donne les relations (structure exacte), et le schéma SQL donne le **Domain-Driven Design implicite** : bounded contexts, agrégats, value objects. Le LLM comprend le métier parce qu&amp;#39;il lit son schéma.

== La Roadmap : du MVP0 au SaaS

[source]
----
MVP0 — Anonymiseur (ce que cet article décrit)
  Sortie : datasets propres, reproductible

MVP1 — RAG pgvector (dépend de MVP0)
  Realité augmentée en prompt sur données nettoyées

MVP2 — Graphify + ONNX + SQL DDD (dépend de MVP1)
  Vecteur composite de contexte (règles + similarité + relations exactes)

MVP3 — SaaS Edster (dépend de MVP0-2)
  Provisionnement workspace client complet
----

Chaque MVP dépend du précédent. Aucun ne peut être livré sans le MVP0. C&amp;#39;est la raison pour laquelle l&amp;#39;Anonymiseur n&amp;#39;est pas « P0 » dans le backlog — il est **MVP0**. C&amp;#39;est le premier livrable commercial, et tout le reste est conditionné à sa réussite.

== Conclusion : le Travail Invisible qui Rend Tout Possible

Dans une startup classique, le nettoyage de données est externalisé, manuel, ou ignoré. Dans cette architecture, c&amp;#39;est le **cœur du produit**. L&amp;#39;Anonymiseur est le premier employé parce que sans lui, rien ne fonctionne :

* Sans MVP0 → pas de RAG légal (MVP1)
* Sans MVP0 → pas de fine-tuning sans fuite de données (EPIC 5)
* Sans MVP0 → pas de SaaS crédible (MVP3)
* Sans MVP0 → pas de réalité augmentée en prompt
* Sans MVP0 → pas de troisième voie de contexte (SQL DDD)

Il fait le sale boulot. Il ne sera jamais cité dans les pitchs. Mais c&amp;#39;est lui qui fait tourner l&amp;#39;usine.

Et c&amp;#39;est pour ça qu&amp;#39;on l&amp;#39;embauche en premier.

== Références

* Article sur l&amp;#39;ontologie spatiale et les cercles de confiance : link:../2026/0114_gouvernance_cercles_confiance_ontologie_spatiale_alignement_llm_post.html[L&amp;#39;Ontologie Spatiale comme Mécanisme d&amp;#39;Alignement]
* Article sur la gouvernance agent Eager/Lazy : link:../2026/0108_gouvernance_agent_opencode_eager_lazy_post.html[Gouverner un Agent IA avec du AsciiDoc]
* Article sur le mécanisme Hot/Warm/Cold : link:../2026/0110_mecanisme_backup_contexte_agent_post.html[Sliding Window et Vague Froide]
* Article sur la comparaison des trois LLMs : link:../2026/0112_comparaison_kimi_glm_deepseek_long_contexte_plugin_gradle_opencode_post.html[DeepSeek-V4-Pro, Kimi K2.6, GLM-5.1]&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Le Jardin Secret du Développeur : Comment l&#39;Ontologie Spatiale Aligne les LLMs Sans Prompt Engineering</title>
            <link >https://cheroliv.com/blog/2026/0114_gouvernance_cercles_confiance_ontologie_spatiale_alignement_llm_post.html</link>
            <pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0114_gouvernance_cercles_confiance_ontologie_spatiale_alignement_llm_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_constat_le_prompt_engineering_est_un_château_de_sable&amp;quot;&amp;gt;Le Constat : le Prompt Engineering est un Château de Sable&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_les_quatre_cercles_de_confiance_une_ontologie_spatiale&amp;quot;&amp;gt;Les Quatre Cercles de Confiance : une Ontologie Spatiale&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_jardin_secret_lespace_hors_cvs&amp;quot;&amp;gt;Le Jardin Secret : l&amp;amp;#8217;Espace Hors-CVS&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel3&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_gitignore_comme_configuration_de_gouvernance&amp;quot;&amp;gt;Le &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt; comme Configuration de Gouvernance&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_mécanisme_de_snapshot&amp;quot;&amp;gt;Le Mécanisme de Snapshot&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_coffre_fort_configuration_comme_spring_cloud_config&amp;quot;&amp;gt;Le Coffre-Fort : &amp;lt;code&amp;gt;configuration/&amp;lt;/code&amp;gt; comme Spring Cloud Config&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_bibliothèque_office_comme_data_consommable&amp;quot;&amp;gt;La Bibliothèque : &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; comme Data Consommable&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_les_forges_foundry_comme_implémentation&amp;quot;&amp;gt;Les Forges : &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt; comme Implémentation&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_procontra_alignement_spatial_vs_alignement_par_prompt&amp;quot;&amp;gt;Pro/Contra : Alignement Spatial vs Alignement par Prompt&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_approche_classique_alignement_par_pré_prompt&amp;quot;&amp;gt;Approche Classique : Alignement par Pré-Prompt&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_cette_approche_alignement_par_ontologie_spatiale&amp;quot;&amp;gt;Cette Approche : Alignement par Ontologie Spatiale&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_lalgèbre_relationnelle_du_workspace_et_le_delta_observable&amp;quot;&amp;gt;L&amp;amp;#8217;Algèbre Relationnelle du Workspace et le Delta Observable&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_vecteur_composite_de_contexte_rag_pgvector_graphify&amp;quot;&amp;gt;Le Vecteur Composite de Contexte : RAG + pgvector + Graphify&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_composante_1_rag_langchain4j_postgresql_pgvector&amp;quot;&amp;gt;Composante 1 — RAG LangChain4j + PostgreSQL pgvector&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_composante_2_knowledge_graph_graphify&amp;quot;&amp;gt;Composante 2 — Knowledge Graph Graphify&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_composante_3_graphify_incrémental_épars_agrégeable_consommable&amp;quot;&amp;gt;Composante 3 — Graphify Incrémental : Épars, Agrégeable, Consommable&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_classification_rgpd_automatique_le_llm_comme_routeur&amp;quot;&amp;gt;Classification RGPD Automatique : le LLM comme Routeur&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_roadmap_de_lasciidoc_à_langgraph4j&amp;quot;&amp;gt;Roadmap : de l&amp;amp;#8217;AsciiDoc à LangGraph4j&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ce_que_cette_architecture_résout_et_ce_quelle_ne_résout_pas&amp;quot;&amp;gt;Ce que Cette Architecture Résout (et ce qu&amp;amp;#8217;elle ne Résout pas)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_conclusion_larchitecture_comme_discours&amp;quot;&amp;gt;Conclusion : l&amp;amp;#8217;Architecture comme Discours&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_références&amp;quot;&amp;gt;Références&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 20 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Le prompt engineering, c&amp;amp;#8217;est fragile. À 80 000 tokens, vos règles d&amp;amp;#8217;alignement sont noyées dans le bruit, et le LLM oublie ce que vous lui avez demandé en début de conversation. Ma solution ? Ne pas aligner par le texte, mais par l&amp;#39;&amp;lt;strong&amp;gt;espace&amp;lt;/strong&amp;gt;. J&amp;amp;#8217;ai structuré mon workspace de développement en quatre cercles de confiance concentriques — du jardin secret intime jusqu&amp;amp;#8217;aux forges publiques — et chaque cercle est une zone physique du système de fichiers. Le LLM n&amp;amp;#8217;a pas besoin qu&amp;amp;#8217;on lui rappelle les règles : le chemin du fichier les contient. Voici comment ça fonctionne, et pourquoi cette architecture d&amp;amp;#8217;alignement par l&amp;amp;#8217;espace est plus résiliente qu&amp;amp;#8217;un &amp;lt;code&amp;gt;system prompt&amp;lt;/code&amp;gt; de 500 lignes.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est un article long.&amp;lt;br&amp;gt;
Installez-vous confortablement.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;toc&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;[]&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_constat_le_prompt_engineering_est_un_château_de_sable&amp;quot;&amp;gt;Le Constat : le Prompt Engineering est un Château de Sable&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pendant trois semaines, j&amp;amp;#8217;ai développé des plugins Gradle avec Opencode, en utilisant trois LLMs différents — Kimi K2.6, GLM-5.1, et DeepSeek-V4-Pro (le seul survivant, mais c&amp;amp;#8217;est une autre histoire&amp;lt;a href=&amp;quot;0112_comparaison_kimi_glm_deepseek_long_contexte_plugin_gradle_opencode_post.html&amp;quot;&amp;gt;Déjà couverte ici.&amp;lt;/a&amp;gt;). Ma méthode de gouvernance agent&amp;lt;a href=&amp;quot;0108_gouvernance_agent_opencode_eager_lazy_post.html&amp;quot;&amp;gt;Je l&amp;amp;#8217;ai documentée en détail dans un précédent article.&amp;lt;/a&amp;gt; repose sur des fichiers AsciiDoc — &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INDEX.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PROMPT_REPRISE.adoc&amp;lt;/code&amp;gt; — qui chargent ~30 000 tokens de règles, de backlog et d&amp;amp;#8217;historique à chaque début de session.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Et malgré cette infrastructure documentaire, deux choses m&amp;amp;#8217;ont frappé :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Le LLM oublie.&amp;lt;/strong&amp;gt; Même avec les règles absolues en tête de chaque fichier EAGER, au-delà de 60 000 tokens cumulés (contexte initial + conversation), Kimi K2.6 a commencé à proposer des &amp;lt;code&amp;gt;Write&amp;lt;/code&amp;gt; écrasants sur des fichiers de configuration. GLM-5.1 a confondu un token Firebase avec un placeholder à remplacer. Les règles étaient écrites — le LLM ne les &amp;lt;strong&amp;gt;voyait&amp;lt;/strong&amp;gt; plus.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;La gouvernance elle-même devient un problème.&amp;lt;/strong&amp;gt; Après avoir implémenté le mécanisme Hot/Warm/Cold&amp;lt;a href=&amp;quot;0110_mecanisme_backup_contexte_agent_post.html&amp;quot;&amp;gt;Article sur la rotation de backup.&amp;lt;/a&amp;gt; pour éviter l&amp;amp;#8217;explosion du contexte, mes fichiers EAGER pesaient encore 1414 lignes&amp;lt;a href=&amp;quot;0111_audit_contexte_agent_post.html&amp;quot;&amp;gt;J&amp;amp;#8217;ai documenté cet audit ici.&amp;lt;/a&amp;gt;. La gouvernance — conçue pour protéger le LLM de la saturation — saturait le LLM.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;avais besoin d&amp;amp;#8217;un mécanisme d&amp;amp;#8217;alignement qui ne dépende pas du nombre de tokens dans le prompt.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La réponse : arrêter d&amp;amp;#8217;aligner par le texte, et commencer à aligner par l&amp;#39;&amp;lt;strong&amp;gt;espace&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_les_quatre_cercles_de_confiance_une_ontologie_spatiale&amp;quot;&amp;gt;Les Quatre Cercles de Confiance : une Ontologie Spatiale&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mon dossier &amp;lt;code&amp;gt;workspace/&amp;lt;/code&amp;gt; (dans &amp;lt;code&amp;gt;~/workspace/&amp;lt;/code&amp;gt;) n&amp;amp;#8217;est &amp;lt;strong&amp;gt;pas&amp;lt;/strong&amp;gt; un dépôt Git. C&amp;amp;#8217;est la racine de tout mon travail — code, documentation, formation, infrastructure. Et il est structuré en quatre zones qui ne sont pas des conventions de rangement, mais des &amp;lt;strong&amp;gt;cercles de confiance concentriques&amp;lt;/strong&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 13.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 20%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 26.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3335%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Niveau&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Label&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Zone physique&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;CVS&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Visibilité&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;0&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Jardin secret&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;workspace/&amp;lt;/code&amp;gt; racine&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Aucun&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Intime — pensée libre, pas de commit, pas de publication&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;1&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Coffre-fort&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;configuration/&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Git privé (solo)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Secrets, tokens, archive de vision. Une seule personne.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;2&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Bibliothèque&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Git privé (élargi)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Data pédagogique, SPG/SPD, schémas JSON. Cercle de confiance identifié.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;4&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Forges (publiques)&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Git public (Apache 2.0)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Code source, plugins, tests, documentation technique.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;ℹ️&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
Il n&amp;amp;#8217;y a pas de niveau 3 dans le tableau. Le niveau 3 est un niveau &amp;lt;strong&amp;gt;transitoire&amp;lt;/strong&amp;gt; : c&amp;amp;#8217;est du contenu de &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; qui a été anonymisé et est prêt à être publié en open data. Il n&amp;amp;#8217;a pas de zone physique propre — c&amp;amp;#8217;est un état de la donnée, pas un emplacement.
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Chaque niveau répond à une question précise :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Où déposer une idée qui n&amp;amp;#8217;est pas encore prête à être partagée, même avec un cercle restreint ?&amp;lt;/strong&amp;gt; → Le jardin secret. Pas de Git. Pas de pression.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Où stocker un token API sans qu&amp;amp;#8217;il fuie ?&amp;lt;/strong&amp;gt; → Le coffre-fort (&amp;lt;code&amp;gt;configuration/&amp;lt;/code&amp;gt;). Physiquement isolé. Aucun autre dépôt ne peut le référencer par erreur.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Où co-construire un catalogue de formation avec un OF pilote ?&amp;lt;/strong&amp;gt; → La bibliothèque (&amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt;). Versionné, collaboratif, mais privé.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Où industrialiser un plugin Gradle open source ?&amp;lt;/strong&amp;gt; → Les forges (&amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt;). Public, forkable, testé en CI.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Cette ontologie est &amp;lt;strong&amp;gt;consommable par un LLM&amp;lt;/strong&amp;gt;. Quand il lit un fichier dans &amp;lt;code&amp;gt;foundry/plantuml-gradle/src/&amp;lt;/code&amp;gt;, il sait implicitement : &amp;quot;je suis dans le cercle 4 — code public, tests obligatoires, pas de secrets, pas de données pédagogiques&amp;quot;. Il n&amp;amp;#8217;a pas besoin d&amp;amp;#8217;un prompt qui le lui rappelle.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_jardin_secret_lespace_hors_cvs&amp;quot;&amp;gt;Le Jardin Secret : l&amp;amp;#8217;Espace Hors-CVS&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est le concept le plus important — et le plus contre-intuitif.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La racine &amp;lt;code&amp;gt;workspace/&amp;lt;/code&amp;gt; n&amp;amp;#8217;a pas de &amp;lt;code&amp;gt;.git/&amp;lt;/code&amp;gt;. Les documents qui y vivent (&amp;lt;code&amp;gt;WORKSPACE_VISION.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WORKSPACE_AS_PRODUCT.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WORKSPACE_ORGANIZATION.adoc&amp;lt;/code&amp;gt; — et celui que vous lisez en ce moment, qui en est issu) ne sont pas destinés à être versionnés, partagés, ou même relus par quelqu&amp;amp;#8217;un d&amp;amp;#8217;autre que moi. Ce sont des &amp;lt;strong&amp;gt;pensées en germination&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock important&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-important&amp;quot; title=&amp;quot;❗&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le jardin secret est &amp;lt;strong&amp;gt;out-of-CVS&amp;lt;/strong&amp;gt; par nature. L&amp;amp;#8217;absence de versionnage est la condition de la liberté de penser. On n&amp;amp;#8217;y écrit pas pour être lu — on y écrit pour clarifier sa propre vision.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mais cette liberté a un coût : un &amp;lt;code&amp;gt;rm&amp;lt;/code&amp;gt; accidentel, et c&amp;amp;#8217;est des mois de réflexion stratégique qui disparaissent. La solution n&amp;amp;#8217;est pas de versionner le jardin (ce serait le détruire) — c&amp;amp;#8217;est de le &amp;lt;strong&amp;gt;mirrorer&amp;lt;/strong&amp;gt; dans le cercle le plus restreint.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_le_gitignore_comme_configuration_de_gouvernance&amp;quot;&amp;gt;Le &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt; comme Configuration de Gouvernance&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;À la racine de &amp;lt;code&amp;gt;workspace/&amp;lt;/code&amp;gt;, un fichier &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt; minimal déclare la &amp;lt;strong&amp;gt;politique d&amp;amp;#8217;historisation&amp;lt;/strong&amp;gt; des fichiers du jardin secret :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;.goosehints
.goose&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt; n&amp;amp;#8217;a pas de fonction Git classique (il n&amp;amp;#8217;y a pas de &amp;lt;code&amp;gt;.git/&amp;lt;/code&amp;gt; à la racine). Il agit comme un &amp;lt;strong&amp;gt;fichier de configuration de gouvernance&amp;lt;/strong&amp;gt; qui répond à une question précise : &amp;lt;strong&amp;gt;quels artefacts du jardin secret méritent d&amp;amp;#8217;être historisés, et lesquels sont purement transitoires ?&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Les fichiers listés dans &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;.goosehints&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.goose&amp;lt;/code&amp;gt; — sont des artefacts éphémères générés par les agents. Pas de valeur stratégique. Pas d&amp;amp;#8217;historisation.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Les fichiers &amp;lt;code&amp;gt;.adoc&amp;lt;/code&amp;gt; de la racine — &amp;lt;code&amp;gt;WORKSPACE_VISION.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WORKSPACE_ORGANIZATION.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WORKSPACE_AS_PRODUCT.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WHAT_THE_GAMES_BEEN_MISSING.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;depots_implementes_strategie.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;synthese-LLMs-long-contexte.adoc&amp;lt;/code&amp;gt; — ne sont &amp;lt;strong&amp;gt;pas&amp;lt;/strong&amp;gt; dans le &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt;. Ce sont les artefacts à historiser.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt; est le &amp;lt;strong&amp;gt;schéma de gouvernance&amp;lt;/strong&amp;gt; : tout ce qui n&amp;amp;#8217;y est pas listé est un candidat au snapshot. Et le LLM, en lisant ce fichier, sait exactement ce qui doit être archivé et ce qui peut être ignoré — sans qu&amp;amp;#8217;on ait besoin de le lui rappeler dans un prompt.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_le_mécanisme_de_snapshot&amp;quot;&amp;gt;Le Mécanisme de Snapshot&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ai créé &amp;lt;code&amp;gt;configuration/vision-archive/&amp;lt;/code&amp;gt; : des snapshots datés de tous les &amp;lt;code&amp;gt;.adoc&amp;lt;/code&amp;gt; de la racine, commités dans le dépôt privé &amp;lt;code&amp;gt;configuration/&amp;lt;/code&amp;gt;. Chaque session de brainstorming produit un snapshot :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;DATE=$(date +%Y-%m-%d)
mkdir -p /home/cheroliv/workspace/configuration/vision-archive/$DATE
cp /home/cheroliv/workspace/*.adoc /home/cheroliv/workspace/configuration/vision-archive/$DATE/
cd /home/cheroliv/workspace/configuration &amp;amp;amp;&amp;amp;amp; git add vision-archive/ &amp;amp;amp;&amp;amp;amp; \
  git commit -m &amp;quot;vision-archive: snapshot $DATE&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La procédure est déclenchée en fin de session par le LLM lui-même, qui exécute cette tâche globale de routage. Chaque snapshot capture l&amp;amp;#8217;état complet de la pensée stratégique à un instant T.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;historique Git de &amp;lt;code&amp;gt;configuration/&amp;lt;/code&amp;gt; devient la &amp;lt;strong&amp;gt;biographie de ma pensée stratégique&amp;lt;/strong&amp;gt;. Je peux faire un &amp;lt;code&amp;gt;git log&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;vision-archive/&amp;lt;/code&amp;gt; et voir l&amp;amp;#8217;évolution de ma vision, session par session, date par date.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Exemple réel de l&amp;amp;#8217;historique après une journée de travail :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;$ git -C configuration log --oneline -- vision-archive/
1089d1b vision-archive: fin de session finale 2026-05-03
6b21eaf vision-archive: fin de session 2026-05-03-1300
1690f82 vision-archive: post-article 2026-05-03
28e6593 vision-archive: post-migration 2026-05-03
3707b78 vision-archive: snapshot 2026-05-03 — jardin secret initial&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Cinq snapshots en une journée. Chacun est un point de restauration. Chacun est un jalon dans la genèse de la stratégie.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le dossier &amp;lt;code&amp;gt;configuration/vision-archive/latest/&amp;lt;/code&amp;gt; contient en permanence une &amp;lt;strong&amp;gt;copie de travail&amp;lt;/strong&amp;gt; du dernier snapshot, servant de référence rapide sans avoir à naviguer dans l&amp;amp;#8217;historique Git.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Et pour le LLM, c&amp;amp;#8217;est un &amp;lt;strong&amp;gt;oracle de cohérence&amp;lt;/strong&amp;gt; : quand il observe une contradiction entre l&amp;amp;#8217;implémentation actuelle et la vision archivée à une date antérieure, il peut la signaler.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_coffre_fort_configuration_comme_spring_cloud_config&amp;quot;&amp;gt;Le Coffre-Fort : &amp;lt;code&amp;gt;configuration/&amp;lt;/code&amp;gt; comme Spring Cloud Config&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;configuration/&amp;lt;/code&amp;gt; ne contient pas que l&amp;amp;#8217;archive de la vision. Sa fonction première — et future — est d&amp;amp;#8217;être un &amp;lt;strong&amp;gt;serveur Spring Cloud Config&amp;lt;/strong&amp;gt;. Tous les secrets, tokens, credentials, et descripteurs d&amp;amp;#8217;infrastructure vivent ici, dans un dépôt Git privé accessible au seul propriétaire.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pourquoi un dépôt séparé plutôt qu&amp;amp;#8217;un fichier &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; dans chaque projet ?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Push accidentel d&amp;amp;#8217;un secret&amp;lt;/strong&amp;gt; : impossible. Les secrets sont dans un dépôt privé que les projets publics ne peuvent pas référencer par erreur.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Audit&amp;lt;/strong&amp;gt; : l&amp;amp;#8217;historique Git donne la piste de chaque modification de configuration. Qui a changé quoi, quand, avec quel hash SHA.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Rollback&amp;lt;/strong&amp;gt; : &amp;lt;code&amp;gt;git revert&amp;lt;/code&amp;gt; sur une configuration cassée. Instantané, sans backup manuel.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_la_bibliothèque_office_comme_data_consommable&amp;quot;&amp;gt;La Bibliothèque : &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; comme Data Consommable&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; est le pendant documentaire du travail de développement. Il contient les articles de blog, les spécifications techniques, les supports de formation (38 répertoires de cours FPA, SPG/SPD, schémas JSON, taxonomies Bloom/Harrow/Krathwohl) — tout ce qui constitue le &amp;lt;strong&amp;gt;matériau pédagogique&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mais &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; n&amp;amp;#8217;est pas qu&amp;amp;#8217;un tiroir à docs. C&amp;amp;#8217;est une &amp;lt;strong&amp;gt;source de données structurée&amp;lt;/strong&amp;gt; que les plugins Gradle de &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt; consomment. Un article de blog dans &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; est une entrée qu&amp;amp;#8217;un plugin transformera en HTML. Un SPG AsciiDoc dans &amp;lt;code&amp;gt;office/metiers/FPA/&amp;lt;/code&amp;gt; est un artefact qu&amp;amp;#8217;un orchestrateur parsera pour générer des slides, des quiz, et des capsules vidéo.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Et le &amp;lt;code&amp;gt;build.gradle.kts&amp;lt;/code&amp;gt; à la racine de &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; n&amp;amp;#8217;est pas du code métier — c&amp;amp;#8217;est un &amp;lt;strong&amp;gt;script de consommation de l&amp;amp;#8217;écosystème de plugins&amp;lt;/strong&amp;gt;. Il dit : &amp;quot;voici les plugins Gradle que j&amp;amp;#8217;utilise, voici le contexte de mon workspace&amp;quot;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_les_forges_foundry_comme_implémentation&amp;quot;&amp;gt;Les Forges : &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt; comme Implémentation&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt; contient le &amp;lt;strong&amp;gt;code industrialisé&amp;lt;/strong&amp;gt;. 54 dépôts Git, dont 7 actuellement gouvernés par des &amp;lt;code&amp;gt;.agents/&amp;lt;/code&amp;gt;. C&amp;amp;#8217;est ici que la vision devient exécutable — plugins Gradle, CI/CD, tests JUnit5 + Cucumber.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La relation avec &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; est bidirectionnelle :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt; : les données pédagogiques sont la matière première que les plugins consomment.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; : les plugins produisent de la data qui enrichit &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; — le &amp;lt;code&amp;gt;graph.json&amp;lt;/code&amp;gt; de graphify-gradle, les decks slider compilés, les rapports de build.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_procontra_alignement_spatial_vs_alignement_par_prompt&amp;quot;&amp;gt;Pro/Contra : Alignement Spatial vs Alignement par Prompt&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Comparons les deux approches.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_approche_classique_alignement_par_pré_prompt&amp;quot;&amp;gt;Approche Classique : Alignement par Pré-Prompt&amp;lt;/h3&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 20%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 80%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅ Pro&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;❌ Contra&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Simple à mettre en œuvre. Un bloc de texte dans le system prompt.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Fragile au contexte long&amp;lt;/strong&amp;gt; : la règle est noyée après 80K tokens.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Fonctionne pour des règles générales (ton, format).&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Non vérifiable&amp;lt;/strong&amp;gt; : rien n&amp;amp;#8217;empêche le LLM de violer la règle.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Pas besoin de repenser l&amp;amp;#8217;architecture du projet.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Non transférable&amp;lt;/strong&amp;gt; : chaque repo redéclare les règles.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Purement déclaratif&amp;lt;/strong&amp;gt; : le LLM sait qu&amp;amp;#8217;il &amp;lt;strong&amp;gt;devrait&amp;lt;/strong&amp;gt;, mais rien ne l&amp;amp;#8217;empêche.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_cette_approche_alignement_par_ontologie_spatiale&amp;quot;&amp;gt;Cette Approche : Alignement par Ontologie Spatiale&amp;lt;/h3&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 20%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 80%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅ Pro&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;❌ Contra&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Résilient au contexte long&amp;lt;/strong&amp;gt; : la règle est dans le chemin du fichier, pas dans un prompt lointain.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Coût d&amp;amp;#8217;infrastructure initial&amp;lt;/strong&amp;gt; : structurer le workspace en cercles prend du temps.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Vérifiable mécaniquement&amp;lt;/strong&amp;gt; : un secret dans &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt; est détectable par &amp;lt;code&amp;gt;git check-ignore&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Nécessite discipline&amp;lt;/strong&amp;gt; : un nouveau contributeur doit comprendre les cercles.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Transférable&amp;lt;/strong&amp;gt; : un &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt; standard expose les cercles à tout nouveau projet.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Ne couvre que les contraintes spatiales&amp;lt;/strong&amp;gt; — le code style reste dans le prompt.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Sécurité par conception&amp;lt;/strong&amp;gt; : un &amp;lt;code&amp;gt;git push&amp;lt;/code&amp;gt; depuis &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt; ne peut pas exposer &amp;lt;code&amp;gt;configuration/&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Consommable par des agents non-LLM&amp;lt;/strong&amp;gt; : un orchestrateur Gradle peut router selon le cercle.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le gain principal n&amp;amp;#8217;est pas défensif (sécurité, visibilité) — il est &amp;lt;strong&amp;gt;créatif&amp;lt;/strong&amp;gt;. Quand le LLM travaille dans un espace structuré par une ontologie, il peut faire ce qu&amp;amp;#8217;aucun prompt ne lui permet : &amp;lt;strong&amp;gt;observer le delta&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_lalgèbre_relationnelle_du_workspace_et_le_delta_observable&amp;quot;&amp;gt;L&amp;amp;#8217;Algèbre Relationnelle du Workspace et le Delta Observable&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Quand le LLM parcourt &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt;, il dispose d&amp;amp;#8217;un &amp;lt;strong&amp;gt;treillis de données structurées&amp;lt;/strong&amp;gt; : nœuds (plugins, fichiers, tests, dépendances), arêtes typées (&amp;lt;code&amp;gt;import&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;depends_on&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;generates&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;tests&amp;lt;/code&amp;gt;), relations de composition et d&amp;amp;#8217;ordre (&amp;lt;code&amp;gt;training-gradle&amp;lt;/code&amp;gt; extrait le référentiel → &amp;lt;code&amp;gt;slider-gradle&amp;lt;/code&amp;gt; génère les slides → &amp;lt;code&amp;gt;capsule-gradle&amp;lt;/code&amp;gt; monte la vidéo).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Cette algèbre n&amp;amp;#8217;est écrite nulle part en clair — mais elle est &amp;lt;strong&amp;gt;observable&amp;lt;/strong&amp;gt;. Chaque &amp;lt;code&amp;gt;build.gradle.kts&amp;lt;/code&amp;gt; expose des dépendances. Chaque &amp;lt;code&amp;gt;INDEX.adoc&amp;lt;/code&amp;gt; expose des références croisées.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le LLM observe cette algèbre et détecte le &amp;lt;strong&amp;gt;delta&amp;lt;/strong&amp;gt; : l&amp;amp;#8217;écart entre ce que le système sait déjà produire et ce que la vision décrit.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;À partir de ce delta, il peut définir des &amp;lt;strong&amp;gt;cartographies d&amp;amp;#8217;experts métiers&amp;lt;/strong&amp;gt; — CDA (Concepteur Développeur d&amp;amp;#8217;Applications, Kotlin/Gradle/JHipster) et FPA (Formateur Professionnel d&amp;amp;#8217;Adultes, Pédagogie/Qualiopi/Bloom) — et identifier ce qui manque pour chaque expert.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;Expert CDA (Kotlin/Gradle/JHipster)
  ├── Plugins : jhipster-gradle-plugins, plantuml-gradle,
  │   codebase-gradle
  ├── Delta : pas encore de SPG CDA formalisé,
  │   pas de fine-tuning expert CDA

Expert FPA (Pédagogie/Qualiopi/Bloom)
  ├── Plugins : training-gradle, slider-gradle,
  │   school-backoffice/forms, capsule-gradle
  ├── Matériel : 38 modules cours, SPG/SPD, taxonomies
  └── Delta : parser AsciiDoc→JSON à créer,
      orchestrateur à coder&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le LLM n&amp;amp;#8217;a pas besoin qu&amp;amp;#8217;on lui dise quoi faire. Le delta émerge de la structure.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_vecteur_composite_de_contexte_rag_pgvector_graphify&amp;quot;&amp;gt;Le Vecteur Composite de Contexte : RAG + pgvector + Graphify&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;algèbre relationnelle n&amp;amp;#8217;est pas une construction théorique. Elle est &amp;lt;strong&amp;gt;matérialisée&amp;lt;/strong&amp;gt; par trois composantes qui forment un &amp;lt;strong&amp;gt;vecteur composite de contexte&amp;lt;/strong&amp;gt; pour le LLM.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_composante_1_rag_langchain4j_postgresql_pgvector&amp;quot;&amp;gt;Composante 1 — RAG LangChain4j + PostgreSQL pgvector&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ai déjà LangChain4j en production dans deux plugins : &amp;lt;code&amp;gt;slider-gradle&amp;lt;/code&amp;gt; (4 providers LLM) et &amp;lt;code&amp;gt;plantuml-gradle&amp;lt;/code&amp;gt; (7 providers). Les embeddings ONNX (AllMiniLmL6V2) indexent les données de &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; et le code source de &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt; dans PostgreSQL + pgvector.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce RAG opère sur deux dimensions :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Dimension data&amp;lt;/strong&amp;gt; : les documents &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; (SPG, articles, formations, schémas JSON)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Dimension code&amp;lt;/strong&amp;gt; : les codebases &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt; (sources Kotlin, tests Cucumber, AGENT.adoc)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;intersection couvre à la fois le &amp;lt;strong&amp;gt;quoi&amp;lt;/strong&amp;gt; (le domaine métier) et le &amp;lt;strong&amp;gt;comment&amp;lt;/strong&amp;gt; (l&amp;amp;#8217;implémentation).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_composante_2_knowledge_graph_graphify&amp;quot;&amp;gt;Composante 2 — Knowledge Graph Graphify&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Graphify est intégré dans &amp;lt;code&amp;gt;plantuml-gradle&amp;lt;/code&amp;gt; (109 tests, 380/380 PASS) et produit un &amp;lt;code&amp;gt;graph.json&amp;lt;/code&amp;gt; — un knowledge graph structuré avec nœuds, arêtes, et communautés détectées automatiquement.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Contrairement au RAG qui opère par similarité vectorielle (flou), le knowledge graph opère par &amp;lt;strong&amp;gt;relations exactes&amp;lt;/strong&amp;gt; (déterministe) : &amp;lt;code&amp;gt;graphify query&amp;lt;/code&amp;gt; pour les interrogations sémantiques (~50 tokens), &amp;lt;code&amp;gt;graphify path&amp;lt;/code&amp;gt; pour naviguer, &amp;lt;code&amp;gt;graphify explain&amp;lt;/code&amp;gt; pour expliquer.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_composante_3_graphify_incrémental_épars_agrégeable_consommable&amp;quot;&amp;gt;Composante 3 — Graphify Incrémental : Épars, Agrégeable, Consommable&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est la décision architecturale clé.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Graphify ne doit pas vivre dans un dépôt unique. Il doit vivre de manière &amp;lt;strong&amp;gt;éparse&amp;lt;/strong&amp;gt; dans chaque plugin :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Chaque plugin&amp;lt;/strong&amp;gt; embarque une tâche Gradle &amp;lt;code&amp;gt;updateKnowledgeGraph&amp;lt;/code&amp;gt; qui appelle Graphify &amp;lt;strong&amp;gt;sur son propre scope&amp;lt;/strong&amp;gt; et produit un &amp;lt;code&amp;gt;graph.json&amp;lt;/code&amp;gt; local.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Le build script de &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt;&amp;lt;/strong&amp;gt; consomme &amp;lt;code&amp;gt;graphify-gradle&amp;lt;/code&amp;gt; avec &amp;lt;code&amp;gt;rootDir = /home/cheroliv/workspace&amp;lt;/code&amp;gt; et produit un &amp;lt;code&amp;gt;graph.json&amp;lt;/code&amp;gt; &amp;lt;strong&amp;gt;global&amp;lt;/strong&amp;gt; qui agrège les graphes locaux.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Le RAG de chaque plugin&amp;lt;/strong&amp;gt; injecte le &amp;lt;code&amp;gt;graph.json&amp;lt;/code&amp;gt; global comme &amp;lt;strong&amp;gt;filtre de contexte&amp;lt;/strong&amp;gt; pour les requêtes LLM.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;TÂCHE GRADLE (dans chaque plugin)
    ↓
graphify → graph.json (scope local)
    ↓
office/build.gradle.kts → graph.json (scope global)
    ↓
RAG pgvector (dans slider, plantuml, codebase...)
    ↓  ← injection du graph.json comme filtre
LLM (deepseek-v4-pro)
    ↓  ← observation algèbre relationnelle
    ↓  ← détection delta vs cartographies experts
PRIORISATION → prochaine tâche&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Résultat : le LLM ne cherche pas dans le vide — il navigue dans un espace structuré par le knowledge graph. Une requête sur &amp;quot;génère un diagramme&amp;quot; sait atteindre les nœuds pertinents du graphe.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_classification_rgpd_automatique_le_llm_comme_routeur&amp;quot;&amp;gt;Classification RGPD Automatique : le LLM comme Routeur&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;ontologie spatiale ne se contente pas d&amp;amp;#8217;aligner le LLM — elle lui donne une &amp;lt;strong&amp;gt;grille de classification RGPD&amp;lt;/strong&amp;gt; pour router chaque donnée vers sa zone légitime.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 12.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 37.5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Critère&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Détection LLM&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Action&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Niveau max&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Donnée personnelle (nom, email, IP)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Pattern &amp;lt;code&amp;gt;@&amp;lt;/code&amp;gt;, IP, noms propres&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Anonymiser → &amp;lt;code&amp;gt;[OF_PILOTE]&amp;lt;/code&amp;gt; ou router niveau 2&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;2&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Token / Secret / Credential&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Pattern &amp;lt;code&amp;gt;sk-&amp;amp;#8230;&amp;amp;#8203;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ghp_&amp;amp;#8230;&amp;amp;#8203;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ya29&amp;amp;#8230;&amp;amp;#8203;&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Router → &amp;lt;code&amp;gt;configuration/&amp;lt;/code&amp;gt;. Référencer par &amp;lt;code&amp;gt;${VAR}&amp;lt;/code&amp;gt; dans le code.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;1&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;URL interne&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Contient &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;, IP privée&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Anonymiser → &amp;lt;code&amp;gt;${API_URL}&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;2&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Donnée pédagogique (SPG, cours)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Structure Bloom/Qualiopi&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Router → &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; (niveau 2). Double version si export.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;3&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Code source / test&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Extension &amp;lt;code&amp;gt;.kt&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.kts&amp;lt;/code&amp;gt; dans &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Router → &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt;. Vérifier absence de secrets.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;4&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;En fin de session, le LLM exécute une &amp;lt;strong&amp;gt;tâche globale&amp;lt;/strong&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Lecture du &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt; racine pour identifier les artefacts éphémères (à exclure du snapshot) vs les artefacts stratégiques (à historiser)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Inventaire de tous les fichiers &amp;lt;code&amp;gt;.adoc&amp;lt;/code&amp;gt; de la racine &amp;lt;code&amp;gt;workspace/&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Filtrage : exclusion des fichiers listés dans &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt;, inclusion de tous les autres&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Copie dans &amp;lt;code&amp;gt;configuration/vision-archive/$DATE/&amp;lt;/code&amp;gt; et mise à jour du symlink &amp;lt;code&amp;gt;latest/&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Commit dans le dépôt &amp;lt;code&amp;gt;configuration/&amp;lt;/code&amp;gt; avec un message structuré&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Classification RGPD automatique de chaque fichier modifié (tous cercles)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Routage : données &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; → commit privé, code &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;./gradlew check&amp;lt;/code&amp;gt;, configuration → commit&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Rapport structuré avec alertes RGPD et confirmation d&amp;amp;#8217;archivage&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt; racine n&amp;amp;#8217;est pas un fichier de configuration Git — c&amp;amp;#8217;est un &amp;lt;strong&amp;gt;fichier de gouvernance de l&amp;amp;#8217;historisation&amp;lt;/strong&amp;gt;. Il définit le schéma que le LLM consomme pour décider quels fichiers du jardin secret entrent dans la biographie stratégique et lesquels sont jetables.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le LLM n&amp;amp;#8217;est plus un simple générateur de texte. Il est le &amp;lt;strong&amp;gt;gestionnaire d&amp;amp;#8217;information&amp;lt;/strong&amp;gt; de l&amp;amp;#8217;écosystème — producteur, classifieur, routeur.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_roadmap_de_lasciidoc_à_langgraph4j&amp;quot;&amp;gt;Roadmap : de l&amp;amp;#8217;AsciiDoc à LangGraph4j&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Aujourd&amp;amp;#8217;hui, cette gouvernance est &amp;lt;strong&amp;gt;déterministe&amp;lt;/strong&amp;gt; : le LLM applique une procédure décrite dans des fichiers AsciiDoc. C&amp;amp;#8217;est la &amp;lt;strong&amp;gt;phase 1&amp;lt;/strong&amp;gt; — le prompt engineering avec mémoire LLM.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La &amp;lt;strong&amp;gt;phase 2&amp;lt;/strong&amp;gt; extraira chaque étape de la procédure dans une &amp;lt;strong&amp;gt;tâche Gradle typée&amp;lt;/strong&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;./gradlew endSessionWorkspace    → snapshot vision-archive
./gradlew endSessionProject      → archive .agents/
./gradlew endSessionReport       → rapport multi-zones&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La &amp;lt;strong&amp;gt;phase 3&amp;lt;/strong&amp;gt; modélisera le processus de fin de session comme un &amp;lt;strong&amp;gt;graphe d&amp;amp;#8217;état&amp;lt;/strong&amp;gt; avec &amp;lt;a href=&amp;quot;https://github.com/langgraph4j/langgraph4j&amp;quot;&amp;gt;LangGraph4j&amp;lt;/a&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;[Start] → [Inventaire fichiers modifiés]
       → [Classification RGPD] (nœud ONNX)
       → [Branchement par cercle]
            ├→ cercle 0 → snapshot → commit
            ├→ cercle 2 → anonymisation → commit
            ├→ cercle 4 → archive → commit
            └→ cercle 1 → commit configuration/
       → [Rapport] → [End]&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce graphe sera versionné dans la CI/CD, exécuté par Gradle, configuré via les GitHub Secrets des plugins. Le LLM n&amp;amp;#8217;aura plus à décider du routage — le graphe le fera.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_ce_que_cette_architecture_résout_et_ce_quelle_ne_résout_pas&amp;quot;&amp;gt;Ce que Cette Architecture Résout (et ce qu&amp;amp;#8217;elle ne Résout pas)&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock caution&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-caution&amp;quot; title=&amp;quot;🔒&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;ontologie spatiale ne couvre pas tout. Les conventions de code style, le nommage, les choix de design architectural — tout ça reste dans le prompt. Ce que l&amp;amp;#8217;ontologie spatiale résout, c&amp;amp;#8217;est la &amp;lt;strong&amp;gt;couche de sécurité et de visibilité&amp;lt;/strong&amp;gt; : où chaque octet doit vivre, et qui peut le voir.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Voici ce qu&amp;amp;#8217;elle apporte concrètement :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Pas de &amp;lt;code&amp;gt;git push&amp;lt;/code&amp;gt; accidentel d&amp;amp;#8217;un secret&amp;lt;/strong&amp;gt; : les secrets sont dans &amp;lt;code&amp;gt;configuration/&amp;lt;/code&amp;gt; (cercle 1). Les projets publics sont dans &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt; (cercle 4). Aucun chemin ne traverse les deux.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Pas de code métier dans la data&amp;lt;/strong&amp;gt; : &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; contient des &amp;lt;code&amp;gt;.adoc&amp;lt;/code&amp;gt;, des YAML, des JSON Schemas — mais pas de &amp;lt;code&amp;gt;.kt&amp;lt;/code&amp;gt;. Le &amp;lt;code&amp;gt;build.gradle.kts&amp;lt;/code&amp;gt; qui y vit est un script de consommation, pas du code métier.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Pas de pensée stratégique exposée&amp;lt;/strong&amp;gt; : les documents de vision vivent dans le jardin secret (racine hors-CVS). Les snapshots sont dans &amp;lt;code&amp;gt;configuration/&amp;lt;/code&amp;gt; (coffre-fort privé). Personne, même en cercle de confiance élargi, ne lit la genèse de la stratégie.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Auto-priorisation&amp;lt;/strong&amp;gt; : le LLM observe le delta entre l&amp;amp;#8217;algèbre relationnelle (ce qui existe) et les cartographies d&amp;amp;#8217;experts (ce qui est nécessaire). La prochaine tâche de développement émerge de ce delta.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_conclusion_larchitecture_comme_discours&amp;quot;&amp;gt;Conclusion : l&amp;amp;#8217;Architecture comme Discours&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Je ne mets pas de manifeste politique dans le footer de mon site. Je ne mets pas de règles éthiques dans mes prompts. L&amp;amp;#8217;alignement n&amp;amp;#8217;est pas dans le texte — il est dans le &amp;lt;strong&amp;gt;système de fichiers&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Quand un LLM travaille dans cet espace, il ne peut pas fuiter un secret (le chemin l&amp;amp;#8217;en empêche). Il ne peut pas confondre une donnée pédagogique avec du code source (la zone physique est différente). Il ne peut pas oublier une règle de sécurité à 80 000 tokens — parce que la règle n&amp;amp;#8217;est pas dans le prompt, elle est dans le &amp;lt;code&amp;gt;workspace/&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;configuration/&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;office/&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;foundry/&amp;lt;/code&amp;gt; que chaque lecture de fichier réactive.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est le principe de la &amp;lt;strong&amp;gt;secure by design&amp;lt;/strong&amp;gt; appliqué à l&amp;amp;#8217;alignement agent : ne pas demander au LLM de se souvenir des règles. Faire en sorte que l&amp;amp;#8217;architecture rende l&amp;amp;#8217;erreur structurellement impossible.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Et au passage, ça donne au LLM ce qu&amp;amp;#8217;aucun prompt ne peut lui donner : la capacité de &amp;lt;strong&amp;gt;percevoir&amp;lt;/strong&amp;gt; où il est, ce qui existe, ce qui manque — et d&amp;amp;#8217;en déduire ce qu&amp;amp;#8217;il doit faire.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_références&amp;quot;&amp;gt;Références&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Article sur la gouvernance agent Eager/Lazy : &amp;lt;a href=&amp;quot;../2026/0108_gouvernance_agent_opencode_eager_lazy_post.html&amp;quot;&amp;gt;Gouverner un Agent IA avec du AsciiDoc&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Article sur le mécanisme Hot/Warm/Cold : &amp;lt;a href=&amp;quot;../2026/0110_mecanisme_backup_contexte_agent_post.html&amp;quot;&amp;gt;Sliding Window et Vague Froide&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Article sur l&amp;amp;#8217;audit de contexte : &amp;lt;a href=&amp;quot;../2026/0111_audit_contexte_agent_post.html&amp;quot;&amp;gt;Quand Votre Propre Gouvernance Devient le Probleme&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Article sur la comparaison des trois LLMs : &amp;lt;a href=&amp;quot;../2026/0112_comparaison_kimi_glm_deepseek_long_contexte_plugin_gradle_opencode_post.html&amp;quot;&amp;gt;DeepSeek-V4-Pro, Kimi K2.6, GLM-5.1&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Migration Supabase → Firebase : Brancher un Formulaire de Contact sur Firestore Sans Backend</title>
            <link >https://cheroliv.com/blog/2026/0113_integration_firebase_contact_form_post.html</link>
            <pubDate>Wed, 29 Apr 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0113_integration_firebase_contact_form_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_scène_un_formulaire_qui_ne_stocke_rien&amp;quot;&amp;gt;La scène : un formulaire qui ne stocke rien&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_lhéritage_supabase&amp;quot;&amp;gt;L&amp;amp;#8217;héritage Supabase&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_double_soumission_fantôme&amp;quot;&amp;gt;La double soumission fantôme&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pourquoi_firebase_plutôt_que_supabase&amp;quot;&amp;gt;Pourquoi Firebase plutôt que Supabase ?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_phase_1_créer_le_projet_firebase&amp;quot;&amp;gt;Phase 1 : Créer le projet Firebase&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_initialisation&amp;quot;&amp;gt;Initialisation&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_règles_de_sécurité_firestore&amp;quot;&amp;gt;Règles de sécurité Firestore&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_phase_2_réécrire_le_javascript_de_soumission&amp;quot;&amp;gt;Phase 2 : Réécrire le JavaScript de soumission&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_dépendance_window_firebase&amp;quot;&amp;gt;La dépendance &amp;lt;code&amp;gt;window.&amp;lt;em&amp;gt;FIREBASE&amp;lt;/em&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_nouveau_contact_js&amp;quot;&amp;gt;Le nouveau &amp;lt;code&amp;gt;contact.js&amp;lt;/code&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_phase_3_nettoyer_le_code_mort_supabase&amp;quot;&amp;gt;Phase 3 : Nettoyer le code mort Supabase&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_phase_4_configurer_le_footer&amp;quot;&amp;gt;Phase 4 : Configurer le footer&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_phase_5_architecture_finale&amp;quot;&amp;gt;Phase 5 : Architecture finale&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ce_que_cette_migration_dit_du_dogfooding&amp;quot;&amp;gt;Ce que cette migration dit du dogfooding&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_récapitulatif_des_modifications&amp;quot;&amp;gt;Récapitulatif des modifications&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_prochaines_étapes_backlog&amp;quot;&amp;gt;Prochaines étapes (backlog)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_références&amp;quot;&amp;gt;Références&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 12 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Pendant des mois, le formulaire de contact de ce site a tourné sur un mock JavaScript — une promesse à 85 % de succès, un faux Firestore, zéro données stockées. Le plan initial prévoyait un backend Supabase avec Google Apps Script pour les notifications mail. Abandonné. Aujourd&amp;amp;#8217;hui, je raconte la migration vers Firebase Firestore : création du projet, règles de sécurité, réécriture du JS, nettoyage du code mort Supabase. Et pourquoi ce choix dit quelque chose de plus large sur la philosophie de développement.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;toc&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;[]&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_scène_un_formulaire_qui_ne_stocke_rien&amp;quot;&amp;gt;La scène : un formulaire qui ne stocke rien&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce site est généré par JBake, mon plugin Gradle &amp;lt;code&amp;gt;bakery&amp;lt;/code&amp;gt;. Il est 100 % statique — pas de backend, pas de base de données. Sauf que j&amp;amp;#8217;ai un formulaire de contact. La page &amp;lt;code&amp;gt;contact.html&amp;lt;/code&amp;gt; existe, le HTML est prêt (champs nom, email, téléphone, sujet, message, validation HTML5, honeypot anti-spam), les styles Bootstrap sont en place. Visuellement, tout est parfait.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Sauf qu&amp;amp;#8217;à la soumission, rien ne se passe.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript hljs&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;const firebaseMock = new Promise((resolve, reject) =&amp;amp;gt; {
    setTimeout(() =&amp;amp;gt; {
        if (Math.random() &amp;amp;lt; 0.85) {
            resolve({ status: 201, message: &amp;#39;Message stored in Firestore.&amp;#39; });
        } else {
            reject({ status: 500, message: &amp;#39;Firestore write failed.&amp;#39; });
        }
    }, 1500);
});&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un mock. Une promesse qui fait semblant. L&amp;amp;#8217;utilisateur voit un spinner, puis un message « Message envoyé avec succès ! ». Mais les données partent dans le vide. Aucun message n&amp;amp;#8217;est stocké nulle part.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La situation est pire qu&amp;amp;#8217;un formulaire cassé — c&amp;amp;#8217;est un formulaire qui ment.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_lhéritage_supabase&amp;quot;&amp;gt;L&amp;amp;#8217;héritage Supabase&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le plan initial, documenté dans &amp;lt;code&amp;gt;content/draft/integration_formulaire_contact_supabase.adoc&amp;lt;/code&amp;gt;, prévoyait :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Une base Supabase avec table &amp;lt;code&amp;gt;contacts&amp;lt;/code&amp;gt; et Row Level Security&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Une RPC &amp;lt;code&amp;gt;handle_contact_form&amp;lt;/code&amp;gt; côté serveur&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Un trigger SQL appelant un webhook Google Apps Script&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Google Apps Script qui envoie un mail Gmail de notification&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le code JavaScript correspondant existe encore dans &amp;lt;code&amp;gt;script.js&amp;lt;/code&amp;gt;. Il y a une classe &amp;lt;code&amp;gt;SupabaseManager&amp;lt;/code&amp;gt; qui initialise un client Supabase avec des variables globales &amp;lt;code&amp;gt;SUPABASE_URL&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;SUPABASE_KEY&amp;lt;/code&amp;gt;, et une classe &amp;lt;code&amp;gt;ContactFormHandler&amp;lt;/code&amp;gt; qui écoute l&amp;amp;#8217;événement submit du formulaire et appelle &amp;lt;code&amp;gt;SupabaseManager.submitContactForm()&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Problème : ces variables globales ne sont plus injectées dans le footer. Le &amp;lt;code&amp;gt;&amp;amp;lt;script src=&amp;quot;supabase-js&amp;quot;&amp;amp;gt;&amp;lt;/code&amp;gt; a été retiré. Le code appelle &amp;lt;code&amp;gt;supabase.createClient()&amp;lt;/code&amp;gt; sur une variable &amp;lt;code&amp;gt;supabase&amp;lt;/code&amp;gt; qui n&amp;amp;#8217;existe plus. Donc :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;console.error : &amp;#39;Supabase client library (supabase-js) is not loaded.&amp;#39;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Non seulement les données ne sont pas stockées, mais le code de soumission est mort.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_la_double_soumission_fantôme&amp;quot;&amp;gt;La double soumission fantôme&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pour empirer les choses, il y a une &amp;lt;strong&amp;gt;concurrence silencieuse&amp;lt;/strong&amp;gt; entre deux handlers sur le même formulaire :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;contact.js&amp;lt;/code&amp;gt; écoute le submit, appelle le mock Firebase&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;script.js&amp;lt;/code&amp;gt; — via &amp;lt;code&amp;gt;ContactFormHandler&amp;lt;/code&amp;gt; — écoute aussi le submit, appelle &amp;lt;code&amp;gt;SupabaseManager&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Les deux font &amp;lt;code&amp;gt;event.preventDefault() + event.stopPropagation()&amp;lt;/code&amp;gt;. Comme &amp;lt;code&amp;gt;contact.js&amp;lt;/code&amp;gt; est chargé en premier dans &amp;lt;code&amp;gt;footer.thyme&amp;lt;/code&amp;gt;, son handler est attaché en premier. Il bloque la propagation. &amp;lt;code&amp;gt;ContactFormHandler&amp;lt;/code&amp;gt; ne sera jamais déclenché.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce n&amp;amp;#8217;est même pas un bug actif — c&amp;amp;#8217;est un zombie. Du code qui n&amp;amp;#8217;a jamais l&amp;amp;#8217;occasion de s&amp;amp;#8217;exécuter.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-before&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-1dca60606b3e7ccf37af78f090e4df27.svg&amp;quot; alt=&amp;quot;État initial — double handler et mock&amp;quot; width=&amp;quot;1972&amp;quot; height=&amp;quot;215&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_pourquoi_firebase_plutôt_que_supabase&amp;quot;&amp;gt;Pourquoi Firebase plutôt que Supabase ?&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La décision de migration est documentée dans &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Firebase est désormais choisi pour les raisons suivantes : meilleur plan gratuit, Firestore natif, Cloud Functions intégrées, écosystème Google plus adapté. L&amp;amp;#8217;implémentation Supabase existante est marquée « ⚠️ Abandonné ».&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Au-delà du plan gratuit, il y a une raison architecturale. Ce site vit dans l&amp;amp;#8217;écosystème Google : le dépôt cible est &amp;lt;code&amp;gt;cheroliv.github.io&amp;lt;/code&amp;gt;, le CNAME pointe sur GitHub Pages, le build Gradle push sur GitHub via JGit. Ajouter un service Google (Firebase) plutôt qu&amp;amp;#8217;un service tiers (Supabase) réduit la surface de dispersion.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Firestore en mode natif (pas en mode Datastore) est aussi plus proche du modèle mental NoSQL document que j&amp;amp;#8217;ai en tête : collections, documents, champs typés, timestamps serveur, règles de sécurité intégrées.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_phase_1_créer_le_projet_firebase&amp;quot;&amp;gt;Phase 1 : Créer le projet Firebase&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_initialisation&amp;quot;&amp;gt;Initialisation&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La CLI Firebase n&amp;amp;#8217;étant pas installée sur ma machine, je passe par la console web :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Aller sur &amp;lt;a href=&amp;quot;https://console.firebase.google.com/&amp;quot;&amp;gt;Firebase Console&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Créer un projet &amp;lt;code&amp;gt;cheroliv-contact&amp;lt;/code&amp;gt; (ou réutiliser un projet existant)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Activer Firestore en mode natif (pas Datastore)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Créer une base de données en région &amp;lt;code&amp;gt;eur3&amp;lt;/code&amp;gt; (Europe)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pour un usage minimaliste comme le nôtre (une seule collection, écriture publique), le mode natif est le bon choix. Pas besoin de règles Datastore complexes.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_règles_de_sécurité_firestore&amp;quot;&amp;gt;Règles de sécurité Firestore&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le formulaire est public — n&amp;amp;#8217;importe qui peut envoyer un message. Mais je veux limiter les abus :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript hljs&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;rules_version = &amp;#39;2&amp;#39;;

service cloud.firestore {
  match /databases/{database}/documents {

    match /contact_messages/{messageId} {
      // Lecture : admin uniquement (authentifié)
      allow read: if request.auth != null;

      // Écriture : publique, mais limitée
      allow create: if request.auth == null
        &amp;amp;amp;&amp;amp;amp; request.resource.data.name is string
        &amp;amp;amp;&amp;amp;amp; request.resource.data.name.size() &amp;amp;gt;= 1
        &amp;amp;amp;&amp;amp;amp; request.resource.data.name.size() &amp;amp;lt;= 100
        &amp;amp;amp;&amp;amp;amp; request.resource.data.email is string
        &amp;amp;amp;&amp;amp;amp; request.resource.data.email.matches(&amp;#39;.*@.*\\..*&amp;#39;)
        &amp;amp;amp;&amp;amp;amp; request.resource.data.email.size() &amp;amp;lt;= 254
        &amp;amp;amp;&amp;amp;amp; request.resource.data.subject is string
        &amp;amp;amp;&amp;amp;amp; request.resource.data.subject.size() &amp;amp;gt;= 3
        &amp;amp;amp;&amp;amp;amp; request.resource.data.subject.size() &amp;amp;lt;= 200
        &amp;amp;amp;&amp;amp;amp; request.resource.data.message is string
        &amp;amp;amp;&amp;amp;amp; request.resource.data.message.size() &amp;amp;gt;= 10
        &amp;amp;amp;&amp;amp;amp; request.resource.data.message.size() &amp;amp;lt;= 5000
        &amp;amp;amp;&amp;amp;amp; request.resource.data.created_at == request.time
        &amp;amp;amp;&amp;amp;amp; request.resource.data.user_agent is string
        &amp;amp;amp;&amp;amp;amp; request.resource.data.user_agent.size() &amp;amp;lt;= 500;
    }
  }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Points clés :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;allow read&amp;lt;/code&amp;gt; — seuls les utilisateurs authentifiés peuvent lire les messages (moi, via la console Firebase)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;allow create&amp;lt;/code&amp;gt; — n&amp;amp;#8217;importe qui peut créer un document, mais avec validation des champs&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Validation côté serveur : tailles min/max, format email, &amp;lt;code&amp;gt;created_at&amp;lt;/code&amp;gt; doit correspondre à &amp;lt;code&amp;gt;request.time&amp;lt;/code&amp;gt; (anti-falsification)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;user_agent&amp;lt;/code&amp;gt; est envoyé pour traçabilité (pas critique mais utile)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ces règles sont plus strictes qu&amp;amp;#8217;un simple &amp;lt;code&amp;gt;allow write: if true;&amp;lt;/code&amp;gt;. Elles empêchent un attaquant d&amp;amp;#8217;injecter des payloads énormes ou des champs mal formés.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_phase_2_réécrire_le_javascript_de_soumission&amp;quot;&amp;gt;Phase 2 : Réécrire le JavaScript de soumission&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le contrat est simple :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Lire les données du formulaire&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Vérifier le honeypot (champ &amp;lt;code&amp;gt;hp_name&amp;lt;/code&amp;gt; — s&amp;amp;#8217;il est rempli, c&amp;amp;#8217;est un bot, on simule un succès sans rien envoyer)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Appeler &amp;lt;code&amp;gt;addDoc(window.&amp;lt;em&amp;gt;FIREBASE&amp;lt;/em&amp;gt;.collection(db, &amp;quot;contact_messages&amp;quot;), {&amp;amp;#8230;&amp;amp;#8203;})&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Afficher succès ou erreur&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_la_dépendance_window_firebase&amp;quot;&amp;gt;La dépendance &amp;lt;code&amp;gt;window.&amp;lt;em&amp;gt;FIREBASE&amp;lt;/em&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Dans &amp;lt;code&amp;gt;footer.thyme&amp;lt;/code&amp;gt;, un script module initialise Firebase SDK et expose un objet global :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html hljs&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;script type=&amp;quot;module&amp;quot;&amp;amp;gt;
    import { initializeApp } from &amp;quot;https://www.gstatic.com/firebasejs/11.6.0/firebase-app.js&amp;quot;;
    import { getFirestore, collection, addDoc, serverTimestamp }
      from &amp;quot;https://www.gstatic.com/firebasejs/11.6.0/firebase-firestore.js&amp;quot;;

    const firebaseConfig = { /* valeurs réelles */ };
    const app = initializeApp(firebaseConfig);
    const db = getFirestore(app);

    window.__FIREBASE__ = { db, collection, addDoc, serverTimestamp };
&amp;amp;lt;/script&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Les scripts module s&amp;amp;#8217;exécutent avant &amp;lt;code&amp;gt;DOMContentLoaded&amp;lt;/code&amp;gt;, donc &amp;lt;code&amp;gt;window.&amp;lt;em&amp;gt;FIREBASE&amp;lt;/em&amp;gt;&amp;lt;/code&amp;gt; est garanti disponible quand le handler &amp;lt;code&amp;gt;contact.js&amp;lt;/code&amp;gt; se déclenche. Par précaution, j&amp;amp;#8217;ajoute quand même un polling de 5 secondes au cas où le CDN serait lent.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_nouveau_contact_js&amp;quot;&amp;gt;Le nouveau &amp;lt;code&amp;gt;contact.js&amp;lt;/code&amp;gt;&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript hljs&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, function () {
    &amp;#39;use strict&amp;#39;;

    const form = document.getElementById(&amp;#39;contact-form&amp;#39;);
    if (!form) return;

    const submitButton = form.querySelector(&amp;#39;button[type=&amp;quot;submit&amp;quot;]&amp;#39;);
    const successMessage = document.getElementById(&amp;#39;contact-success-message&amp;#39;);
    const errorMessage = document.getElementById(&amp;#39;contact-error-message&amp;#39;);

    // Éléments de validation
    const nameInput = form.querySelector(&amp;#39;input[name=&amp;quot;name&amp;quot;]&amp;#39;);
    const emailInput = form.querySelector(&amp;#39;input[name=&amp;quot;email&amp;quot;]&amp;#39;);
    const phoneInput = form.querySelector(&amp;#39;input[name=&amp;quot;phone&amp;quot;]&amp;#39;);
    const subjectInput = form.querySelector(&amp;#39;input[name=&amp;quot;subject&amp;quot;]&amp;#39;);
    const messageInput = form.querySelector(&amp;#39;textarea[name=&amp;quot;message&amp;quot;]&amp;#39;);
    const honeypotInput = form.querySelector(&amp;#39;input[name=&amp;quot;hp_name&amp;quot;]&amp;#39;);

    /**
     * Attend que window.__FIREBASE__ soit disponible.
     * Timeout de 5 secondes — si le CDN Firebase est lent, on abandonne.
     */
    function waitForFirebase(timeoutMs = 5000) {
        return new Promise((resolve, reject) =&amp;amp;gt; {
            if (window.__FIREBASE__) {
                resolve(window.__FIREBASE__);
                return;
            }
            const start = Date.now();
            const interval = setInterval(() =&amp;amp;gt; {
                if (window.__FIREBASE__) {
                    clearInterval(interval);
                    resolve(window.__FIREBASE__);
                } else if (Date.now() - start &amp;amp;gt; timeoutMs) {
                    clearInterval(interval);
                    reject(new Error(&amp;#39;Firebase SDK non disponible après timeout&amp;#39;));
                }
            }, 100);
        });
    }

    // --- Validation (identique à l&amp;#39;existant) ---
    function validateForm() {
        nameInput.setCustomValidity(&amp;#39;&amp;#39;);
        emailInput.setCustomValidity(&amp;#39;&amp;#39;);
        if (phoneInput) phoneInput.setCustomValidity(&amp;#39;&amp;#39;);
        subjectInput.setCustomValidity(&amp;#39;&amp;#39;);
        messageInput.setCustomValidity(&amp;#39;&amp;#39;);

        if (nameInput.value.trim().length &amp;amp;lt; 1) {
            nameInput.setCustomValidity(&amp;#39;Veuillez saisir votre nom.&amp;#39;);
        }
        const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        if (!emailPattern.test(emailInput.value.trim())) {
            emailInput.setCustomValidity(&amp;#39;Veuillez saisir une adresse email valide.&amp;#39;);
        }
        if (phoneInput &amp;amp;amp;&amp;amp;amp; phoneInput.value.trim() !== &amp;#39;&amp;#39;) {
            const phonePattern = /^\d{10,15}$/;
            if (!phonePattern.test(phoneInput.value.trim())) {
                phoneInput.setCustomValidity(&amp;#39;Veuillez saisir un numéro valide (10 à 15 chiffres).&amp;#39;);
            }
        }
        if (subjectInput.value.trim().length &amp;amp;lt; 3) {
            subjectInput.setCustomValidity(&amp;#39;Veuillez saisir un sujet (3 caractères minimum).&amp;#39;);
        }
        if (messageInput.value.trim().length &amp;amp;lt; 10) {
            messageInput.setCustomValidity(&amp;#39;Veuillez saisir un message (10 caractères minimum).&amp;#39;);
        }

        form.classList.add(&amp;#39;was-validated&amp;#39;);
        return form.checkValidity();
    }

    // --- Handler de soumission ---
    form.addEventListener(&amp;#39;submit&amp;#39;, async function (event) {
        event.preventDefault();
        event.stopPropagation();

        if (!validateForm()) return;

        // Honeypot : si rempli, simuler un succès sans rien envoyer
        if (honeypotInput &amp;amp;amp;&amp;amp;amp; honeypotInput.value.trim() !== &amp;#39;&amp;#39;) {
            successMessage.style.display = &amp;#39;block&amp;#39;;
            form.reset();
            form.classList.remove(&amp;#39;was-validated&amp;#39;);
            return;
        }

        // UI : état d&amp;#39;envoi
        submitButton.disabled = true;
        submitButton.innerHTML = `
            &amp;amp;lt;span class=&amp;quot;spinner-border spinner-border-sm&amp;quot; role=&amp;quot;status&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;
            Envoi en cours...
        `;
        successMessage.style.display = &amp;#39;none&amp;#39;;
        errorMessage.style.display = &amp;#39;none&amp;#39;;

        try {
            const fb = await waitForFirebase();
            const messagesCollection = fb.collection(fb.db, &amp;#39;contact_messages&amp;#39;);

            await fb.addDoc(messagesCollection, {
                name: nameInput.value.trim(),
                email: emailInput.value.trim(),
                phone: phoneInput ? phoneInput.value.trim() : &amp;#39;&amp;#39;,
                subject: subjectInput.value.trim(),
                message: messageInput.value.trim(),
                created_at: fb.serverTimestamp(),
                user_agent: navigator.userAgent.substring(0, 500)
            });

            successMessage.style.display = &amp;#39;block&amp;#39;;
            form.reset();
            form.classList.remove(&amp;#39;was-validated&amp;#39;);

        } catch (error) {
            console.error(&amp;#39;Erreur Firestore:&amp;#39;, error);
            errorMessage.style.display = &amp;#39;block&amp;#39;;

        } finally {
            submitButton.disabled = false;
            submitButton.innerHTML = `
                &amp;amp;lt;i class=&amp;quot;bi bi-send me-2&amp;quot;&amp;amp;gt;&amp;amp;lt;/i&amp;amp;gt;
                Envoyer le Message
            `;
        }
    }, false);
});&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Les changements par rapport au mock :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;waitForFirebase()&amp;lt;/code&amp;gt; — polling avec timeout, robuste même si le CDN est lent&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;honeypot&amp;lt;/code&amp;gt; — si le champ caché &amp;lt;code&amp;gt;hp_name&amp;lt;/code&amp;gt; est rempli, simuler un succès sans appel Firestore. Le bot croit avoir réussi mais rien n&amp;amp;#8217;est stocké&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;addDoc(collection, {&amp;amp;#8230;&amp;amp;#8203;})&amp;lt;/code&amp;gt; — vrai appel Firestore avec &amp;lt;code&amp;gt;serverTimestamp()&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;user_agent&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Gestion d&amp;amp;#8217;erreur avec &amp;lt;code&amp;gt;try/catch&amp;lt;/code&amp;gt; asynchrone&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Nettoyage du &amp;lt;code&amp;gt;finally&amp;lt;/code&amp;gt; (restauration du bouton)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;Note&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pourquoi &amp;lt;code&amp;gt;user_agent&amp;lt;/code&amp;gt; ? C&amp;amp;#8217;est optionnel, mais utile pour le diagnostic. Si un message étrange arrive, savoir si ça vient d&amp;amp;#8217;un navigateur desktop, mobile, ou d&amp;amp;#8217;un script curl aide au tri.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_phase_3_nettoyer_le_code_mort_supabase&amp;quot;&amp;gt;Phase 3 : Nettoyer le code mort Supabase&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;script.js&amp;lt;/code&amp;gt; contient 250 lignes de dead code :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;SupabaseManager&amp;lt;/code&amp;gt; (lignes 417-481) — 65 lignes&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;ContactFormHandler&amp;lt;/code&amp;gt; (lignes 490-551) — 62 lignes&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Bloc d&amp;amp;#8217;initialisation (lignes 645-654) — 10 lignes&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Total : ~140 lignes à supprimer.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le bloc &amp;lt;code&amp;gt;DOMContentLoaded&amp;lt;/code&amp;gt; crée un &amp;lt;code&amp;gt;SupabaseManager&amp;lt;/code&amp;gt; puis un &amp;lt;code&amp;gt;ContactFormHandler&amp;lt;/code&amp;gt; rattaché au formulaire. Comme expliqué plus haut, ce code ne s&amp;amp;#8217;exécute jamais (bloqué par &amp;lt;code&amp;gt;contact.js&amp;lt;/code&amp;gt;), et même s&amp;amp;#8217;il s&amp;amp;#8217;exécutait, il échouerait (pas de SDK Supabase chargé).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Je supprime :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;La classe &amp;lt;code&amp;gt;SupabaseManager&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;La classe &amp;lt;code&amp;gt;ContactFormHandler&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le bloc d&amp;amp;#8217;initialisation dans &amp;lt;code&amp;gt;DOMContentLoaded&amp;lt;/code&amp;gt; (lignes 645-654)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le reste de &amp;lt;code&amp;gt;script.js&amp;lt;/code&amp;gt; est intact : &amp;lt;code&amp;gt;ThemeManager&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ScrollToTopButton&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;MobileMenuManager&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SmoothScrollWithOffset&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NavbarHeightUpdater&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DynamicNavbarBreakpoint&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CodeBlockManager&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;TooltipManager&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PhoneInputManager&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_phase_4_configurer_le_footer&amp;quot;&amp;gt;Phase 4 : Configurer le footer&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;footer.thyme&amp;lt;/code&amp;gt; a déjà le boilerplate Firebase mais avec des valeurs placeholder. Je remplace :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript hljs&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;const firebaseConfig = {
    apiKey: &amp;quot;REMPLACER_PAR_VOTRE_API_KEY&amp;quot;,
    authDomain: &amp;quot;REMPLACER_PAR_VOTRE_AUTH_DOMAIN&amp;quot;,
    projectId: &amp;quot;REMPLACER_PAR_VOTRE_PROJECT_ID&amp;quot;,
    storageBucket: &amp;quot;REMPLACER_PAR_VOTRE_STORAGE_BUCKET&amp;quot;,
    messagingSenderId: &amp;quot;REMPLACER_PAR_VOTRE_SENDER_ID&amp;quot;,
    appId: &amp;quot;REMPLACER_PAR_VOTRE_APP_ID&amp;quot;
};&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Par les valeurs réelles récupérées depuis &amp;lt;strong&amp;gt;Project Settings &amp;amp;gt; General &amp;amp;gt; Your apps &amp;amp;gt; Web app&amp;lt;/strong&amp;gt; dans la console Firebase.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Les valeurs sont sensibles (&amp;lt;code&amp;gt;apiKey&amp;lt;/code&amp;gt; est publique par design chez Firebase, mais je préfère ne pas les commiter en clair). Je les stocke dans &amp;lt;code&amp;gt;site.yml&amp;lt;/code&amp;gt; (déjà dans &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt;) et le plugin &amp;lt;code&amp;gt;bakery&amp;lt;/code&amp;gt; les injecte dans le template via une logique à ajouter côté build.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pour l&amp;amp;#8217;instant, je les mets directement dans &amp;lt;code&amp;gt;footer.thyme&amp;lt;/code&amp;gt; — le build &amp;lt;code&amp;gt;./gradlew serve&amp;lt;/code&amp;gt; les chargera localement. Au déploiement, je migrerai l&amp;amp;#8217;injection vers &amp;lt;code&amp;gt;site.yml&amp;lt;/code&amp;gt; ou vers une variable Gradle.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock warning&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-warning&amp;quot; title=&amp;quot;Warning&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;#39;`apiKey` Firebase n&amp;amp;#8217;est &amp;lt;strong&amp;gt;pas&amp;lt;/strong&amp;gt; un secret. Elle est publique par conception. Ce qui protège vos données, ce sont les &amp;lt;strong&amp;gt;règles de sécurité Firestore&amp;lt;/strong&amp;gt;, pas la clé API. Ne la mettez pas dans un &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; chargé côté serveur — elle est destinée à être exposée au navigateur.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_phase_5_architecture_finale&amp;quot;&amp;gt;Phase 5 : Architecture finale&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;diag-after&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-97da02b2e5039b13e18110950d9d0e1b.svg&amp;quot; alt=&amp;quot;Architecture finale — Firebase Firestore&amp;quot; width=&amp;quot;512&amp;quot; height=&amp;quot;505&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_ce_que_cette_migration_dit_du_dogfooding&amp;quot;&amp;gt;Ce que cette migration dit du dogfooding&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce site est généré par mon propre plugin Gradle &amp;lt;code&amp;gt;bakery&amp;lt;/code&amp;gt;. Le formulaire de contact vit à l&amp;amp;#8217;intérieur du site. La migration Supabase → Firebase est documentée dans &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt;, elle est discutée dans le backlog, elle est testée via &amp;lt;code&amp;gt;./gradlew serve&amp;lt;/code&amp;gt;, et elle génère un article de blog (celui que vous lisez).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est du dogfooding pur. Le site est le produit du plugin, le plugin est le produit du développeur, le développeur documente le processus dans le site lui-même.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La boucle est bouclée.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le fait d&amp;amp;#8217;avoir traîné un mock pendant des mois (des sessions entières où le formulaire mentait silencieusement) m&amp;amp;#8217;a fait réaliser quelque chose : le backlog d&amp;amp;#8217;un site statique personnel n&amp;amp;#8217;est jamais « fini ». Il y a toujours une US prioritaire, toujours un article en draft, toujours une section commentée dans un template. La discipline n&amp;amp;#8217;est pas de tout finir — c&amp;amp;#8217;est de finir ce qui est visible par l&amp;amp;#8217;utilisateur.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un formulaire de contact cassé, c&amp;amp;#8217;est pire que pas de formulaire du tout. C&amp;amp;#8217;est une promesse non tenue.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_récapitulatif_des_modifications&amp;quot;&amp;gt;Récapitulatif des modifications&amp;lt;/h3&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6676%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Fichier&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Modification&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Impact&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;blog/2026/0113_*.adoc&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Création de l&amp;amp;#8217;article&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Documentation&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;assets/js/contact.js&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Réécriture (mock → Firestore réel)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Fonctionnel&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;assets/js/script.js&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Suppression SupabaseManager + ContactFormHandler + init bloc&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Nettoyage&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;templates/footer.thyme&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Remplacement config placeholder → valeurs réelles&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Configuration&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_prochaines_étapes_backlog&amp;quot;&amp;gt;Prochaines étapes (backlog)&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Notification email&amp;lt;/strong&amp;gt; : Une Cloud Function &amp;lt;code&amp;gt;onCreate&amp;lt;/code&amp;gt; sur &amp;lt;code&amp;gt;contact_messages&amp;lt;/code&amp;gt; qui envoie un mail via SendGrid. Le formulaire stocke, mais je ne suis pas notifié. Priorité moyenne — les messages sont visibles dans la console Firebase.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Rate limiting côté client&amp;lt;/strong&amp;gt; : Ajouter un timestamp localStorage pour empêcher les soumissions multiples en rafale. Le honeypot bloque les bots naïfs, un rate limiter bloquerait les bots un peu plus malins.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Tests&amp;lt;/strong&amp;gt; : Un test Playwright qui soumet le formulaire et vérifie que le document apparaît dans Firestore. Pour l&amp;amp;#8217;instant, je teste manuellement via &amp;lt;code&amp;gt;./gradlew serve&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_références&amp;quot;&amp;gt;Références&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://firebase.google.com/docs/firestore/security/get-started&amp;quot;&amp;gt;Documentation Firestore Security Rules&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://firebase.google.com/docs/firestore/manage-data/add-data#add_a_document&amp;quot;&amp;gt;Documentation Firestore addDoc — Web v9 modulaire&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;/blog/2026/0108_gouvernance_agent_opencode_eager_lazy_post.html&amp;quot;&amp;gt;Série gouvernance agent — Partie 1 : Eager/Lazy&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;/blog/2026/0110_mecanisme_backup_contexte_agent_post.html&amp;quot;&amp;gt;Série gouvernance agent — Partie 2 : Hot/Warm/Cold&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;/blog/2026/0111_audit_contexte_agent_post.html&amp;quot;&amp;gt;Série gouvernance agent — Partie 3 : Audit&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>DeepSeek-V4-Pro, Kimi K2.6, GLM-5.1 : Trois LLMs à l&#39;Épreuve du Vibe Coding Long Contexte</title>
            <link >https://cheroliv.com/blog/2026/0112_comparaison_kimi_glm_deepseek_long_contexte_plugin_gradle_opencode_post.html</link>
            <pubDate>Tue, 28 Apr 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0112_comparaison_kimi_glm_deepseek_long_contexte_plugin_gradle_opencode_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_contexte_pas_un_banc_dessai_un_chantier&amp;quot;&amp;gt;Contexte : pas un banc d&amp;amp;#8217;essai, un chantier&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_mon_environnement_de_test&amp;quot;&amp;gt;Mon environnement de test&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_grille_dévaluation&amp;quot;&amp;gt;La Grille d&amp;amp;#8217;Évaluation&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_round_1_kimi_k2_6_le_faux_départ&amp;quot;&amp;gt;Round 1 : Kimi K2.6 — Le Faux Départ&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_session_9_lembellie&amp;quot;&amp;gt;Session 9 : l&amp;amp;#8217;embellie&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_session_10_le_naufrage_silencieux&amp;quot;&amp;gt;Session 10 : le naufrage silencieux&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_round_2_glm_5_1_le_combattant_honorable&amp;quot;&amp;gt;Round 2 : GLM-5.1 — Le Combattant Honorable&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_architecture_le_dsa_contre_le_mla_pur&amp;quot;&amp;gt;Architecture : le DSA contre le MLA pur&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_sessions_11_13_solide_mais_frustrant&amp;quot;&amp;gt;Sessions 11-13 : solide mais frustrant&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_round_3_deepseek_v4_pro_la_machine_de_guerre&amp;quot;&amp;gt;Round 3 : DeepSeek-V4-Pro — La Machine de Guerre&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_architecture_csa_hca_le_double_filet&amp;quot;&amp;gt;Architecture : CSA + HCA, le double filet&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_sessions_1_8_le_soulagement&amp;quot;&amp;gt;Sessions 1-8 : le soulagement&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_test_décisif_refactoring_à_100k_tokens&amp;quot;&amp;gt;Le test décisif : refactoring à 100K tokens&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_face_à_face_metrics_comparatives&amp;quot;&amp;gt;Le Face-à-Face : Metrics Comparatives&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pourquoi_deepseek_v4_pro_gagne_en_développement_logiciel&amp;quot;&amp;gt;Pourquoi DeepSeek-V4-Pro Gagne en Développement Logiciel&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_1_larchitecture_csahca_est_taillée_pour_le_code&amp;quot;&amp;gt;1. L&amp;amp;#8217;architecture CSA+HCA est taillée pour le code&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_2_le_contexte_eager_est_sa_zone_de_confort&amp;quot;&amp;gt;2. Le contexte EAGER est sa zone de confort&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_3_le_rapport_qualitélatence_est_optimal_pour_le_flow&amp;quot;&amp;gt;3. Le rapport qualité/latence est optimal pour le flow&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_leçons_apprises_comment_choisir_son_llm_pour_le_vibe_coding&amp;quot;&amp;gt;Leçons Apprises : Comment Choisir son LLM pour le Vibe Coding&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_et_la_gouvernance_agent_dans_tout_ça&amp;quot;&amp;gt;Et la Gouvernance Agent dans tout ça ?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_sources_techniques&amp;quot;&amp;gt;Sources Techniques&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_conclusion_le_choix_de_lartisan&amp;quot;&amp;gt;Conclusion : Le Choix de l&amp;amp;#8217;Artisan&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 18 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;La guerre des LLMs se joue aussi dans le terminal d&amp;amp;#8217;un développeur. Pas sur des benchmarks académiques stériles. Dans la vraie vie : un prompt de 30 000 tokens, une gouvernance agent en AsciiDoc, des plugins Gradle Kotlin DSL à debugger et des sessions qui s&amp;amp;#8217;enchaînent sur trois semaines. J&amp;amp;#8217;ai testé pour vous DeepSeek-V4-Pro, Kimi K2.6 et GLM-5.1. Voici le verdict, preuves techniques à l&amp;amp;#8217;appui.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;toc&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;[]&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_contexte_pas_un_banc_dessai_un_chantier&amp;quot;&amp;gt;Contexte : pas un banc d&amp;amp;#8217;essai, un chantier&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Il y a trois semaines, je travaillais sur &amp;lt;code&amp;gt;codebase-gradle&amp;lt;/code&amp;gt;, mon meta-build system qui centralise la configuration YAML de quatre projets : un générateur de README PlantUML, un constructeur de slides AsciiDoc, un site statique JBake et un chatbot LLM. L&amp;amp;#8217;agent Opencode, gouverné par ma méthodologie de fichiers agents en AsciiDoc, chargeait ~30K tokens de contexte EAGER à chaque début de session — règles absolues, backlog, historique des 10 dernières sessions.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est sur ce terrain que j&amp;amp;#8217;ai confronté trois modèles :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Kimi K2.6&amp;lt;/strong&amp;gt; (Moonshot AI, 1T params / 32B activés, 256K contexte max, MLA) - &amp;lt;strong&amp;gt;GLM-5.1&amp;lt;/strong&amp;gt; (Zhipu AI/Tsinghua, 744B params / DSA, 200K contexte max) - &amp;lt;strong&amp;gt;DeepSeek-V4-Pro&amp;lt;/strong&amp;gt; (DeepSeek, 1.6T params / 49B activés, 1M contexte max, CSA+HCA)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Tous servis via Ollama sur serveur cloud, tous en mode thinking (phase de réflexion activée). L&amp;amp;#8217;enjeu : produire du code correct, maintenir la cohérence sur des sessions longues, et ne pas halluciner quand le contexte dépasse les 80K tokens.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_mon_environnement_de_test&amp;quot;&amp;gt;Mon environnement de test&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;diag-dev-env&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-b1ac0f8f2064fca47d705e64ced8b52f.svg&amp;quot; alt=&amp;quot;Environnement de développement — LLM + Opencode + Gradle&amp;quot; width=&amp;quot;1826&amp;quot; height=&amp;quot;5528&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Chaque session démarrait avec environ 30K tokens de contexte EAGER : &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt; (287 lignes), &amp;lt;code&amp;gt;PROMPT_REPRISE.adoc&amp;lt;/code&amp;gt; (51 lignes), &amp;lt;code&amp;gt;.agents/INDEX.adoc&amp;lt;/code&amp;gt; (218 lignes), &amp;lt;code&amp;gt;LAZY_EAGER_ESSENTIALS.adoc&amp;lt;/code&amp;gt; (50 lignes). Le contexte grossissait rapidement avec les échanges — une session typique de 10 messages ajoutait 15-20K tokens au prompt cumulé.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_grille_dévaluation&amp;quot;&amp;gt;La Grille d&amp;amp;#8217;Évaluation&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ai évalué chaque modèle sur quatre axes critiques pour le développement logiciel assisté :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Axe&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Critère concret&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Cohérence long contexte&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;L&amp;amp;#8217;agent se souvient-il des conventions décidées il y a 40 messages ?&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Qualité du code produit&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Le code compile-t-il du premier coup ? Respecte-t-il les patterns existants ?&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Raisonnement architectural&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;L&amp;amp;#8217;agent comprend-il les relations entre modules sans que je les lui réexplique ?&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Résistance aux hallucinations&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;À partir de combien de tokens l&amp;amp;#8217;agent commence-t-il à inventer des API ou des classes inexistantes ?&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Et une métrique synthétique maison : le &amp;lt;strong&amp;gt;coefficient de reprise&amp;lt;/strong&amp;gt; (combien de temps je passe à corriger l&amp;amp;#8217;agent plutôt qu&amp;amp;#8217;à coder avec lui).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_round_1_kimi_k2_6_le_faux_départ&amp;quot;&amp;gt;Round 1 : Kimi K2.6 — Le Faux Départ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Kimi K2.6 a été mon premier choix. Ses benchmarks sur SWE-Bench Verified (80.2) et Terminal-Bench 2.0 (66.7) sont excellents. Son architecture MLA promet une bonne efficacité sur les longues séquences.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_session_9_lembellie&amp;quot;&amp;gt;Session 9 : l&amp;amp;#8217;embellie&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Première session avec Kimi. Tâche : implémenter la méthode &amp;lt;code&amp;gt;resolveActiveKey()&amp;lt;/code&amp;gt; dans &amp;lt;code&amp;gt;codebase.kt&amp;lt;/code&amp;gt; — une fonction de résolution de clé API avec fallback CLI. Le contexte est à 30K tokens, Kimi raisonne vite, produit un code propre avec gestion d&amp;amp;#8217;expiration des clés.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;fun resolveActiveKey(
    cfg: CodebaseConfiguration,
    logger: Logger,
    cliProvider: String? = null,
    cliAccount: String? = null,
    cliKey: String? = null
): NamedApiKey? {
    // Résolution provider → compte → clé avec CLI override
    // Kimi a parfaitement compris la chaîne de priorité
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le code compile. Les 7 cas de test passent. Je suis optimiste.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_session_10_le_naufrage_silencieux&amp;quot;&amp;gt;Session 10 : le naufrage silencieux&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Deuxième session. Le contexte grimpe à ~90K tokens avec les échanges. Je demande à Kimi d&amp;amp;#8217;ajouter un mécanisme de snapshot AsciiDoc qui anonymise les secrets avant écriture.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est là que ça dérape. Kimi commence à inventer des classes qui n&amp;amp;#8217;existent pas. Il me propose &amp;lt;code&amp;gt;AnonymizedObjectMapper&amp;lt;/code&amp;gt; — une classe fictive. Il confond &amp;lt;code&amp;gt;ReadmeYmlAnonymizer&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;CodebaseYmlAnonymizer&amp;lt;/code&amp;gt;. Il me suggère d&amp;amp;#8217;importer &amp;lt;code&amp;gt;com.fasterxml.jackson.anonymize.*&amp;lt;/code&amp;gt; — un package qui n&amp;amp;#8217;a jamais existé.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pire : dans sa phase de réflexion, je vois qu&amp;amp;#8217;il construit des raisonnements sur des prémisses fausses. Il &amp;quot;se souvient&amp;quot; que &amp;lt;code&amp;gt;GitConfig&amp;lt;/code&amp;gt; a un champ &amp;lt;code&amp;gt;anonymizedToken&amp;lt;/code&amp;gt; — non, c&amp;amp;#8217;est &amp;lt;code&amp;gt;resolvedToken()&amp;lt;/code&amp;gt;. Il attribue à &amp;lt;code&amp;gt;SiteYmlAnonymizer&amp;lt;/code&amp;gt; une méthode &amp;lt;code&amp;gt;maskSupabaseCredentials()&amp;lt;/code&amp;gt; — qui n&amp;amp;#8217;existe pas.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&amp;lt;em&amp;gt;_ Ce n&amp;amp;#8217;était pas un bug. C&amp;amp;#8217;était une dissolution progressive de la cohérence. Comme si chaque token ajouté au contexte diluait un peu plus la mémoire des 30 000 premiers. &amp;lt;/em&amp;gt;_&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;arrête Kimi après deux sessions. Le diagnostic est clair : le MLA compresse bien le KV cache, mais sans mécanisme de sélection sparse fine-grained, l&amp;amp;#8217;attention se dilue mécaniquement au-delà de 60K tokens. Chaque token &amp;quot;voit&amp;quot; de moins en moins bien le contexte lointain — et commence à combler les trous par du bruit.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_round_2_glm_5_1_le_combattant_honorable&amp;quot;&amp;gt;Round 2 : GLM-5.1 — Le Combattant Honorable&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;GLM-5.1 arrive avec une architecture différente : MLA pour le base model, puis un &amp;lt;strong&amp;gt;continued pre-training&amp;lt;/strong&amp;gt; avec DSA (DeepSeek Sparse Attention) — un indexer léger qui sélectionne dynamiquement les top-2048 tokens pertinents parmi tout l&amp;amp;#8217;historique.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_architecture_le_dsa_contre_le_mla_pur&amp;quot;&amp;gt;Architecture : le DSA contre le MLA pur&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La différence est fondamentale. Là où Kimi compresse l&amp;amp;#8217;historique dans un espace latent unique (et perd progressivement la capacité à discriminer l&amp;amp;#8217;information pertinente), GLM greffe un indexer post-entraînement qui fait une sélection sparse explicite.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-mla-vs-dsa&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-96552207a44b513333686c1c93d0cef9.svg&amp;quot; alt=&amp;quot;Comparaison architecture MLA (Kimi) vs MLA+DSA (GLM)&amp;quot; width=&amp;quot;1074&amp;quot; height=&amp;quot;364&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le rapport technique le dit explicitement : DSA est &amp;lt;em&amp;gt;&amp;quot;lossless by construction&amp;quot;&amp;lt;/em&amp;gt; — contrairement aux alternatives comme SWA (pattern search), Gated DeltaNet ou SimpleGDN qui perdent jusqu&amp;amp;#8217;à 5.69 pts sur RULER@128K.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_sessions_11_13_solide_mais_frustrant&amp;quot;&amp;gt;Sessions 11-13 : solide mais frustrant&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;GLM-5.1 tient mieux la distance. Sur la session 11 (~60K tokens), il reste cohérent. Il produit un &amp;lt;code&amp;gt;SnapshotManager&amp;lt;/code&amp;gt; fonctionnel avec gestion correcte des quatre anonymiseurs.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mais la latence est un problème. Les phases de réflexion DSA sont plus lourdes que le MLA pur — l&amp;amp;#8217;indexer doit rescanner l&amp;amp;#8217;historique à chaque étape. Une réponse qui prenait 8 secondes avec Kimi en prend 15 avec GLM. Sur une session de 30 messages, ça se fait sentir.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Et puis il y a les erreurs subtiles. GLM ne délire pas comme Kimi — mais il fait des erreurs de &amp;lt;strong&amp;gt;nommage&amp;lt;/strong&amp;gt;. Il appelle &amp;lt;code&amp;gt;toAnonymizedYaml()&amp;lt;/code&amp;gt; la méthode qui devrait s&amp;amp;#8217;appeler &amp;lt;code&amp;gt;anonymize()&amp;lt;/code&amp;gt;. Il inverse &amp;lt;code&amp;gt;loadReadmeConfiguration()&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;loadCodebaseConfiguration()&amp;lt;/code&amp;gt; dans le &amp;lt;code&amp;gt;renderFileSection()&amp;lt;/code&amp;gt;. Ce ne sont pas des hallucinations, ce sont des confusions de surface — mais en production, une confusion de surface peut casser un build.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ai tenu trois sessions avec GLM. Il est meilleur que Kimi, sans conteste. Mais trois sessions de correction manuelle sur des détails de nommage, ça use.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_round_3_deepseek_v4_pro_la_machine_de_guerre&amp;quot;&amp;gt;Round 3 : DeepSeek-V4-Pro — La Machine de Guerre&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;DeepSeek-V4-Pro arrive avec l&amp;amp;#8217;architecture la plus ambitieuse des trois : un système hybride qui combine deux mécanismes d&amp;amp;#8217;attention complémentaires.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_architecture_csa_hca_le_double_filet&amp;quot;&amp;gt;Architecture : CSA + HCA, le double filet&amp;lt;/h3&amp;gt;
&amp;lt;div id=&amp;quot;diag-csa-hca&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-aad75fde6f9e97e39f6617b3b9f836d7.svg&amp;quot; alt=&amp;quot;Architecture hybride CSA+HCA de DeepSeek-V4-Pro&amp;quot; width=&amp;quot;741&amp;quot; height=&amp;quot;459&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Deux niveaux de compression, deux granularités d&amp;amp;#8217;attention :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;CSA&amp;lt;/strong&amp;gt; : compresse le KV cache tous les &amp;lt;code&amp;gt;m&amp;lt;/code&amp;gt; tokens, puis applique une attention sparse (DeepSeek Sparse Attention) — seul le top-k des entrées compressées est consulté. Précis, local, efficace. - &amp;lt;strong&amp;gt;HCA&amp;lt;/strong&amp;gt; : compression extrême (facteur &amp;lt;code&amp;gt;m&amp;#39;&amp;lt;/code&amp;gt; bien plus grand que &amp;lt;code&amp;gt;m&amp;lt;/code&amp;gt;), mais attention dense sur le résidu compressé — garde les connexions globales sans explosion quadratique.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Résultat : à 1M de tokens, DeepSeek-V4-Pro ne consomme que &amp;lt;strong&amp;gt;27% des FLOPs d&amp;amp;#8217;inférence&amp;lt;/strong&amp;gt; et &amp;lt;strong&amp;gt;10% de la taille du KV cache&amp;lt;/strong&amp;gt; par rapport à DeepSeek-V3.2. Le modèle précédent.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Et surtout, le rapport technique (Figure 9) annonce : &amp;lt;em&amp;gt;&amp;quot;Retrieval performance remains highly stable within a 128K context window.&amp;quot;&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_sessions_1_8_le_soulagement&amp;quot;&amp;gt;Sessions 1-8 : le soulagement&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ai passé huit sessions avec DeepSeek-V4-Pro sur &amp;lt;code&amp;gt;codebase-gradle&amp;lt;/code&amp;gt;. Huit sessions sans une seule hallucination, sans une seule classe inventée, sans une seule confusion de nommage.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Session 1 : implémentation de &amp;lt;code&amp;gt;CodebaseYmlConfig&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;CodebaseYmlAnonymizer&amp;lt;/code&amp;gt;. 350 lignes de Kotlin, tests inline, tout compile. Session 4 : ajout du &amp;lt;code&amp;gt;SnapshotManager&amp;lt;/code&amp;gt; avec tree view, collecte de fichiers, rendu AsciiDoc par fichier. 279 lignes, zéro erreur. Session 7 : debug du &amp;lt;code&amp;gt;renderFileSection()&amp;lt;/code&amp;gt; qui devait gérer quatre types d&amp;amp;#8217;anonymiseurs différents sans ambiguïté de résolution. Résolu en trois messages.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La latence est plus élevée que Kimi — environ 10-12 secondes par réponse en mode thinking. Mais le taux de correction est quasi nul. Je ne passe pas mon temps à réparer les erreurs de l&amp;amp;#8217;agent. Je code &amp;lt;strong&amp;gt;avec&amp;lt;/strong&amp;gt; lui.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_test_décisif_refactoring_à_100k_tokens&amp;quot;&amp;gt;Le test décisif : refactoring à 100K tokens&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;À la session 8, le contexte cumulé dépasse les 100K tokens. Je demande un refactoring lourd : extraire les quatre tâches de vérification inline du &amp;lt;code&amp;gt;build.gradle.kts&amp;lt;/code&amp;gt; vers des fichiers de test JUnit5 dans &amp;lt;code&amp;gt;buildSrc/src/test/&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;agent propose un plan en trois phases :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Créer les classes de test avec migration des cas existants&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Ajouter les dépendances JUnit5 et Kotest dans &amp;lt;code&amp;gt;buildSrc/build.gradle.kts&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Supprimer le code inline de &amp;lt;code&amp;gt;build.gradle.kts&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le plan est correct. L&amp;amp;#8217;exécution est propre. Il identifie même un edge case que j&amp;amp;#8217;avais manqué : les dépendances Jackson dupliquées entre &amp;lt;code&amp;gt;buildscript {}&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;buildSrc/build.gradle.kts&amp;lt;/code&amp;gt; qui doivent être unifiées pendant la migration.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;100K tokens de contexte, et l&amp;amp;#8217;agent se souvient que &amp;lt;code&amp;gt;CodebaseYmlAnonymizer.TOKEN_MASK&amp;lt;/code&amp;gt; est &amp;lt;code&amp;gt;&amp;quot;&amp;lt;strong&amp;gt;*&amp;lt;/strong&amp;gt;&amp;quot;&amp;lt;/code&amp;gt;, que &amp;lt;code&amp;gt;GitConfig.resolvedToken()&amp;lt;/code&amp;gt; est une extension function définie dans &amp;lt;code&amp;gt;readme.kt&amp;lt;/code&amp;gt;, et que &amp;lt;code&amp;gt;SnapshotManager.PRUNED_DIRS&amp;lt;/code&amp;gt; exclut &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.gradle&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.git&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est ça, la différence.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_face_à_face_metrics_comparatives&amp;quot;&amp;gt;Le Face-à-Face : Metrics Comparatives&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Critère&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Kimi K2.6&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;GLM-5.1&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;DeepSeek-V4-Pro&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Contexte max&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;256K&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;200K&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;1M&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Mécanisme attention&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;MLA pur&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;MLA + DSA&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;CSA + HCA hybride&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Paramètres totaux&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;1T&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;744B&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;1.6T&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Paramètres activés&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;32B&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;non publié&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;49B&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Seuil dégradation observé&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;~60K tokens&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;~120K tokens&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;~128K tokens&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Comportement au-delà&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Hallucinations massives&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Confusions de surface&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Dégradation progressive lente&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Stabilité NIAH&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;non publié&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;100% @128K (DSA)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;stable jusqu&amp;amp;#8217;à 128K (Figure 9)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;MRCR @128K&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;non publié&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;non publié&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;supérieur à Gemini 3.1 Pro&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Sessions tenues avant abandon&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;2&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;3&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;8 (et continue)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Temps de correction / temps de code&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;60%&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;30%&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;amp;lt;5%&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Latence moyenne (mode think)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;8 s&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;15 s&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;11 s&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Coefficient de confiance*&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;2/10&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;6/10&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;9/10&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;*Coefficient de confiance = mesure subjective de ma capacité à prendre le code de l&amp;amp;#8217;agent et le commit sans relecture ligne à ligne.&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-radar&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-1ac33bab88740dda58ef1579a97513c4.svg&amp;quot; alt=&amp;quot;Radar comparatif — Kimi K2.6 vs GLM-5.1 vs DeepSeek-V4-Pro&amp;quot; width=&amp;quot;1135&amp;quot; height=&amp;quot;844&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_pourquoi_deepseek_v4_pro_gagne_en_développement_logiciel&amp;quot;&amp;gt;Pourquoi DeepSeek-V4-Pro Gagne en Développement Logiciel&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La supériorité de DeepSeek-V4-Pro n&amp;amp;#8217;est pas due à un seul facteur — c&amp;amp;#8217;est une convergence :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_1_larchitecture_csahca_est_taillée_pour_le_code&amp;quot;&amp;gt;1. L&amp;amp;#8217;architecture CSA+HCA est taillée pour le code&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le développement logiciel assisté est un cas d&amp;amp;#8217;usage &amp;lt;strong&amp;gt;extrême&amp;lt;/strong&amp;gt; pour l&amp;amp;#8217;attention long-contexte. Vous avez besoin de : - Précision locale (cette classe hérite de quoi ? cette méthode est définie où ?) → &amp;lt;strong&amp;gt;CSA&amp;lt;/strong&amp;gt; - Vision globale (pourquoi ce module existe ? comment les quatre anonymiseurs interagissent ?) → &amp;lt;strong&amp;gt;HCA&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Kimi avec MLA seul gère la précision locale mais perd la vision globale au-delà de 60K. GLM avec DSA améliore la vision globale mais reste mono-niveau. DeepSeek combine les deux explicitement.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_2_le_contexte_eager_est_sa_zone_de_confort&amp;quot;&amp;gt;2. Le contexte EAGER est sa zone de confort&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mon système de gouvernance charge ~30K tokens de règles et de backlog au démarrage. Avec une fenêtre stable jusqu&amp;amp;#8217;à 128K, DeepSeek dispose de ~100K tokens de marge pour les échanges de la session. C&amp;amp;#8217;est 3 à 4 fois plus que ce que Kimi peut gérer sans dégradation.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&amp;lt;em&amp;gt;_ La fenêtre de 128K de stabilité parfaite correspond exactement à mes besoins : 30K d&amp;amp;#8217;EAGER + 70K d&amp;amp;#8217;échanges = une session productive de 20-30 messages sans jamais sortir de la zone verte. &amp;lt;/em&amp;gt;_&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_3_le_rapport_qualitélatence_est_optimal_pour_le_flow&amp;quot;&amp;gt;3. Le rapport qualité/latence est optimal pour le flow&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Oui, DeepSeek-V4-Pro est plus lent que Kimi (11s vs 8s). Mais le temps &amp;lt;strong&amp;gt;total&amp;lt;/strong&amp;gt; d&amp;amp;#8217;une tâche est bien inférieur parce que je ne passe pas 20 minutes à corriger les hallucinations de l&amp;amp;#8217;agent.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le développeur ne mesure pas la latence d&amp;amp;#8217;une réponse. Il mesure le temps entre &amp;quot;je pose la question&amp;quot; et &amp;quot;le code est dans mon repo et il fonctionne&amp;quot;. Sur cette métrique, DeepSeek-V4-Pro est le plus rapide des trois.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_leçons_apprises_comment_choisir_son_llm_pour_le_vibe_coding&amp;quot;&amp;gt;Leçons Apprises : Comment Choisir son LLM pour le Vibe Coding&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Au-delà du classement ponctuel, cette expérience m&amp;amp;#8217;a appris à évaluer un LLM pour le développement logiciel assisté sur des critères qui ne figurent dans aucun benchmark :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Regarde l&amp;amp;#8217;architecture, pas la taille de contexte annoncée&amp;lt;/strong&amp;gt; — Un modèle qui annonce 256K de contexte mais n&amp;amp;#8217;a qu&amp;amp;#8217;un MLA finira comme Kimi : théoriquement capable, pratiquement inutilisable au-delà de 60K.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Teste sur TON contexte, pas sur un benchmark générique&amp;lt;/strong&amp;gt; — Mon prompt initial de 30K tokens AsciiDoc avec règles absolues et backlog n&amp;amp;#8217;a rien à voir avec les questions de HLE ou AIME.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;La latence n&amp;amp;#8217;est pas l&amp;amp;#8217;ennemie si la qualité suit&amp;lt;/strong&amp;gt; — Un modèle lent qui produit du code juste est plus rapide qu&amp;amp;#8217;un modèle rapide qui produit du code faux.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Méfie-toi des modèles sans technical report public&amp;lt;/strong&amp;gt; — Si l&amp;amp;#8217;équipe ne documente pas son architecture d&amp;amp;#8217;attention, c&amp;amp;#8217;est qu&amp;amp;#8217;elle n&amp;amp;#8217;a pas confiance dans sa tenue en long contexte.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-decision-tree&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-764212652633dc337e38e51de5fc291e.svg&amp;quot; alt=&amp;quot;Arbre de décision pour choisir un LLM pour le développement logiciel assisté&amp;quot; width=&amp;quot;827&amp;quot; height=&amp;quot;461&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_et_la_gouvernance_agent_dans_tout_ça&amp;quot;&amp;gt;Et la Gouvernance Agent dans tout ça ?&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Cette expérience valide un point que je défends depuis mon article sur la gouvernance Eager/Lazy : &amp;lt;strong&amp;gt;la qualité du LLM et la qualité de la gouvernance sont multiplicatives, pas additives&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avec Kimi K2.6, ma gouvernance était impeccable — mais le modèle diluait l&amp;amp;#8217;information. Résultat : gouvernance parfaite × hallucination = zéro.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avec DeepSeek-V4-Pro, la gouvernance EAGER (30K tokens de règles) + LAZY (archives de sessions, références techniques) + Hot/Warm/Cold (backup rotatif) forme un écosystème où chaque couche amplifie l&amp;amp;#8217;autre. L&amp;amp;#8217;agent a les règles sous les yeux (EAGER), peut consulter l&amp;amp;#8217;historique (LAZY), et le contexte ne sature jamais (rotation backup).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&amp;lt;em&amp;gt;_ Un bon LLM sans gouvernance, c&amp;amp;#8217;est un moteur de Ferrari sans volant. Une bonne gouvernance sans bon LLM, c&amp;amp;#8217;est un volant sans moteur. DeepSeek-V4-Pro + ma gouvernance agent = la première fois que j&amp;amp;#8217;ai l&amp;amp;#8217;impression de conduire. &amp;lt;/em&amp;gt;_&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le mécanisme de backup rotatif (rotation toutes les 10 sessions ou &amp;amp;gt;500 lignes EAGER) prend tout son sens avec un modèle qui tient 128K de contexte : la sliding window de 10 sessions actives maintient le contexte frais sans jamais dépasser la zone de dégradation.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_sources_techniques&amp;quot;&amp;gt;Sources Techniques&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ai croisé mon expérience empirique avec les rapports techniques officiels pour valider mes observations :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;DeepSeek-V4 Technical Report&amp;lt;/strong&amp;gt; — PDF récupéré depuis &amp;lt;a href=&amp;quot;https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash&amp;quot;&amp;gt;HuggingFace&amp;lt;/a&amp;gt;. Figure 9 : &amp;quot;Retrieval performance remains highly stable within a 128K context window. While a performance degradation becomes visible beyond the 128K mark, the model&amp;amp;#8217;s retrieval capabilities at 1M tokens remain remarkably strong.&amp;quot; Architecture CSA+HCA documentée section 2.3.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;GLM-5 Technical Report&amp;lt;/strong&amp;gt; — &amp;lt;a href=&amp;quot;https://arxiv.org/abs/2602.15763&amp;quot;&amp;gt;arXiv:2602.15763&amp;lt;/a&amp;gt;. DSA introduit via continued pre-training, &amp;quot;lossless by construction&amp;quot;. Contexte max 202,752 tokens. Tables 3/5/6 documentent les performances long-contexte vs alternatives (SWA, Gated DeltaNet, SimpleGDN).&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Kimi K2.6 Model Card&amp;lt;/strong&amp;gt; — &amp;lt;a href=&amp;quot;https://huggingface.co/moonshotai/Kimi-K2.6&amp;quot;&amp;gt;HuggingFace&amp;lt;/a&amp;gt;. MLA, 256K contexte max. Stratégie de discard-all au-delà du seuil sur les tâches agentiques (confirmant implicitement la limite pratique du MLA en long contexte).&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Kimi K2 Technical Report&amp;lt;/strong&amp;gt; — &amp;lt;a href=&amp;quot;https://arxiv.org/abs/2507.20534&amp;quot;&amp;gt;arXiv:2507.20534&amp;lt;/a&amp;gt;. Architecture MoE, MuonClip optimizer, performances agentiques (HLE, BrowseComp, Terminal-Bench).&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le point le plus révélateur : dans leur propre évaluation, Moonshot applique une stratégie de &amp;lt;strong&amp;gt;discard-all&amp;lt;/strong&amp;gt; (suppression du contexte ancien) dès que la fenêtre de contexte est dépassée. Cela confirme exactement ce que j&amp;amp;#8217;ai observé : le MLA seul ne peut pas maintenir la cohérence sur toute la fenêtre de 256K. L&amp;amp;#8217;architecture ne suit pas.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_conclusion_le_choix_de_lartisan&amp;quot;&amp;gt;Conclusion : Le Choix de l&amp;amp;#8217;Artisan&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Après trois semaines et treize sessions de développement réel, le verdict est sans appel :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 8.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 8.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 8.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 8.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 8.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 8.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 8.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 8.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 8.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 8.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 8.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 8.3337%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Kimi K2.6&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;GLM-5.1&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;DeepSeek-V4-Pro&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Excellent sous 60K&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Solide jusqu&amp;amp;#8217;à 120K&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Domine partout&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Inutilisable au-delà&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Confusions de surface&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Stable jusqu&amp;amp;#8217;à 128K&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;2 sessions, abandonné&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;3 sessions, abandonné&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;8 sessions, adopté&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;DeepSeek-V4-Pro est devenu mon LLM par défaut pour toutes les sessions de développement logiciel assisté avec Opencode. Pas parce qu&amp;amp;#8217;il est le plus récent. Pas parce qu&amp;amp;#8217;il a les meilleurs benchmarks académiques. Mais parce que dans la vraie vie d&amp;amp;#8217;un développeur qui pousse des plugins Gradle Kotlin DSL avec un contexte agent de 30K tokens, c&amp;amp;#8217;est le seul qui ne me trahit pas quand le contexte s&amp;amp;#8217;allonge.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le CSA+HCA est un &amp;lt;strong&amp;gt;game changer&amp;lt;/strong&amp;gt; architectural. La compression double niveau + sparsification n&amp;amp;#8217;est pas un détail d&amp;amp;#8217;implémentation — c&amp;amp;#8217;est ce qui fait la différence entre un assistant de code et un coéquipier fiable.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&amp;lt;em&amp;gt;_ J&amp;amp;#8217;ai choisi DeepSeek-V4-Pro parce qu&amp;amp;#8217;il est le seul des trois qui transforme ma gouvernance agent d&amp;amp;#8217;une contrainte défensive (&amp;quot;comment éviter que l&amp;amp;#8217;agent oublie ?&amp;quot;) en un avantage offensif (&amp;quot;que peut-on construire maintenant que l&amp;amp;#8217;agent se souvient de tout ?&amp;quot;). &amp;lt;/em&amp;gt;_&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Cet article est le fruit de 13 sessions de développement réel sur le projet &amp;lt;code&amp;gt;codebase-gradle&amp;lt;/code&amp;gt;, documentées dans &amp;lt;code&amp;gt;.agents/sessions/&amp;lt;/code&amp;gt; selon ma méthodologie de gouvernance agent Eager/Lazy/Hot/Warm/Cold. Les sources techniques citées sont accessibles publiquement sur HuggingFace et arXiv.&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Audit de Contexte Agent : Quand Votre Propre Gouvernance Devient le Problème — et Comment la Réparer sans Rien Perdre</title>
            <link >https://cheroliv.com/blog/2026/0111_audit_contexte_agent_post.html</link>
            <pubDate>Mon, 27 Apr 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0111_audit_contexte_agent_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_scène_session_051_quelque_chose_cloche&amp;quot;&amp;gt;La scène : session 051, quelque chose cloche&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_laudit_décortiquer_les_627_lignes&amp;quot;&amp;gt;L&amp;amp;#8217;audit : décortiquer les 627 lignes&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_peur_de_perdre_lingénierie&amp;quot;&amp;gt;La peur de perdre l&amp;amp;#8217;ingénierie&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_solution_split_encyclopédique&amp;quot;&amp;gt;La solution : split encyclopédique&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_contenu_du_fichier_essentials&amp;quot;&amp;gt;Le contenu du fichier ESSENTIALS&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_résultat_50_de_contexte_eager&amp;quot;&amp;gt;Le résultat : -50% de contexte EAGER&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pourquoi_le_dossier_sappelle_encyclopedies&amp;quot;&amp;gt;Pourquoi le dossier s&amp;amp;#8217;appelle &amp;lt;code&amp;gt;encyclopedies/&amp;lt;/code&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_suite_logique_de_la_série&amp;quot;&amp;gt;La suite logique de la série&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ce_que_jaurais_fait_différemment&amp;quot;&amp;gt;Ce que j&amp;amp;#8217;aurais fait différemment&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_guide_pour_auditer_votre_propre_contexte&amp;quot;&amp;gt;Le guide pour auditer votre propre contexte&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_une_gouvernance_vivante&amp;quot;&amp;gt;Une gouvernance vivante&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_liens&amp;quot;&amp;gt;Liens&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 14 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Vous avez passé des semaines à construire une gouvernance agent impeccable. Eager/Lazy, procédure de fin de session, backups rotatifs. Le système tourne. Puis un jour, l&amp;amp;#8217;agent devient lent. Les réponses sont diluées. Vous mesurez : 1414 lignes chargées automatiquement. Et le pire, c&amp;amp;#8217;est que le coupable n&amp;amp;#8217;est pas le code, ni le backlog, ni les archives de sessions. Le coupable, c&amp;amp;#8217;est le fichier qui documente votre méthode.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;toc&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;[]&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_scène_session_051_quelque_chose_cloche&amp;quot;&amp;gt;La scène : session 051, quelque chose cloche&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;30 avril 2026, 16h00. Je suis en pleine session sur &amp;lt;code&amp;gt;magic-stick&amp;lt;/code&amp;gt;, mon projet de build d&amp;amp;#8217;ISO Linux live. L&amp;amp;#8217;agent Opencode a chargé automatiquement mes fichiers Eager comme d&amp;amp;#8217;habitude — &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PROMPT_REPRISE.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.agents/INDEX.adoc&amp;lt;/code&amp;gt;. Tout est normal.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Sauf que les réponses sont molles. L&amp;amp;#8217;agent met deux secondes de plus à raisonner. Il oublie un détail qu&amp;amp;#8217;il avait sous les yeux trois messages plus tôt. Ce n&amp;amp;#8217;est pas un crash, pas une erreur — c&amp;amp;#8217;est une dégradation lente, le genre qu&amp;amp;#8217;on ne remarque pas tout de suite.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;avais déjà vécu ça à la session 048, quand j&amp;amp;#8217;avais découvert que les fichiers de gouvernance pesaient 5200 lignes cumulées. J&amp;amp;#8217;avais alors conceptualisé le mécanisme Hot/Warm/Cold avec sa sliding window de 10 sessions, ses vagues froides identiques, son capteur à deux déclencheurs. Le problème était réglé. En théorie.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mais là, on est à la session 051. La rotation backup a bien eu lieu — les fichiers EAGER sont passés de 2087 à 500 lignes. Pourtant, le contexte reste lourd. Quelque chose m&amp;amp;#8217;échappe.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ouvre un terminal et je tape :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;wc -l AGENT.adoc AGENT_MODUS_OPERANDI.adoc PROMPT_REPRISE.adoc \
  .agents/INDEX.adoc .agents/SESSIONS_HISTORY.adoc \
  .agents/archives/COMPLETED_TASKS_ARCHIVE_2026-04.adoc&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;  287 AGENT.adoc
  627 AGENT_MODUS_OPERANDI.adoc
   51 PROMPT_REPRISE.adoc
  218 .agents/INDEX.adoc
   18 .agents/SESSIONS_HISTORY.adoc
  213 .agents/archives/COMPLETED_TASKS_ARCHIVE_2026-04.adoc
 1414 total&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;1414 lignes. La rotation backup a bien taillé dans INDEX, SESSIONS_HISTORY et COMPLETED_TASKS — ils sont propres. Mais il y a un éléphant dans la pièce que je n&amp;amp;#8217;avais pas vu : &amp;lt;strong&amp;gt;627 lignes&amp;lt;/strong&amp;gt; dans un seul fichier. &amp;lt;code&amp;gt;AGENT_MODUS_OPERANDI.adoc&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce fichier, c&amp;amp;#8217;est celui que j&amp;amp;#8217;ai écrit à la session 1 pour documenter la stratégie Eager/Lazy. C&amp;amp;#8217;est le manuel de la méthode. Et il est devenu, à lui seul, 44% du contexte EAGER.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-before-audit&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-055a31fdef8c78e522a1ab22c6f74925.svg&amp;quot; alt=&amp;quot;Répartition des 1414 lignes EAGER avant audit&amp;quot; width=&amp;quot;721&amp;quot; height=&amp;quot;200&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;ironie est totale. Le fichier conçu pour &amp;lt;strong&amp;gt;économiser&amp;lt;/strong&amp;gt; du contexte est devenu le principal &amp;lt;strong&amp;gt;consommateur&amp;lt;/strong&amp;gt; de contexte. C&amp;amp;#8217;est comme si le manuel d&amp;amp;#8217;utilisation de votre voiture pesait plus lourd que le moteur.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_laudit_décortiquer_les_627_lignes&amp;quot;&amp;gt;L&amp;amp;#8217;audit : décortiquer les 627 lignes&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Je décide de faire un audit section par section. Pas pour supprimer — pour &amp;lt;strong&amp;gt;comprendre&amp;lt;/strong&amp;gt; ce qui mérite d&amp;amp;#8217;être en EAGER et ce qui pourrait vivre ailleurs sans perte de connaissance.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Voici la structure exacte de &amp;lt;code&amp;gt;AGENT_MODUS_OPERANDI.adoc&amp;lt;/code&amp;gt; et ce que j&amp;amp;#8217;y trouve :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2727%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.2739%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Section&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Lignes&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Contenu&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Déjà présent dans&amp;amp;#8230;&amp;amp;#8203;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;P1 — Vue d&amp;amp;#8217;ensemble&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;64&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Problème résolu, principes fondamentaux, analogie tableau de bord vs manuel&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;—&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;P2 — Structure des fichiers&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;97&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Arborescence, politique de chargement, quand charger quoi&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;—&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;P3 — Règles absolues&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;34&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Git interdit, commandes destructrices interdites, secrets interdits&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;INDEX.adoc&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;P4 — Cycle de vie session&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;133&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Template ouverture, règles de travail, 6 étapes fin de session, checklist&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt; §Fin session + &amp;lt;code&amp;gt;INDEX.adoc&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;P5 — Métriques et seuils&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;49&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Session idéale (15-30 min, 1-3 fichiers), signes d&amp;amp;#8217;alerte&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;—&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;P6 — Types de sessions&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;72&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Tableau de détection, format de proposition, exceptions&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;—&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;P7 — Amélioration continue&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;39&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Métriques de suivi, revue hebdomadaire&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;—&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;P8 — Checklist démarrage&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;13&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Bootstrap nouveau projet&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;—&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;P9 — Références&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;30&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Fichiers de référence, ressources externes&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt; (fichiers EAGER/LAZY)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Annexes A+B&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;42&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Glossaire, historique versions&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;—&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le verdict est sans appel :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Doublons intégraux&amp;lt;/strong&amp;gt; (167 lignes) : P3, P4, P9 — tout est déjà dans &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt; ou &amp;lt;code&amp;gt;INDEX.adoc&amp;lt;/code&amp;gt;, souvent mot pour mot&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Jamais consulté en pratique&amp;lt;/strong&amp;gt; (215 lignes) : P5, P6, P7, P8, Annexes — de la méta-gouvernance qui n&amp;amp;#8217;a jamais servi dans aucune session&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Connaissance unique&amp;lt;/strong&amp;gt; (161 lignes) : P1 et P2 — le vocabulaire LAZY/EAGER, l&amp;amp;#8217;analogie, la politique de chargement&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Sur 627 lignes, &amp;lt;strong&amp;gt;382 sont du bruit&amp;lt;/strong&amp;gt;. Et ces 382 lignes sont chargées &amp;lt;strong&amp;gt;à chaque début de session&amp;lt;/strong&amp;gt;, consommées par l&amp;amp;#8217;agent, diluant son attention avant même que je dise bonjour.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-audit-result&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-e3ec2f50f58c8bbd108e7f63232946be.svg&amp;quot; alt=&amp;quot;Résultat de l&amp;amp;#8217;audit — 627 lignes réparties en doublons, jamais consulté, connaissance unique&amp;quot; width=&amp;quot;514&amp;quot; height=&amp;quot;665&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce diagramme est la clé de tout. Les doublons (jaune) sont du bruit pur — l&amp;amp;#8217;agent les lit deux fois, dans deux fichiers différents. Le jamais consulté (rouge) est de la documentation morte — écrite avec soin, jamais utilisée. Seul le vert contient de la connaissance que l&amp;amp;#8217;agent ne peut pas trouver ailleurs.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_peur_de_perdre_lingénierie&amp;quot;&amp;gt;La peur de perdre l&amp;amp;#8217;ingénierie&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;À ce stade, j&amp;amp;#8217;ai l&amp;amp;#8217;évidence sous les yeux : je dois réduire &amp;lt;code&amp;gt;AGENT_MODUS_OPERANDI.adoc&amp;lt;/code&amp;gt;. Mais j&amp;amp;#8217;hésite.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce fichier, je l&amp;amp;#8217;ai écrit à la main. Chaque section est le résultat d&amp;amp;#8217;une leçon apprise en session réelle. La partie P3 est née d&amp;amp;#8217;un &amp;lt;code&amp;gt;rm -rf&amp;lt;/code&amp;gt; accidentel sur &amp;lt;code&amp;gt;bakery-plugin&amp;lt;/code&amp;gt; qui m&amp;amp;#8217;a coûté des tokens Firebase réels. La partie P4 est le résultat de quinze sessions où j&amp;amp;#8217;oubliais d&amp;amp;#8217;archiver et je perdais le fil. La procédure en 6 étapes n&amp;amp;#8217;est pas sortie d&amp;amp;#8217;un livre — elle est sortie de la douleur.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Supprimer ces sections, ce serait jeter l&amp;amp;#8217;historique de ma propre ingénierie. Les leçons qui les ont produites, les sessions pendant lesquelles je les ai découvertes, les erreurs que je ne veux plus jamais refaire. Ce n&amp;amp;#8217;est pas du texte — c&amp;amp;#8217;est de l&amp;amp;#8217;expérience cristallisée.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est là que je formule le principe qui va guider la solution :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&amp;lt;em&amp;gt;_ &amp;lt;strong&amp;gt;Ne jamais supprimer. Toujours relocaliser.&amp;lt;/strong&amp;gt; La connaissance n&amp;amp;#8217;a pas à disparaître du projet. Elle a juste à ne pas être chargée automatiquement quand elle n&amp;amp;#8217;est pas nécessaire. &amp;lt;/em&amp;gt;_&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_solution_split_encyclopédique&amp;quot;&amp;gt;La solution : split encyclopédique&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le modèle que je propose est simple et s&amp;amp;#8217;inspire de la façon dont Wikipédia a grandi : quand un article devient trop long, on ne le coupe pas — on crée un article détaillé et on garde un résumé dans l&amp;amp;#8217;article principal.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pour &amp;lt;code&amp;gt;AGENT_MODUS_OPERANDI.adoc&amp;lt;/code&amp;gt;, cela donne :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Extraire&amp;lt;/strong&amp;gt; les 161 lignes de connaissance unique (P1 + P2) dans un nouveau fichier &amp;lt;code&amp;gt;LAZY_EAGER_ESSENTIALS.adoc&amp;lt;/code&amp;gt; — compacté à ~50 lignes, strictement EAGER&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Renommer&amp;lt;/strong&amp;gt; &amp;lt;code&amp;gt;AGENT_MODUS_OPERANDI.adoc&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;.agents/encyclopedies/LAZY_EAGER_ENCYCLOPEDIE.adoc&amp;lt;/code&amp;gt; — le fichier original de 627 lignes, préservé &amp;lt;strong&amp;gt;intact&amp;lt;/strong&amp;gt;, en cold storage&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Ne jamais charger&amp;lt;/strong&amp;gt; le fichier encyclopédie automatiquement — il est là pour l&amp;amp;#8217;humain, pour la distillation future, pour l&amp;amp;#8217;agent qu&amp;amp;#8217;on invoquera dans six mois avec un meilleur modèle&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-split-solution&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-1ca7b1421a06e9049df1c3513a7924d2.svg&amp;quot; alt=&amp;quot;Architecture du split encyclopédique — ESSENTIALS EAGER + ENCYCLOPEDIE cold storage&amp;quot; width=&amp;quot;762&amp;quot; height=&amp;quot;530&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le nom &amp;lt;code&amp;gt;encyclopedies/&amp;lt;/code&amp;gt; n&amp;amp;#8217;est pas anodin. Une encyclopédie, ce n&amp;amp;#8217;est pas un dossier d&amp;amp;#8217;archives — c&amp;amp;#8217;est une collection de connaissance organisée, consultable mais pas portable. On ne lit pas l&amp;amp;#8217;Encyclopédie Universalis dans le métro. On la garde dans la bibliothèque, et on y va quand on a une question précise.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est exactement le rôle de ce dossier : une bibliothèque de référence froide, structurée, exhaustive — que l&amp;amp;#8217;agent ne touche pas automatiquement.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_contenu_du_fichier_essentials&amp;quot;&amp;gt;Le contenu du fichier ESSENTIALS&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Voici à quoi ressemble concrètement le nouveau fichier &amp;lt;code&amp;gt;LAZY_EAGER_ESSENTIALS.adoc&amp;lt;/code&amp;gt;, extrait et compacté à partir de P1 et P2 :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;= Stratégie LAZY/EAGER — Principes Essentiels

[abstract]
Ce fichier définit la stratégie de gestion du contexte agent.
Chargé automatiquement (EAGER) en début de session.

== Principes

|===
| EAGER | LAZY
| Tableau de bord | Manuel du propriétaire
| Chargé automatiquement | Chargé sur demande
| &amp;amp;lt;= 100 lignes, &amp;amp;lt;= 10k tokens | Illimité, détaillé
| Règles absolues, mission courante | Archives, historique, références
|===

== Politique de Chargement

|===
| Fichier | Type | Quand charger
| PROMPT_REPRISE.adoc | EAGER | Début session (auto)
| *_ESSENTIALS.adoc | EAGER | Début session si EPIC active
| .agents/INDEX.adoc | EAGER | Début session (auto)
| *_REFERENCE.adoc | LAZY | Sur besoin (détails architecture)
| .agents/sessions/N-*.adoc | LAZY | Sur demande (détails session)
| .agents/encyclopedies/*.adoc | COLD | Jamais auto (humain seulement)
|===

== Comment l&amp;#39;Agent Sait Quoi Charger

Début session → PROMPT_REPRISE + INDEX + ESSENTIALS actifs.
Besoin de détails → charger les *_REFERENCE et sessions/ en LAZY.
Connaissance froide → encyclopedies/, jamais automatique.&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Cinquante lignes. C&amp;amp;#8217;est tout ce dont l&amp;amp;#8217;agent a besoin pour comprendre la mécanique. Tout le reste — l&amp;amp;#8217;historique des leçons, les analogies détaillées, les procédures pas à pas, les annexes — vit dans l&amp;amp;#8217;encyclopédie.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Et le plus important : &amp;lt;strong&amp;gt;rien n&amp;amp;#8217;a été supprimé&amp;lt;/strong&amp;gt;. Les 627 lignes d&amp;amp;#8217;ingénierie sont toujours là, dans &amp;lt;code&amp;gt;.agents/encyclopedies/LAZY_EAGER_ENCYCLOPEDIE.adoc&amp;lt;/code&amp;gt;. Elles sont juste rangées dans la bibliothèque plutôt que sur le plan de travail.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_résultat_50_de_contexte_eager&amp;quot;&amp;gt;Le résultat : -50% de contexte EAGER&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avant le split :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt; 287 AGENT.adoc
 627 AGENT_MODUS_OPERANDI.adoc
  51 PROMPT_REPRISE.adoc
 218 .agents/INDEX.adoc
  18 .agents/SESSIONS_HISTORY.adoc
 213 .agents/archives/COMPLETED_TASKS_ARCHIVE_2026-04.adoc
1414 total&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Après le split :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt; 287 AGENT.adoc
  50 LAZY_EAGER_ESSENTIALS.adoc       ← remplace 627 lignes
  51 PROMPT_REPRISE.adoc
 218 .agents/INDEX.adoc
  18 .agents/SESSIONS_HISTORY.adoc
 213 .agents/archives/COMPLETED_TASKS_ARCHIVE_2026-04.adoc
 837 total                              ← -41%&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-after-audit&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-4ca8c26a5cbdc6d1078c3680e6b90bec.svg&amp;quot; alt=&amp;quot;Répartition des 837 lignes EAGER après audit — gain de 41%&amp;quot; width=&amp;quot;687&amp;quot; height=&amp;quot;230&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le plus gros consommateur (AGENT_MODUS_OPERANDI, 627 lignes) a été remplacé par un fichier de 50 lignes. Le gain est immédiat : 577 lignes de contexte libérées. L&amp;amp;#8217;agent respire.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Et dans &amp;lt;code&amp;gt;.agents/encyclopedies/&amp;lt;/code&amp;gt;, le fichier original de 627 lignes attend. Intact. Avec toutes ses sections — y compris celles qui sont des doublons, y compris celles qui n&amp;amp;#8217;ont jamais servi. Parce qu&amp;amp;#8217;un jour, un meilleur modèle ou un data scientist humain voudra croiser ces angles, ces redondances assumées, ces leçons apprises. Et ce jour-là, la matière première sera là.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_pourquoi_le_dossier_sappelle_encyclopedies&amp;quot;&amp;gt;Pourquoi le dossier s&amp;amp;#8217;appelle &amp;lt;code&amp;gt;encyclopedies/&amp;lt;/code&amp;gt;&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le choix du nom n&amp;amp;#8217;est pas cosmétique. Il encode la philosophie du mécanisme.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Une &amp;lt;strong&amp;gt;archive&amp;lt;/strong&amp;gt; (&amp;lt;code&amp;gt;archives/&amp;lt;/code&amp;gt;) contient des données historiques organisées chronologiquement — comme les COMPLETED_TASKS mensuels. Un &amp;lt;strong&amp;gt;backup&amp;lt;/strong&amp;gt; (&amp;lt;code&amp;gt;backup/&amp;lt;/code&amp;gt;) est un snapshot horodaté — une copie de sécurité d&amp;amp;#8217;un état passé.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Une &amp;lt;strong&amp;gt;encyclopédie&amp;lt;/strong&amp;gt;, c&amp;amp;#8217;est autre chose. C&amp;amp;#8217;est une collection de connaissance thématique, structurée par sujet, exhaustive mais non linéaire. On ne lit pas une encyclopédie du début à la fin. On y plonge pour répondre à une question précise.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est exactement le contrat de ce dossier :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Dossier&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Rôle&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Accès&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Granularité&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;archives/&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Données historiques (tâches terminées par mois)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;LAZY, structuré&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Chronologique&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;backup/&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Snapshots froids (vagues de 10 sessions)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;COLD, copie intégrale&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Chronologique&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;encyclopedies/&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Connaissance thématique exhaustive (méthodologie, patterns)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;COLD, jamais auto&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Thématique&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Cette distinction évite le fourre-tout. Chaque fichier sait où il doit vivre selon &amp;lt;strong&amp;gt;ce qu&amp;amp;#8217;il contient&amp;lt;/strong&amp;gt;, pas selon &amp;lt;strong&amp;gt;quand il a été créé&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_suite_logique_de_la_série&amp;quot;&amp;gt;La suite logique de la série&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Si vous avez lu les deux premiers articles, voici comment les trois pièces s&amp;amp;#8217;emboîtent :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-trilogie&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-7a93be1f2d7bbeab8cf9d47564547c7c.svg&amp;quot; alt=&amp;quot;Les trois articles de la série gouvernance — progression logique&amp;quot; width=&amp;quot;1216&amp;quot; height=&amp;quot;493&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;0108&amp;lt;/strong&amp;gt; répond à : « Comment donner une mémoire à l&amp;amp;#8217;agent entre deux sessions ? »&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;0110&amp;lt;/strong&amp;gt; répond à : « Comment empêcher cette mémoire d&amp;amp;#8217;étouffer l&amp;amp;#8217;agent ? »&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;0111&amp;lt;/strong&amp;gt; répond à : « Et si le problème n&amp;amp;#8217;est pas la taille des archives, mais ce qu&amp;amp;#8217;on a &amp;lt;strong&amp;gt;choisi&amp;lt;/strong&amp;gt; de mettre en EAGER ? »&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le premier article a construit la structure. Le deuxième a ajouté le mécanisme de vieillissement. Le troisième audite le contenu — et découvre que la méthodologie elle-même est devenue le problème.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_ce_que_jaurais_fait_différemment&amp;quot;&amp;gt;Ce que j&amp;amp;#8217;aurais fait différemment&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avec le recul, je vois l&amp;amp;#8217;erreur de conception initiale. &amp;lt;code&amp;gt;AGENT_MODUS_OPERANDI.adoc&amp;lt;/code&amp;gt; a été créé comme un document unique — un manifeste. C&amp;amp;#8217;était la bonne approche pour formaliser la pensée. Mais une fois la pensée formalisée, le document aurait dû être splité immédiatement : l&amp;amp;#8217;essentiel en EAGER, l&amp;amp;#8217;exhaustif en cold.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Je ne l&amp;amp;#8217;ai pas fait parce que j&amp;amp;#8217;étais fier du document. 627 lignes d&amp;amp;#8217;ingénierie pure, écrites à la main, chaque section fruit d&amp;amp;#8217;une leçon de session. C&amp;amp;#8217;était mon œuvre. Et comme tout auteur, j&amp;amp;#8217;ai eu du mal à la découper.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La leçon : &amp;lt;strong&amp;gt;ce n&amp;amp;#8217;est pas parce qu&amp;amp;#8217;un document est bon qu&amp;amp;#8217;il doit être chargé automatiquement&amp;lt;/strong&amp;gt;. La qualité du contenu n&amp;amp;#8217;a aucun rapport avec sa pertinence pour le contexte immédiat de l&amp;amp;#8217;agent.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Aujourd&amp;amp;#8217;hui, la règle est simple : tout document de plus de 100 lignes dans le contexte EAGER est un suspect. Il mérite un audit. Pas une condamnation — un audit. Et la question n&amp;amp;#8217;est jamais « faut-il le supprimer ? » mais « faut-il le charger à chaque session ? »&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_guide_pour_auditer_votre_propre_contexte&amp;quot;&amp;gt;Le guide pour auditer votre propre contexte&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Si vous avez suivi les deux premiers articles et mis en place votre propre gouvernance Eager/Lazy, voici une procédure d&amp;amp;#8217;audit en cinq étapes :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Mesurer&amp;lt;/strong&amp;gt; : &amp;lt;code&amp;gt;wc -l&amp;lt;/code&amp;gt; sur tous vos fichiers EAGER. Le total devrait être sous 1000 lignes.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Identifier le plus gros&amp;lt;/strong&amp;gt; : le fichier qui pèse plus de 20% du total est le suspect numéro un.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Auditer section par section&amp;lt;/strong&amp;gt; : pour chaque section, demandez-vous « Est-ce que cette information est déjà ailleurs ? Est-ce que l&amp;amp;#8217;agent l&amp;amp;#8217;a déjà lue dans un autre fichier ? Est-ce qu&amp;amp;#8217;elle a servi dans les 5 dernières sessions ? »&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Classifier&amp;lt;/strong&amp;gt; : doublon, jamais utilisé, connaissance unique.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Splitter ou relocaliser&amp;lt;/strong&amp;gt; : ce qui est unique et critique → ESSENTIALS compacté. Tout le reste → &amp;lt;code&amp;gt;encyclopedies/&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-audit-checklist&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-5bc9a34fb18adeac0f7da7af8a309acd.svg&amp;quot; alt=&amp;quot;Procédure d&amp;amp;#8217;audit en 5 étapes&amp;quot; width=&amp;quot;430&amp;quot; height=&amp;quot;741&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Cette procédure prend 15 minutes. Sur un projet de 50 sessions, elle économise des centaines de tokens par session future. Le ROI est immédiat.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_une_gouvernance_vivante&amp;quot;&amp;gt;Une gouvernance vivante&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce que cette série de trois articles m&amp;amp;#8217;a appris, c&amp;amp;#8217;est que la gouvernance agent n&amp;amp;#8217;est pas un produit fini. C&amp;amp;#8217;est un &amp;lt;strong&amp;gt;organisme vivant&amp;lt;/strong&amp;gt;. Elle grandit avec le projet. Elle attrape des maladies de croissance. Elle nécessite des check-ups réguliers.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La session 048 a révélé que les archives gonflent. La session 051 a révélé que la méthodologie elle-même gonfle. La session 060 révélera probablement autre chose. C&amp;amp;#8217;est normal. C&amp;amp;#8217;est sain. Une gouvernance qui ne se remet jamais en question est une gouvernance morte.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Les trois mécanismes mis en place — Eager/Lazy, Hot/Warm/Cold, split encyclopédique — forment un système de défense en profondeur contre la saturation du contexte. Aucun n&amp;amp;#8217;est suffisant seul. Ensemble, ils se complètent :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Eager/Lazy&amp;lt;/strong&amp;gt; structure l&amp;amp;#8217;information &amp;lt;strong&amp;gt;par disponibilité&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Hot/Warm/Cold&amp;lt;/strong&amp;gt; structure l&amp;amp;#8217;information &amp;lt;strong&amp;gt;par fraîcheur&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Audit encyclopédique&amp;lt;/strong&amp;gt; structure l&amp;amp;#8217;information &amp;lt;strong&amp;gt;par densité&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-defense-in-depth&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-c815b1bc714a7df30a365994ac557d7d.svg&amp;quot; alt=&amp;quot;Les trois couches de défense contre la saturation du contexte&amp;quot; width=&amp;quot;672&amp;quot; height=&amp;quot;345&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avec ces trois couches, le contexte agent sur &amp;lt;code&amp;gt;magic-stick&amp;lt;/code&amp;gt; est passé de 2087 lignes (avant toute optimisation) à environ 800 lignes — une division par 2,6. Sans avoir perdu une seule ligne de documentation, une seule archive de session, une seule leçon apprise.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Tout est là. Juste mieux rangé.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_liens&amp;quot;&amp;gt;Liens&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Article 0108 — Stratégie Eager/Lazy : &amp;lt;a href=&amp;quot;/blog/2026/0108_gouvernance_agent_opencode_eager_lazy_post.html&amp;quot;&amp;gt;Gouverner un Agent IA avec du AsciiDoc&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Article 0110 — Mécanisme Hot/Warm/Cold : &amp;lt;a href=&amp;quot;/blog/2026/0110_mecanisme_backup_contexte_agent_post.html&amp;quot;&amp;gt;Sliding Window et Vague Froide&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Mon site : &amp;lt;a href=&amp;quot;https://cheroliv.com&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://cheroliv.com&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le projet &amp;lt;code&amp;gt;magic-stick&amp;lt;/code&amp;gt; : &amp;lt;a href=&amp;quot;https://github.com/cheroliv/magic-stick&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://github.com/cheroliv/magic-stick&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;La connaissance n&amp;amp;#8217;a pas à disparaître. Elle a juste à ne pas être chargée quand elle n&amp;amp;#8217;est pas nécessaire.&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Sliding Window et Vague Froide : Quand le Contexte Agent Explose et qu&#39;il Faut Archiver sans Perdre</title>
            <link >https://cheroliv.com/blog/2026/0110_mecanisme_backup_contexte_agent_post.html</link>
            <pubDate>Sun, 26 Apr 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0110_mecanisme_backup_contexte_agent_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_résumé&amp;quot;&amp;gt;Résumé&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Après 48 sessions sur un seul projet et 150+ au total, le système de gouvernance Eager/Lazy que j&amp;amp;#8217;avais construit avec soin commençait à s&amp;amp;#8217;étouffer. Les fichiers agents, censés être légers, pesaient 5200 lignes cumulées. Le contexte auto-chargé montait plus vite que ma capacité à le contrôler. Cet article raconte comment j&amp;amp;#8217;ai conceptualisé un mécanisme de backup — entre sliding window et vague froide identique — pour maintenir un contexte actif léger sans jamais rien perdre.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_signal_5200_lignes&amp;quot;&amp;gt;Le Signal : 5200 Lignes&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Je suis en pleine session 048 sur &amp;lt;code&amp;gt;magic-stick&amp;lt;/code&amp;gt;, mon projet de build d&amp;amp;#8217;ISO Linux live. Opencode me regarde. Comme toujours, il a chargé automatiquement mes fichiers Eager en début de session — &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PROMPT_REPRISE.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.agents/INDEX.adoc&amp;lt;/code&amp;gt;. Rien d&amp;amp;#8217;anormal.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Sauf que quelque chose cloche. Les réponses sont plus lentes. Le raisonnement est plus dilué. L&amp;amp;#8217;agent oublie des détails qu&amp;amp;#8217;il avait sous les yeux il y a deux messages.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ouvre un terminal et je tape :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;wc -l .agents/INDEX.adoc .agents/SESSIONS_HISTORY.adoc \
  .agents/archives/COMPLETED_TASKS_ARCHIVE_2026-04.adoc&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;260 lignes pour INDEX. 55 pour SESSIONS_HISTORY. &amp;lt;strong&amp;gt;1756 pour COMPLETED_TASKS_ARCHIVE&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le dossier &amp;lt;code&amp;gt;sessions/&amp;lt;/code&amp;gt; ajoute encore ~3200 lignes. Total : &amp;lt;strong&amp;gt;5200 lignes&amp;lt;/strong&amp;gt; de contexte qui se chargent, d&amp;amp;#8217;une manière ou d&amp;amp;#8217;une autre, dans le cerveau temporaire de l&amp;amp;#8217;agent.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La stratégie Eager/Lazy que j&amp;amp;#8217;avais théorisée à l&amp;amp;#8217;article précédent fonctionne — mais elle a un défaut de naissance que je n&amp;amp;#8217;avais pas anticipé : elle n&amp;amp;#8217;a &amp;lt;strong&amp;gt;pas de mécanisme de vieillissement&amp;lt;/strong&amp;gt;. Chaque session ajoute une ligne à INDEX, un paragraphe à COMPLETED_TASKS, un fichier dans sessions/. Rien ne sort jamais. Le contexte est une boule de neige qui grossit à chaque nouvelle session.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-growth&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-95c83a721c5c943661137fb4c7f9bc23.svg&amp;quot; alt=&amp;quot;Courbe de croissance des fichiers agents — de la session 1 à 48&amp;quot; width=&amp;quot;427&amp;quot; height=&amp;quot;591&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce n&amp;amp;#8217;est pas un bug, c&amp;amp;#8217;est une conséquence directe de la procédure de fin de session qui archive méticuleusement chaque détail. Le système est victime de son propre succès.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_diagnostic_triple_redondance&amp;quot;&amp;gt;Le Diagnostic : Triple Redondance&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Je demande à l&amp;amp;#8217;agent de diagnostiquer le problème. Sa réponse est immédiate et chirurgicale.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Fichier&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Lignes&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Rôle&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Problème&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;.agents/INDEX.adoc&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;260+&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;EAGER (chargé auto)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Table de toutes les sessions depuis la 001 — &amp;lt;strong&amp;gt;+1 ligne par session&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;.agents/SESSIONS_HISTORY.adoc&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;55&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;EAGER&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Table récapitulative — &amp;lt;strong&amp;gt;redondance avec INDEX&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;COMPLETED_TASKS_ARCHIVE_2026-04.adoc&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;1756&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;EAGER (implicite)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Détails complets de toutes les sessions d&amp;amp;#8217;avril&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;.agents/sessions/*.adoc&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;~5200 total&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;LAZY (supposé)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Archives individuelles, mais &amp;lt;strong&amp;gt;pas utilisées&amp;lt;/strong&amp;gt; car tout est déjà dans COMPLETED_TASKS&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;agent identifie quatre causes racines :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;COMPLETED_TASKS_ARCHIVE absorbe tout&amp;lt;/strong&amp;gt; — Au lieu de pointer vers les archives &amp;lt;code&amp;gt;.sessions/&amp;lt;/code&amp;gt;, il recopie intégralement chaque session.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;INDEX.adoc fait office d&amp;amp;#8217;historique complet&amp;lt;/strong&amp;gt; — Le tableau &amp;quot;Sessions Récentes&amp;quot; contient 30+ entrées.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;SESSIONS_HISTORY.adoc redondant&amp;lt;/strong&amp;gt; — Même info que INDEX, format différent.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;La règle LAZY n&amp;amp;#8217;est pas respectée&amp;lt;/strong&amp;gt; — COMPLETED_TASKS est implicitement EAGER car il contient tout.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Sa proposition est radicale : limiter INDEX à 10 sessions, vider COMPLETED_TASKS, déplacer SESSIONS_HISTORY en LAZY pur. Gain immédiat : &amp;lt;strong&amp;gt;~1900 lignes économisées&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est propre, efficace, logique. Mais j&amp;amp;#8217;ai un problème avec cette approche.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_pourquoi_jai_refusé_la_solution_évidente&amp;quot;&amp;gt;Pourquoi J&amp;amp;#8217;ai Refusé la Solution Évidente&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La solution de l&amp;amp;#8217;agent est celle d&amp;amp;#8217;un ingénieur qui optimise un cache. Limiter. Tronquer. Supprimer les redondances.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mais ces &amp;quot;redondances&amp;quot; n&amp;amp;#8217;en sont pas. Chaque fichier de gouvernance capture un &amp;lt;strong&amp;gt;angle différent&amp;lt;/strong&amp;gt; sur la même réalité :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;INDEX&amp;lt;/strong&amp;gt; = vue macro, tableau de bord exécutif&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;SESSIONS_HISTORY&amp;lt;/strong&amp;gt; = table chronologique linéaire, scorée&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;COMPLETED_TASKS_ARCHIVE&amp;lt;/strong&amp;gt; = narrative détaillée avec métriques&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;sessions/*.adoc&amp;lt;/strong&amp;gt; = archives individuelles, contexte complet&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce n&amp;amp;#8217;est pas de la duplication bête. C&amp;amp;#8217;est de la &amp;lt;strong&amp;gt;perspective multiple structurée&amp;lt;/strong&amp;gt;. C&amp;amp;#8217;est exactement ce dont on a besoin pour distiller — pour que plus tard, un humain (ou un futur LLM mieux entraîné) puisse croiser les angles et extraire des patterns.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Imaginez un data scientist qui vous dit : « Supprimons 3 colonnes sur 6, elles sont corrélées. » Vous lui répondez quoi ? Que la corrélation n&amp;amp;#8217;est pas de la redondance quand chaque colonne capture une dimension différente du même phénomène. Que c&amp;amp;#8217;est précisément cette richesse dimensionnelle qui rend le dataset exploitable.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est mon intuition. Et je la défends contre la rationalité froide de l&amp;amp;#8217;agent.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&amp;lt;em&amp;gt;_ Je ne vois pas de fourre-tout silencieux dans mon idée. On ne fourre pas tout, on déplace le résultat structuré de la procédure de fin de session — chaque fichier avec son angle, ses redondances qui sont en réalité un enrichissement. C&amp;amp;#8217;est ce matériel multidimensionnel qui sera meilleur pour la distillation. &amp;lt;/em&amp;gt;_&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;agent accuse le coup. Et se corrige.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_proposition_vague_froide_identique&amp;quot;&amp;gt;La Proposition : Vague Froide Identique&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;agent propose alors un mécanisme plus fin, qui respecte mon intuition de dataset riche tout en résolvant le problème technique du contexte qui explose.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le principe est simple et s&amp;amp;#8217;inspire directement du pattern &amp;lt;strong&amp;gt;Hot/Warm/Cold Storage&amp;lt;/strong&amp;gt; appliqué à la gestion d&amp;amp;#8217;archives :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Hot (EAGER)&amp;lt;/strong&amp;gt; = les 10 dernières sessions dans INDEX, PROMPT_REPRISE de la session N+1, les 2 derniers fichiers de session&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Warm (LAZY)&amp;lt;/strong&amp;gt; = SESSIONS_HISTORY récent, SCRIPT_VERIFICATION, toute la documentation de référence&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Cold (backup/)&amp;lt;/strong&amp;gt; = tout le reste, déplacé &amp;lt;strong&amp;gt;intact&amp;lt;/strong&amp;gt;, sans transformation, sans réindexation&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code&amp;gt;----
.agents/
├── INDEX.adoc                         → Sessions N-9 à N (10 dernières)
├── SESSIONS_HISTORY.adoc              → Sessions N-9 à N
├── SCRIPT_VERIFICATION.adoc           → Dernière vérif (pas d&amp;#39;historique)
├── PROMPT_REPRISE.adoc                → Session N+1 uniquement
├── sessions/                          → Sessions N-1 à N uniquement
└── backup/
    └── Y2026-sessions-001-039/          ← Vague froide, COPIE INTÉGRALE
        ├── INDEX.adoc                  → Sessions 001 à 039 (complet)
        ├── SESSIONS_HISTORY.adoc       → Sessions 001 à 039 (complet)
        ├── COMPLETED_TASKS_ARCHIVE.adoc → Sessions 001 à 039 (complet)
        └── sessions/                   → 001.adoc, 002.adoc...
----

La clé du mécanisme : **le backup n&amp;#39;est pas un index central, c&amp;#39;est une copie conforme de la vague passée**. Quand on dépasse l&amp;#39;horizon des 10 sessions actives, on ne supprime rien. On ne réindexe rien. On ne fusionne rien. On prend le paquet de fichiers agents tel qu&amp;#39;il était à la session N-10, et on le déplace dans `backup/`.

Les fichiers actifs, eux, sont tronqués :

* INDEX : uniquement les 10 dernières lignes (sliding window)
* SESSIONS_HISTORY : idem
* COMPLETED_TASKS_ARCHIVE : nouveau fichier pour la période en cours
* sessions/ : uniquement les 2 dernières sessions

[plantuml, format=svg, id=diag-hot-warm-cold, alt=&amp;quot;Architecture Hot/Warm/Cold du contexte agent — EAGER/LAZY/backup&amp;quot;]
----
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam wrapWidth 200

title Architecture Hot / Warm / Cold du Contexte Agent

package &amp;quot;HOT (EAGER)\nChargé automatiquement\n~300 lignes&amp;quot; as HOT #FFCDD2 {
  file &amp;quot;INDEX.adoc\n(10 sessions)&amp;quot; as IDX_HOT
  file &amp;quot;PROMPT_REPRISE\n(session N+1)&amp;quot; as PRO_HOT
  file &amp;quot;AGENT.adoc\n(règles absolues)&amp;quot; as AG_HOT
}

package &amp;quot;WARM (LAZY)\nChargé sur demande\n~500 lignes&amp;quot; as WARM #FFF9C4 {
  file &amp;quot;SESSIONS_HISTORY\n(10 dernières)&amp;quot; as HIS_WARM
  file &amp;quot;SCRIPT_VERIFICATION\n(dernière)&amp;quot; as VER_WARM
  file &amp;quot;PROCEDURES.adoc\n(templates)&amp;quot; as PRO_WARM
  file &amp;quot;*_REFERENCE.adoc\n(doc technique)&amp;quot; as REF_WARM
}

package &amp;quot;COLD (backup/)\nJamais chargé\nLecture humaine uniquement&amp;quot; as COLD #BBDEFB {
  folder &amp;quot;Y2026-001-039/&amp;quot; as WAVE {
    file &amp;quot;INDEX (complet)&amp;quot; as IDX_COLD
    file &amp;quot;SESSIONS_HISTORY\n(complet)&amp;quot; as HIS_COLD
    file &amp;quot;COMPLETED_TASKS\n(complet)&amp;quot; as ARCH_COLD
    folder &amp;quot;sessions/ (001-039)&amp;quot; as SESS_COLD
  }
  folder &amp;quot;Y2026-040-???\n(future)&amp;quot; as FUTURE
}

HOT --&amp;amp;gt; WARM : &amp;quot;Agent remonte\nsi besoin&amp;quot;
WARM --&amp;amp;gt; COLD : &amp;quot;Jamais automatique\nL&amp;#39;humain y va seul&amp;quot;

note bottom of COLD
  Règle : COPIE INTÉGRALE
  Pas de transformation
  Pas de réindexation
  Read-only après archivage
end note

@enduml
----

Le gain immédiat est massif : le contexte EAGER passe de **~5200 lignes à ~300 lignes**. Une division par 17. Sans avoir perdu une seule ligne de données historiques.

== Pourquoi Ce N&amp;#39;est Pas un Fourre-Tout

L&amp;#39;agent, dans sa première itération, craignait que `backup/` devienne une boîte noire — un dossier où l&amp;#39;on jette des fichiers qu&amp;#39;on ne relira jamais. C&amp;#39;est une peur légitime. Mais elle repose sur une confusion.

Un fourre-tout, c&amp;#39;est quand on jette des fichiers **sans structure, sans convention, sans logique de regroupement**. Ici, le backup est structuré par période (Y2026-001-039), et chaque dossier de backup contient **la même structure** que le dossier `.agents/` actif : INDEX, SESSIONS_HISTORY, COMPLETED_TASKS_ARCHIVE, sessions/.

Ce n&amp;#39;est pas un fourre-tout. C&amp;#39;est un **snapshot horodaté**. On pourrait même dire que c&amp;#39;est un mécanisme de versioning simplifié — à ceci près qu&amp;#39;il ne versionne pas les fichiers individuellement, mais le paquet complet de la gouvernance à un instant T.

Quand vous voulez retrouver une information ancienne, vous n&amp;#39;avez pas besoin d&amp;#39;un index central. Vous avez deux options :

1. **`grep` ciblé** : `grep -r &amp;quot;zsh&amp;quot; backup/Y2026-001-039/` — et vous trouvez tout ce qui mentionne zsh dans la période, quel que soit l&amp;#39;angle (INDEX, SESSIONS_HISTORY, archive de session).
2. **Réintégration manuelle** : vous copiez temporairement le dossier de backup dans le contexte actif, et vous demandez à l&amp;#39;agent d&amp;#39;analyser cette période spécifique.

L&amp;#39;index est implicite. Il est dans la structure même des fichiers — chacun étant déjà un index depuis son propre angle.

== La Méthaphore des Étagères

Pour rendre le mécanisme intuitif, je l&amp;#39;ai conceptualisé en trois étagères :

* **Étagère 1 (EAGER)** — le plan de travail. Ce dont j&amp;#39;ai besoin *maintenant*. INDEX récent, PROMPT_REPRISE, règles absolues. Léger, immédiat, critique.
* **Étagère 2 (LAZY)** — la bibliothèque de consultation. Ce que je peux aller chercher sur demande. Références techniques, historique récent, procédures. Plus volumineux, mais pas chargé en mémoire.
* **Cave (backup/)** — les archives froides. Tout ce qui est passé mais que je ne veux pas jeter. L&amp;#39;agent n&amp;#39;y entre jamais. L&amp;#39;humain y descend quand il veut distiller.

L&amp;#39;agent a proposé initialement une quatrième étagère — un `index-backup.adoc` qui serait LAZY et contiendrait une table des matières de tout le backup. J&amp;#39;ai refusé. Ce serait une redondance de plus dans un système qui souffre déjà de croissance linéaire. La structure des fichiers archivés est déjà un index.

== Le Capteur à Deux Déclencheurs

La conceptualisation était solide, mais il restait un angle mort : **quand exactement déclencher la rotation ?** L&amp;#39;article initial l&amp;#39;identifiait comme une question ouverte. Deux jours plus tard, la réponse est codifiée dans les fichiers de gouvernance de six projets : un capteur à deux déclencheurs.

=== Le Déclencheur Automatique — `N % 10 == 0`

Le premier déclencheur est mathématique. Quand le numéro de session est un multiple de 10 — session 10, 20, 30, 40 — la rotation backup s&amp;#39;exécute automatiquement au sein de la procédure de fin de session, juste après l&amp;#39;étape 6.

Pourquoi 10 ? C&amp;#39;est le compromis entre deux forces contraires : une fenêtre trop courte (5 sessions) perd le contexte nécessaire à la continuité ; une fenêtre trop longue (20 sessions) ne résout pas le problème d&amp;#39;embonpoint du contexte. Dix sessions, sur un rythme de une à deux sessions par jour, couvrent environ une semaine de travail — assez pour que l&amp;#39;agent se souvienne des décisions récentes, pas assez pour que le contexte explose.

=== Le Déclencheur par Seuil — 500 Lignes EAGER

Le second déclencheur est dynamique. Indépendamment du numéro de session, si les fichiers EAGER cumulés dépassent **500 lignes**, la rotation se déclenche.

Ce seuil protège contre le scénario où les sessions sont exceptionnellement productives — beaucoup de contenu écrit en peu de sessions. Une session qui produit 120 lignes de contenu éditorial fait grossir COMPLETED_TASKS_ARCHIVE bien plus vite qu&amp;#39;une session de debug qui corrige deux lignes. Le seuil de 500 lignes, mesuré via `wc -l .agents/INDEX.adoc .agents/archives/COMPLETED_TASKS_ARCHIVE_*.adoc PROMPT_REPRISE.adoc`, capte cette asymétrie.

=== Le Déclencheur Manuel — &amp;quot;rotation backup&amp;quot;

Enfin, l&amp;#39;humain garde la main. Les mots-clés `rotation backup`, `backup rotation` ou `lance la rotation backup` déclenchent la procédure sur demande, indépendamment de la fin de session. Utile quand on sent que le contexte devient lourd mais qu&amp;#39;on n&amp;#39;est pas encore à un multiple de 10, ou quand on veut archiver une phase de travail avant d&amp;#39;en commencer une nouvelle.

[plantuml, format=svg, id=diag-capteur-trigger, alt=&amp;quot;Les trois déclencheurs du capteur de rotation backup — automatique, seuil, manuel&amp;quot;]
----
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam wrapWidth 200

title Capteur de Rotation Backup — Les Trois Déclencheurs

start

:Procédure de fin de session;
note right: Mots-clés &amp;quot;fin de session&amp;quot;\nou &amp;quot;on arrête là&amp;quot;

:Étapes 1 à 6\n(archivage standard);
note right
  1. Archive sessions/N.adoc
  2. MAJ PROMPT_REPRISE
  3. MAJ SESSIONS_HISTORY
  4. MAJ INDEX.adoc
  5. MAJ TEST_COVERAGE
  6. MAJ COMPLETED_TASKS
end note

if (N % 10 == 0\nOU\nEAGER cumulé &amp;amp;gt; 500 lignes ?) then (oui)
  :⚙️ Rotation Backup\n(étape 7);
  note right
    1. Créer backup/Y20XX-sessions-X-Y/
    2. Copier intégrale INDEX + HISTORY
       + COMPLETED_TASKS + sessions/
    3. Tronquer actifs à 10 sessions
    4. Ajouter _Localisation active_
  end note
else (non)
  :Pas de rotation;
endif

:Checklist [✅] x 7\n(si applicable);

stop

@enduml
----

Ce diagramme montre l&amp;#39;insertion exacte du capteur dans la procédure de fin de session. L&amp;#39;étape 7 est optionnelle — elle ne s&amp;#39;exécute que si une des deux conditions est vraie — mais elle est systématiquement *vérifiée*. La checklist finale inclut `[✅] 7. Backup roté (si applicable)`.

=== La Boucle Fermée

Ce capteur referme la boucle ouverte par l&amp;#39;article précédent. La gouvernance Eager/Lazy avait résolu le problème de la mémoire agent entre deux sessions. Le mécanisme Hot/Warm/Cold a résolu le problème de la mémoire qui grossit. Le capteur à deux déclencheurs résout le problème du *quand* — retirant à l&amp;#39;humain la charge mentale de surveiller la taille du contexte.

[plantuml, format=svg, id=diag-boucle-fermee, alt=&amp;quot;Les trois couches de la gouvernance agent — Eager/Lazy, Hot/Warm/Cold, Capteur&amp;quot;]
----
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center

title Les Trois Couches de la Gouvernance Agent

left to right direction

package &amp;quot;Couche 1 — Mémoire\n(Article 0108)&amp;quot; as C1 #E8F5E9 {
  rectangle &amp;quot;**EAGER**\nTableau de bord\nChargé auto&amp;quot; as EAG
  rectangle &amp;quot;**LAZY**\nManuel propriétaire\nChargé sur demande&amp;quot; as LAZ
  EAG -[hidden]right-&amp;amp;gt; LAZ
}

package &amp;quot;Couche 2 — Vieillissement\n(Article 0110)&amp;quot; as C2 #FFF9C4 {
  rectangle &amp;quot;**HOT**\n10 sessions actives\n~300 lignes&amp;quot; as HOT
  rectangle &amp;quot;**WARM**\nRéférences\nProcédures&amp;quot; as WRM
  rectangle &amp;quot;**COLD**\nbackup/\nVague froide&amp;quot; as CLD
  HOT -[hidden]right-&amp;amp;gt; WRM
  WRM -[hidden]right-&amp;amp;gt; CLD
}

package &amp;quot;Couche 3 — Déclencheur\n(Aujourd&amp;#39;hui)&amp;quot; as C3 #BBDEFB {
  rectangle &amp;quot;**Auto**\nN % 10 == 0&amp;quot; as AUTO
  rectangle &amp;quot;**Seuil**\n&amp;amp;gt; 500 lignes&amp;quot; as SEUIL
  rectangle &amp;quot;**Manuel**\nrotation backup&amp;quot; as MAN
  AUTO -[hidden]right-&amp;amp;gt; SEUIL
  SEUIL -[hidden]right-&amp;amp;gt; MAN
}

C1 --&amp;amp;gt; C2 : &amp;quot;La mémoire grandit\n→ il faut un mécanisme\nde vieillissement&amp;quot;
C2 --&amp;amp;gt; C3 : &amp;quot;Le vieillissement\n→ il faut un déclencheur\npour l&amp;#39;exécuter&amp;quot;

note bottom of C3
  ✅ Déployé sur 6 projets
  magic-stick · bakery-gradle
  plantuml-gradle · cheroliv.com
  jhipster-gradle-plugins
  quizz-benchmark-gradle
end note

@enduml
----

Les trois couches s&amp;#39;empilent logiquement. La première donne une mémoire à l&amp;#39;agent. La deuxième empêche cette mémoire d&amp;#39;étouffer l&amp;#39;agent. La troisième automatise la maintenance de cette mémoire pour que l&amp;#39;humain n&amp;#39;ait pas à y penser.

=== La Migration Effective sur cheroliv.com

Le mécanisme n&amp;#39;est pas resté théorique. Sur `cheroliv.com`, la première rotation backup a été exécutée le 29 avril 2026 — les sessions -6 à 2 ont migré vers `.agents/backup/Y2026-sessions-neg6-a-002/` :

|===
|Fichier |Avant rotation |Après rotation |Gain |`.agents/INDEX.adoc` |19 sessions listées |10 sessions (3-12) |-9 entrées |`.agents/SESSIONS_HISTORY.adoc` |18 sessions |10 sessions |-8 entrées |`COMPLETED_TASKS_ARCHIVE` |161 lignes (sessions 1-12) |135 lignes (sessions 3-12) |-26 lignes |`sessions/` |20 fichiers |10 fichiers |-10 fichiers |**backup/** |Inexistant |1 vague froide (10 sessions archivées) |+1 paquet froid
|===

Le gain en lignes était modeste — le projet est jeune, 12 sessions — mais l&amp;#39;important est que le **mécanisme est en place**. La prochaine rotation automatique se déclenchera à la session 20, ou plus tôt si les 500 lignes EAGER sont atteintes.

== La Leçon Humain-Agent

Cette session 048 m&amp;#39;a appris quelque chose de fondamental sur la collaboration avec un agent IA.

L&amp;#39;agent a un biais naturel : il cherche à **optimiser**, à **simplifier**, à **éliminer les redondances**. C&amp;#39;est le biais d&amp;#39;un système entraîné à produire des réponses propres et concises. Face à un dataset riche et multidimensionnel, son premier réflexe est de le réduire à sa plus simple expression.

L&amp;#39;humain, lui, a une intuition différente : il pressent que la redondance structurée est un **atout**, pas un défaut. Que la diversité des angles sur une même réalité est précisément ce qui permettra, plus tard, une distillation de qualité.

Ce n&amp;#39;est pas que l&amp;#39;agent a tort. C&amp;#39;est que son &amp;quot;optimum&amp;quot; n&amp;#39;est pas le mien. L&amp;#39;agent optimise pour le **présent** — le contexte immédiat, la réponse rapide à la question posée. L&amp;#39;humain optimise pour le **futur** — la capacité à retrouver, croiser, distiller dans trois mois ou trois ans.

____ Ce que je veux, c&amp;#39;est le matériel brut. Tes réflexions, tes hésitations, tes réponses à mes questions. Pas ta synthèse. La synthèse, je sais la faire mieux que toi. Je veux la matière première. ____

Cette phrase que je lui ai dite en fin de session résume tout. L&amp;#39;agent est un outil de production. L&amp;#39;humain est l&amp;#39;outil de distillation. La gouvernance n&amp;#39;est pas faite pour que l&amp;#39;agent comprenne tout tout seul — elle est faite pour que l&amp;#39;humain puisse, plus tard, travailler le matériau produit.

La vague froide identique est la traduction architecturale de cette philosophie : on ne jette rien, on ne fusionne rien, on ne réindexe rien. On déplace le paquet intact. La distillation viendra plus tard, à la main, par l&amp;#39;humain.

== La Suite Logique de l&amp;#39;Article Précédent

Si vous avez lu link:/blog/2026/0108_gouvernance_agent_opencode_eager_lazy_post.html[l&amp;#39;article sur la stratégie Eager/Lazy], vous reconnaîtrez la progression naturelle :

1. **Article 0108** — La gouvernance Eager/Lazy : *comment* structurer le contexte agent en deux niveaux de disponibilité
2. **Cet article 0110** — Le mécanisme de backup : *comment* faire vieillir ce contexte sans le perdre quand il devient trop volumineux

Le premier article répondait à la question : « L&amp;#39;agent ne se souvient de rien entre deux sessions, comment lui donner une mémoire ? »

Celui-ci répond à la question qui découle inévitablement de la première : « La mémoire grossit à chaque session, comment l&amp;#39;empêcher d&amp;#39;étouffer l&amp;#39;agent sans l&amp;#39;effacer ? »

La réponse tient en un pattern : **Hot/Warm/Cold**, appliqué aux fichiers de gouvernance. Et en un principe : **ne jamais rien perdre, toujours tout relocaliser**.

== Liens

* Article précédent : link:/blog/2026/0108_gouvernance_agent_opencode_eager_lazy_post.html[Gouverner un Agent IA avec du AsciiDoc]
* Mon site : https://cheroliv.com
* Le projet `magic-stick` : https://github.com/cheroliv/magic-stick

---

*Un bon système de gouvernance ne supprime jamais de données. Il les range.*&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Quand Gradle 9, Docker 29 et Testcontainers se mettent la rate au court-bouillon : debugging d&#39;un build JHipster</title>
            <link >https://cheroliv.com/blog/2026/0109_gradle_jhipster_docker_testcontainers_debugging_post.html</link>
            <pubDate>Sat, 25 Apr 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0109_gradle_jhipster_docker_testcontainers_debugging_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_scène_un_projet_jhipster_un_build_qui_ne_charge_plus&amp;quot;&amp;gt;La scène : un projet JHipster, un build qui ne charge plus&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_erreur_1_la_variable_fantôme_reportsdir&amp;quot;&amp;gt;Erreur 1 : la variable fantôme &amp;lt;code&amp;gt;reportsDir&amp;lt;/code&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_erreur_2_main_nexiste_plus_sous_gradle_9&amp;quot;&amp;gt;Erreur 2 : &amp;lt;code&amp;gt;main = &amp;quot;&amp;amp;#8230;&amp;amp;#8203;&amp;quot;&amp;lt;/code&amp;gt; n&amp;amp;#8217;existe plus sous Gradle 9&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_erreur_3_sourcecompatibility_nest_plus_une_propriété_de_projet&amp;quot;&amp;gt;Erreur 3 : &amp;lt;code&amp;gt;sourceCompatibility&amp;lt;/code&amp;gt; n&amp;amp;#8217;est plus une propriété de projet&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_erreur_4_lassertion_groovy_à_trois_opérandes&amp;quot;&amp;gt;Erreur 4 : l&amp;amp;#8217;assertion Groovy à trois opérandes&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_erreur_5_la_dépendance_implicite_compilekotlin_openapigenerate&amp;quot;&amp;gt;Erreur 5 : la dépendance implicite &amp;lt;code&amp;gt;compileKotlin&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;openApiGenerate&amp;lt;/code&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_erreur_6_generategitproperties_casse_sur_filteroutputstream_write&amp;quot;&amp;gt;Erreur 6 : &amp;lt;code&amp;gt;generateGitProperties&amp;lt;/code&amp;gt; casse sur &amp;lt;code&amp;gt;FilterOutputStream.write()&amp;lt;/code&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_enfin_testcontainers_entre_en_scène&amp;quot;&amp;gt;Enfin : Testcontainers entre en scène&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_phase_1_la_piste_docker_java&amp;quot;&amp;gt;Phase 1 : la piste docker-java&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_phase_2_recherche_web_et_fil_dariane_github&amp;quot;&amp;gt;Phase 2 : recherche web et fil d&amp;amp;#8217;ariane GitHub&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_phase_3_le_piège_des_artifacts_renommés&amp;quot;&amp;gt;Phase 3 : le piège des artifacts renommés&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_phase_4_forcer_la_résolution&amp;quot;&amp;gt;Phase 4 : forcer la résolution&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_résultat_final&amp;quot;&amp;gt;Résultat final&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_tableau_récapitulatif_des_corrections&amp;quot;&amp;gt;Tableau récapitulatif des corrections&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_conclusion&amp;quot;&amp;gt;Conclusion&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 15 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Vous avez déjà connu ce moment où un simple &amp;lt;code&amp;gt;./gradlew build&amp;lt;/code&amp;gt; que vous lancez cent fois par jour se met soudain à planter sur une erreur jamais vue ? Multipliez ça par onze erreurs successives, ajoutez une bonne dose d&amp;amp;#8217;incompatibilité Docker Engine 29, saupoudrez de Gradle 9 qui fait disparaître des API qu&amp;amp;#8217;on utilisait depuis dix ans. Voici le carnet de bord complet.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Diagramme 1 — Migration Gradle 9 (chaîne d’erreurs)&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Objectif : montrer la série d’incompatibilités.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-6215da1a3f4f27918205b5c8ff34a48c.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;579&amp;quot; height=&amp;quot;106&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Figure 1. 👉 Clair, centré sur Gradle.&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Diagramme 2 — Plugins JHipster incompatibles&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Objectif : isoler les plugins cassés.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-07ed01d932957e366cd8fed4b8aee2a3.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;569&amp;quot; height=&amp;quot;123&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Figure 2. 👉 Vision propre des dépendances.&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Diagramme 3 — Docker 29 / Testcontainers&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Objectif : problème runtime.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-544e3a93289a5db5b898714292d384f4.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;788&amp;quot; height=&amp;quot;123&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Figure 3. 👉 Histoire claire du runtime.&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-5d4d1754844f7121ef284aa0cc588011.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;1072&amp;quot; height=&amp;quot;193&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Figure 4. une autre maniere de se le representer&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_scène_un_projet_jhipster_un_build_qui_ne_charge_plus&amp;quot;&amp;gt;La scène : un projet JHipster, un build qui ne charge plus&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le projet &amp;lt;code&amp;gt;edster&amp;lt;/code&amp;gt; est une application JHipster générée en 2024. Le build script racine &amp;lt;code&amp;gt;build.gradle&amp;lt;/code&amp;gt; est resté stable pendant des mois. Puis on décide de monter en version :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1428%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 7.1436%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Composant&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Version cible&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Gradle&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;9.4.1&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Java&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;21.0.11-tem (Eclipse Temurin)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;JHipster&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;8.x (framework &amp;lt;code&amp;gt;tech.jhipster:jhipster-framework:8.11.0&amp;lt;/code&amp;gt;)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Spring Boot&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;3.4.5&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Kotlin&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;2.3.0&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Docker Engine&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;29.4.1 (API 1.54)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le changement de version Java passe via SDKMAN :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;sdk use java 21.0.11-tem&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Premier lancement :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ ./gradlew build --no-daemon

FAILURE: Build failed with an exception.

* Where:
Build file &amp;#39;/home/.../edster/build.gradle&amp;#39; line: 18

* What went wrong:
An exception occurred applying plugin request [id: &amp;#39;jhipster.cucumber-conventions&amp;#39;]
&amp;amp;gt; Failed to apply plugin &amp;#39;jhipster.cucumber-conventions&amp;#39;.
   &amp;amp;gt; Could not create task &amp;#39;:cucumberTest&amp;#39;.
      &amp;amp;gt; Could not create task &amp;#39;:consoleLauncherTest&amp;#39;.
         &amp;amp;gt; Could not set unknown property &amp;#39;reportsDir&amp;#39; for task &amp;#39;:consoleLauncherTest&amp;#39;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;On ne décolle même pas du chargement du build script. Le problème est dans &amp;lt;code&amp;gt;buildSrc/src/main/groovy/jhipster.cucumber-conventions.gradle&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_erreur_1_la_variable_fantôme_reportsdir&amp;quot;&amp;gt;Erreur 1 : la variable fantôme &amp;lt;code&amp;gt;reportsDir&amp;lt;/code&amp;gt;&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le script &amp;lt;code&amp;gt;jhipster.cucumber-conventions.gradle&amp;lt;/code&amp;gt; contient :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-groovy hljs&amp;quot; data-lang=&amp;quot;groovy&amp;quot;&amp;gt;tasks.register(&amp;#39;consoleLauncherTest&amp;#39;, JavaExec) {
    dependsOn(testClasses)
    String cucumberReportsDir = file(&amp;quot;$buildDir/reports/tests&amp;quot;)
    outputs.dir(reportsDir)           // &amp;amp;lt;-- reportsDir n&amp;#39;existe PAS
    classpath = sourceSets[&amp;quot;test&amp;quot;].runtimeClasspath
    main = &amp;quot;org.junit.platform.console.ConsoleLauncher&amp;quot;
    // ...
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La variable définie est &amp;lt;code&amp;gt;cucumberReportsDir&amp;lt;/code&amp;gt;. Celle utilisée est &amp;lt;code&amp;gt;reportsDir&amp;lt;/code&amp;gt;&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;qui n&amp;amp;#8217;est définie nulle part.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Correction&amp;lt;/strong&amp;gt; : &amp;lt;code&amp;gt;outputs.dir(cucumberReportsDir)&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_erreur_2_main_nexiste_plus_sous_gradle_9&amp;quot;&amp;gt;Erreur 2 : &amp;lt;code&amp;gt;main = &amp;quot;&amp;amp;#8230;&amp;amp;#8203;&amp;quot;&amp;lt;/code&amp;gt; n&amp;amp;#8217;existe plus sous Gradle 9&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Relance immédiate :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;Could not set unknown property &amp;#39;main&amp;#39; for task &amp;#39;:consoleLauncherTest&amp;#39; of type org.gradle.api.tasks.JavaExec.&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Gradle 9 supprime la propriété &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; au profit de &amp;lt;code&amp;gt;mainClass&amp;lt;/code&amp;gt; sur les tâches &amp;lt;code&amp;gt;JavaExec&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Correction&amp;lt;/strong&amp;gt; : &amp;lt;code&amp;gt;mainClass = &amp;quot;org.junit.platform.console.ConsoleLauncher&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_erreur_3_sourcecompatibility_nest_plus_une_propriété_de_projet&amp;quot;&amp;gt;Erreur 3 : &amp;lt;code&amp;gt;sourceCompatibility&amp;lt;/code&amp;gt; n&amp;amp;#8217;est plus une propriété de projet&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Nouvelle erreur :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;Could not set unknown property &amp;#39;sourceCompatibility&amp;#39; for root project &amp;#39;edster&amp;#39; of type org.gradle.api.Project.&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le script racine avait :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-groovy hljs&amp;quot; data-lang=&amp;quot;groovy&amp;quot;&amp;gt;sourceCompatibility=17
targetCompatibility=17&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Gradle 9 supprime ces propriétés au niveau root. Elles doivent vivre dans un bloc &amp;lt;code&amp;gt;java&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Correction&amp;lt;/strong&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-groovy hljs&amp;quot; data-lang=&amp;quot;groovy&amp;quot;&amp;gt;java {
    sourceCompatibility = JavaVersion.VERSION_21
    targetCompatibility = JavaVersion.VERSION_21
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_erreur_4_lassertion_groovy_à_trois_opérandes&amp;quot;&amp;gt;Erreur 4 : l&amp;amp;#8217;assertion Groovy à trois opérandes&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;ancien script contenait :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-groovy hljs&amp;quot; data-lang=&amp;quot;groovy&amp;quot;&amp;gt;assert System.properties[&amp;quot;java.specification.version&amp;quot;] == &amp;quot;17&amp;quot; || &amp;quot;21&amp;quot; || &amp;quot;24&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;En Groovy, &amp;lt;code&amp;gt;&amp;quot;21&amp;quot;&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;&amp;quot;24&amp;quot;&amp;lt;/code&amp;gt; sont des strings truthy. L&amp;amp;#8217;expression résout en &amp;lt;code&amp;gt;(&amp;amp;#8230;&amp;amp;#8203; == &amp;quot;17&amp;quot;) || true || true&amp;lt;/code&amp;gt;, ce qui est toujours vraie&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;mais la syntaxe est invalide pour l&amp;amp;#8217;assertion stricte souhaitée.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Correction&amp;lt;/strong&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-groovy hljs&amp;quot; data-lang=&amp;quot;groovy&amp;quot;&amp;gt;assert System.properties[&amp;quot;java.specification.version&amp;quot;] in [&amp;quot;17&amp;quot;, &amp;quot;21&amp;quot;, &amp;quot;23&amp;quot;, &amp;quot;24&amp;quot;]&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_erreur_5_la_dépendance_implicite_compilekotlin_openapigenerate&amp;quot;&amp;gt;Erreur 5 : la dépendance implicite &amp;lt;code&amp;gt;compileKotlin&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;openApiGenerate&amp;lt;/code&amp;gt;&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le build progresse. Compilation Kotlin réussie. Puis :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;Task &amp;#39;:compileKotlin&amp;#39; uses this output of task &amp;#39;:openApiGenerate&amp;#39;
without declaring an explicit or implicit dependency.&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Gradle 9 refuse les dépendances implicites entre tâches. Puisque &amp;lt;code&amp;gt;compileKotlin&amp;lt;/code&amp;gt; lit les sources générées par &amp;lt;code&amp;gt;openApiGenerate&amp;lt;/code&amp;gt;, il faut déclarer le lien.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Correction&amp;lt;/strong&amp;gt; dans &amp;lt;code&amp;gt;build.gradle&amp;lt;/code&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-groovy hljs&amp;quot; data-lang=&amp;quot;groovy&amp;quot;&amp;gt;afterEvaluate {
    tasks.named(&amp;quot;compileKotlin&amp;quot;).configure {
        dependsOn(tasks.named(&amp;quot;openApiGenerate&amp;quot;))
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le &amp;lt;code&amp;gt;afterEvaluate&amp;lt;/code&amp;gt; est nécessaire car &amp;lt;code&amp;gt;openApiGenerate&amp;lt;/code&amp;gt; est une extension (plugin OpenAPI Generator) et non une tâche directement accessible pendant la phase de configuration.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_erreur_6_generategitproperties_casse_sur_filteroutputstream_write&amp;quot;&amp;gt;Erreur 6 : &amp;lt;code&amp;gt;generateGitProperties&amp;lt;/code&amp;gt; casse sur &amp;lt;code&amp;gt;FilterOutputStream.write()&amp;lt;/code&amp;gt;&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La compilation Java passe. Les ressources sont processées. Puis :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;&amp;amp;gt; Task :generateGitProperties FAILED

No signature of method: java.io.FilterOutputStream.write() is applicable for argument types: (Integer) values: [103]&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le plugin &amp;lt;code&amp;gt;gradle-git-properties&amp;lt;/code&amp;gt; version 2.5.0 est incompatible avec Java 21 / Gradle 9. Un bug interne tente d&amp;amp;#8217;appeler &amp;lt;code&amp;gt;write(int)&amp;lt;/code&amp;gt; via Groovy sur un flux qui l&amp;amp;#8217;a fermé.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Correction&amp;lt;/strong&amp;gt; dans &amp;lt;code&amp;gt;gradle.properties&amp;lt;/code&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-properties hljs&amp;quot; data-lang=&amp;quot;properties&amp;quot;&amp;gt;gitPropertiesPluginVersion=2.5.7&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_enfin_testcontainers_entre_en_scène&amp;quot;&amp;gt;Enfin : Testcontainers entre en scène&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Jusqu&amp;amp;#8217;ici, c&amp;amp;#8217;était du &amp;quot;build script debugging&amp;quot; pur. Chaque erreur était une incompatibilité Gradle 9 ou Java 21 dans les scripts de build. Après les six corrections ci-dessus, le &amp;lt;code&amp;gt;./gradlew assemble&amp;lt;/code&amp;gt; passe avec succès.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mais &amp;lt;code&amp;gt;./gradlew build&amp;lt;/code&amp;gt; exécute aussi les tests, et les tests Cucumber utilisent Testcontainers pour lancer un PostgreSQL éphémère.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;Could not find a valid Docker environment.

EnvironmentAndSystemPropertyClientProviderStrategy: failed with exception BadRequestException
(Status 400: {&amp;quot;message&amp;quot;:&amp;quot;client version 1.32 is too old. Minimum supported API version is 1.40&amp;quot;}
UnixSocketClientProviderStrategy: failed with exception BadRequestException
(Status 400: {&amp;quot;message&amp;quot;:&amp;quot;client version 1.32 is too old. Minimum supported API version is 1.40&amp;quot;}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Testcontainers est incapable de communiquer avec Docker. Deux stratégies différentes (variables d&amp;amp;#8217;environnement + socket Unix) échouent sur la même erreur.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-docker-handshake&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-f31d9e10795d818ce3068413fb5fdd1e.svg&amp;quot; alt=&amp;quot;Handshake Docker API refusé par le daemon&amp;quot; width=&amp;quot;731&amp;quot; height=&amp;quot;616&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_phase_1_la_piste_docker_java&amp;quot;&amp;gt;Phase 1 : la piste docker-java&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Premier réflexe : le client Docker Java utilisé par Testcontainers envoie la version API &amp;lt;code&amp;gt;1.32&amp;lt;/code&amp;gt; dans son handshake HTTP, mais Docker Engine 29.4.1 exige un minimum de &amp;lt;code&amp;gt;1.40&amp;lt;/code&amp;gt;. Le problème est au niveau du client, pas du daemon.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Vérification de la version de docker-java résolue par Testcontainers 1.20.6 :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ ./gradlew dependencies --configuration testRuntimeClasspath | grep docker-java

+--- com.github.docker-java:docker-java-api:3.4.1
+--- com.github.docker-java:docker-java-transport:3.4.1&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;docker-java 3.4.1, datant de Testcontainers 1.20.6. La dernière version publique de docker-java est 3.5.1. Tentons de forcer la montée de version via &amp;lt;code&amp;gt;resolutionStrategy&amp;lt;/code&amp;gt; dans le bloc &amp;lt;code&amp;gt;configurations&amp;lt;/code&amp;gt; de &amp;lt;code&amp;gt;build.gradle&amp;lt;/code&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-groovy hljs&amp;quot; data-lang=&amp;quot;groovy&amp;quot;&amp;gt;configurations {
    all {
        resolutionStrategy.eachDependency { details -&amp;amp;gt;
            if (details.requested.group == &amp;quot;com.github.docker-java&amp;quot;
                &amp;amp;amp;&amp;amp;amp; details.requested.name.startsWith(&amp;quot;docker-java&amp;quot;)) {
                details.useVersion(&amp;quot;3.5.1&amp;quot;)
            }
        }
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Relance du build. Même erreur : &amp;lt;code&amp;gt;client version 1.32 is too old&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Vérification du cache Gradle : les JARs ont bien été re-téléchargés, mais l&amp;amp;#8217;erreur persiste. docker-java 3.5.1 envoie toujours &amp;lt;code&amp;gt;1.32&amp;lt;/code&amp;gt;. Cette version n&amp;amp;#8217;est donc PAS suffisante pour Docker Engine 29.4.1.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Action de purification&amp;lt;/strong&amp;gt; : vider complètement le cache Gradle, juste pour être sûr :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;rm -rf ~/.gradle/caches
rm -rf /path/to/project/.gradle&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Relance complète après purge. Même erreur.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_phase_2_recherche_web_et_fil_dariane_github&amp;quot;&amp;gt;Phase 2 : recherche web et fil d&amp;amp;#8217;ariane GitHub&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;docker-java 3.5.1 est insuffisant. Ne reste plus qu&amp;amp;#8217;à chercher si quelqu&amp;amp;#8217;un a rencontré ce problème exact.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Recherche ciblée sur les issues testcontainers-java et docker-java :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;site:github.com/testcontainers &amp;quot;client version 1.32 is too old&amp;quot;
site:github.com/docker-java &amp;quot;client version 1.32&amp;quot; Docker Engine 29&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Premiers résultats immédiats :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/testcontainers/testcontainers-java/issues/11210&amp;quot;&amp;gt;testcontainers-java#11210&amp;lt;/a&amp;gt; — &amp;lt;code&amp;gt;[Bug]: client version 1.32 is too old. Minimum supported API version is 1.44&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/testcontainers/testcontainers-java/issues/11212&amp;quot;&amp;gt;testcontainers-java#11212&amp;lt;/a&amp;gt; — &amp;lt;code&amp;gt;[Bug]: Docker 29.0.0 could not find a valid Docker environment&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/testcontainers/testcontainers-java/issues/11491&amp;quot;&amp;gt;testcontainers-java#11491&amp;lt;/a&amp;gt; — &amp;lt;code&amp;gt;[Bug]: Incompatibility in Ubuntu Github runners with Docker Engine 29.1.*&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le fil d&amp;amp;#8217;Ariane est clair : Docker Engine 29.x a élevé son minimum API version de &amp;lt;code&amp;gt;1.24&amp;lt;/code&amp;gt; (ancien défaut) à &amp;lt;code&amp;gt;1.40&amp;lt;/code&amp;gt;. Testcontainers 1.20.x utilise docker-java 3.4.x qui négocie la version API en envoyant &amp;lt;code&amp;gt;1.32&amp;lt;/code&amp;gt;. Le daemon refuse poliment mais fermement.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Dans l&amp;amp;#8217;issue #11491, un mainteneur répond :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&amp;lt;em&amp;gt;_ Hi, I have a project running with version 2.0.3 on a GH runner with engine 29.1 and it works. Can you all please check there is no version conflict? Please, remember all modules were prefixed with &amp;lt;code&amp;gt;testcontainers-&amp;lt;/code&amp;gt;. So, starting with version 2.x we went from &amp;lt;code&amp;gt;postgresql&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;testcontainers-postgresql&amp;lt;/code&amp;gt; &amp;lt;/em&amp;gt;_&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Cette réponse contient &amp;lt;strong&amp;gt;deux informations critiques&amp;lt;/strong&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Testcontainers 2.0.3+ résout le problème&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Les modules ont été &amp;lt;strong&amp;gt;renommés avec le préfixe &amp;lt;code&amp;gt;testcontainers-&amp;lt;/code&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_phase_3_le_piège_des_artifacts_renommés&amp;quot;&amp;gt;Phase 3 : le piège des artifacts renommés&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le renommage est brutal. En Testcontainers 2.x, plus aucun des anciens noms ne fonctionne sous ce nom-là :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 10%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Ancien nom (1.x)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Nouveau nom (2.x)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;org.testcontainers:postgresql&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;org.testcontainers:testcontainers-postgresql&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;org.testcontainers:jdbc&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;org.testcontainers:testcontainers-jdbc&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;org.testcontainers:junit-jupiter&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;org.testcontainers:testcontainers-junit-jupiter&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;org.testcontainers:testcontainers&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;inchangé&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Première tentative : appliquer la BOM Testcontainers 2.0.5 et les nouveaux noms d&amp;amp;#8217;artifacts dans &amp;lt;code&amp;gt;build.gradle&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-groovy hljs&amp;quot; data-lang=&amp;quot;groovy&amp;quot;&amp;gt;dependencies {
    testImplementation platform(&amp;quot;org.testcontainers:testcontainers-bom:2.0.5&amp;quot;)
    testImplementation &amp;quot;org.testcontainers:testcontainers-postgresql&amp;quot;
    testImplementation &amp;quot;org.testcontainers:testcontainers-jdbc&amp;quot;
    testImplementation &amp;quot;org.testcontainers:testcontainers-junit-jupiter&amp;quot;
    testImplementation &amp;quot;org.testcontainers:testcontainers&amp;quot;
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;./gradlew build&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;FAILURE: Could not find org.testcontainers:jdbc:2.0.5.
Could not find org.testcontainers:junit-jupiter:2.0.5.&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Le BOM de testcontainers-bom ne suffit pas.&amp;lt;/strong&amp;gt; Pourquoi ? Parce que Spring Boot 3.4.5 expose son propre BOM de gestion de dépendances (&amp;lt;code&amp;gt;spring-boot-dependencies&amp;lt;/code&amp;gt;) qui &amp;lt;strong&amp;gt;gagne&amp;lt;/strong&amp;gt; sur le BOM de Testcontainers dans la résolution transitive. Spring Boot fixe &amp;lt;code&amp;gt;testcontainers&amp;lt;/code&amp;gt; à &amp;lt;code&amp;gt;1.20.6&amp;lt;/code&amp;gt;, et donc tous les artifacts qui ne sont pas explicitement dans le BOM Spring Boot (comme les nouveaux &amp;lt;code&amp;gt;testcontainers-*&amp;lt;/code&amp;gt;) résolvent vers les anciens noms &amp;lt;code&amp;gt;1.20.6&amp;lt;/code&amp;gt;&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;qui n&amp;amp;#8217;existent plus dans cette version.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;En inspectant le &amp;lt;code&amp;gt;dependencies --configuration testRuntimeClasspath&amp;lt;/code&amp;gt;, on trouve :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;+--- org.testcontainers:testcontainers -&amp;amp;gt; 1.20.6 (*)
|    \--- org.testcontainers:testcontainers:2.0.5 -&amp;amp;gt; 1.20.6&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le &amp;lt;code&amp;gt;&amp;amp;#8594;&amp;lt;/code&amp;gt; indique la substitution : Testcontainers 2.0.5 est &amp;lt;strong&amp;gt;demandé&amp;lt;/strong&amp;gt;, mais Spring Boot force &amp;lt;code&amp;gt;1.20.6&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-bom-war&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-714056a094f875d4bd0cf8db572918d3.svg&amp;quot; alt=&amp;quot;Conflit entre le BOM Spring Boot et le BOM Testcontainers&amp;quot; width=&amp;quot;1111&amp;quot; height=&amp;quot;321&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_phase_4_forcer_la_résolution&amp;quot;&amp;gt;Phase 4 : forcer la résolution&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La stratégie devient double :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Forcer docker-java à sa version 3.7.1 (testée comme compatible Docker Engine 29)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Forcer Testcontainers core à 2.0.5 en contournant le BOM Spring Boot&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-resolution-override&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-0e6edf1a58135d9df65ae14483179ddf.svg&amp;quot; alt=&amp;quot;resolutionStrategy.eachDependency court-circuite le BOM Spring Boot&amp;quot; width=&amp;quot;1103&amp;quot; height=&amp;quot;468&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Correction finale&amp;lt;/strong&amp;gt; dans &amp;lt;code&amp;gt;build.gradle&amp;lt;/code&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-groovy hljs&amp;quot; data-lang=&amp;quot;groovy&amp;quot;&amp;gt;configurations {
    all {
        resolutionStrategy.eachDependency { details -&amp;amp;gt;
            if (details.requested.group == &amp;quot;com.github.docker-java&amp;quot;
                &amp;amp;amp;&amp;amp;amp; details.requested.name.startsWith(&amp;quot;docker-java&amp;quot;)) {
                details.useVersion(&amp;quot;3.7.1&amp;quot;)
            }
            if (details.requested.group == &amp;quot;org.testcontainers&amp;quot;
                &amp;amp;amp;&amp;amp;amp; details.requested.name == &amp;quot;testcontainers&amp;quot;) {
                details.useVersion(&amp;quot;2.0.5&amp;quot;)
            }
        }
    }
}

dependencies {
    testImplementation platform(&amp;quot;org.testcontainers:testcontainers-bom:2.0.5&amp;quot;)
    testImplementation &amp;quot;org.testcontainers:testcontainers-jdbc&amp;quot;
    testImplementation &amp;quot;org.testcontainers:testcontainers-junit-jupiter&amp;quot;
    testImplementation &amp;quot;org.testcontainers:testcontainers-postgresql&amp;quot;
    testImplementation &amp;quot;org.testcontainers:testcontainers&amp;quot;
    // ... autres dépendances Spring Boot
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le &amp;lt;code&amp;gt;resolutionStrategy.eachDependency&amp;lt;/code&amp;gt; est le seul moyen d&amp;amp;#8217;outrepasser le BOM &amp;lt;code&amp;gt;spring-boot-dependencies&amp;lt;/code&amp;gt; géré par le plugin Spring Boot. Le test d&amp;amp;#8217;égalité sur &amp;lt;code&amp;gt;details.requested.name == &amp;quot;testcontainers&amp;quot;&amp;lt;/code&amp;gt; est volontairement restrictif : on ne force que le module core. Les modules &amp;lt;code&amp;gt;testcontainers-*&amp;lt;/code&amp;gt; suivent le BOM de Testcontainers 2.0.5 qu&amp;amp;#8217;on a explicitement déclaré.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_résultat_final&amp;quot;&amp;gt;Résultat final&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ ./gradlew build --no-daemon

&amp;amp;gt; Task :consoleLauncherTest
[2 containers found]
[2 containers started]
[2 containers successful]

BUILD SUCCESSFUL in 1m 16s&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Testcontainers 2.0.5 + docker-java 3.7.1 parviennent enfin à créer leurs containers PostgreSQL via Docker Engine 29.4.1. L&amp;amp;#8217;erreur métier finale (HTTP 500 sur le test Cucumber) est un problème applicatif totalement indépendant du build script.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_tableau_récapitulatif_des_corrections&amp;quot;&amp;gt;Tableau récapitulatif des corrections&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;#&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Fichier&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Problème&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Correction&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;1&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;buildSrc/src/main/groovy/jhipster.cucumber-conventions.gradle&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Variable &amp;lt;code&amp;gt;reportsDir&amp;lt;/code&amp;gt; inexistante&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;outputs.dir(cucumberReportsDir)&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;2&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;buildSrc/src/main/groovy/jhipster.cucumber-conventions.gradle&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; déprécié Gradle 9&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;mainClass&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;3&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;build.gradle&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;sourceCompatibility&amp;lt;/code&amp;gt; top-level interdit Gradle 9&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Bloc &amp;lt;code&amp;gt;java { sourceCompatibility = JavaVersion.VERSION_21 }&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;4&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;build.gradle&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Assertion Groovy syntaxiquement invalide&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;assert &amp;amp;#8230;&amp;amp;#8203; in [&amp;quot;17&amp;quot;, &amp;quot;21&amp;quot;, &amp;quot;23&amp;quot;, &amp;quot;24&amp;quot;]&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;5&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;build.gradle&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Dépendance implicite &amp;lt;code&amp;gt;compileKotlin&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;openApiGenerate&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;afterEvaluate { tasks.named(&amp;quot;compileKotlin&amp;quot;).dependsOn(&amp;quot;openApiGenerate&amp;quot;) }&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;6&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;gradle.properties&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;gitPropertiesPluginVersion&amp;lt;/code&amp;gt; incompatible Java 21&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;2.5.7&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;7&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Cache Gradle&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;docker-java 3.5.1 testé, résolu mais insuffisant&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Purge + passage docker-java 3.7.1&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;8&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;build.gradle&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Testcontainers 1.20.6 incompatible Docker Engine 29&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Forçage Testcontainers 2.0.5 + prefix &amp;lt;code&amp;gt;testcontainers-*&amp;lt;/code&amp;gt; + resolutionStrategy vs Spring Boot BOM&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_conclusion&amp;quot;&amp;gt;Conclusion&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Si votre build JHipster/Gradle plante après une montée de version vers Gradle 9 + Docker Engine 29, les erreurs se répartissent en deux catégories :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Erreurs de build script&amp;lt;/strong&amp;gt; (les 6 premières) : Gradle 9 supprime des propriétés et des syntaxes qui marchaient depuis des années (&amp;lt;code&amp;gt;sourceCompatibility=&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;main =&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;reportsDir&amp;lt;/code&amp;gt;). Ce sont des migrations mécaniques une fois qu&amp;amp;#8217;on connaît la nouvelle API.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Erreurs de runtime Docker&amp;lt;/strong&amp;gt; (les 2 dernières) : Docker Engine 29.4.1 écarte les clients API &amp;amp;lt; 1.40. Testcontainers 1.20.6 (imposé par Spring Boot 3.4.5) utilise docker-java 3.4.1 qui envoie 1.32. Seul Testcontainers 2.0.5 + docker-java 3.7.1 résout le problème, avec le renommage des artifacts et le forçage de version via &amp;lt;code&amp;gt;resolutionStrategy.eachDependency&amp;lt;/code&amp;gt; comme seul moyen de contourner le BOM implicite de Spring Boot.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le build script Gradle à la racine du projet est maintenant propre. &amp;lt;code&amp;gt;./gradlew build&amp;lt;/code&amp;gt; passe sur Java 21, Gradle 9.4.1, Spring Boot 3.4.5 et Docker Engine 29.4.1.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Gouverner un Agent IA avec du AsciiDoc : Ma Stratégie Eager/Lazy pour des Sessions Opencode sans Fuite de Contexte</title>
            <link >https://cheroliv.com/blog/2026/0108_gouvernance_agent_opencode_eager_lazy_post.html</link>
            <pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0108_gouvernance_agent_opencode_eager_lazy_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_résumé&amp;quot;&amp;gt;Résumé&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Quand on travaille avec un agent IA comme Opencode sur des projets complexes sur plusieurs sessions, on fait face à un problème fondamental : &amp;lt;strong&amp;gt;la fuite de contexte&amp;lt;/strong&amp;gt;. L&amp;amp;#8217;agent ne se souvient pas de la session précédente. Tout ce qu&amp;amp;#8217;on lui a expliqué&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;l&amp;amp;#8217;architecture, les conventions, l&amp;amp;#8217;état du backlog&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;est perdu. Reconstruire ce contexte à chaque session est coûteux, lent et source d&amp;amp;#8217;erreur.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Cet article expose la stratégie artisanale que j&amp;amp;#8217;ai construite pour résoudre ce problème : un système de gouvernance persistant basé sur des fichiers AsciiDoc, avec une dichotomie &amp;lt;strong&amp;gt;Eager/Lazy&amp;lt;/strong&amp;gt; pour optimiser la consommation du token de contexte, et une &amp;lt;strong&amp;gt;procédure de fin de session incontournable&amp;lt;/strong&amp;gt; pour assurer la continuité.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_scène_lundi_21_avril_9h00&amp;quot;&amp;gt;La Scène : Lundi 21 Avril, 9h00&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Je rouvre Opencode pour reprendre mon plugin Gradle &amp;lt;code&amp;gt;plantuml-plugin&amp;lt;/code&amp;gt;. Hier soir, j&amp;amp;#8217;ai passé trois heures à discuter avec l&amp;amp;#8217;agent de l&amp;amp;#8217;architecture du pool de clés API&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;rotation round-robin, gestion des quotas, fallback automatique. Ce matin, l&amp;amp;#8217;agent me regarde avec des yeux de poisson rouge.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&amp;lt;em&amp;gt;_&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;Bonjour, je suis votre assistant Opencode. Comment puis-je vous aider aujourd&amp;amp;#8217;hui ? &amp;lt;/em&amp;gt;_&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pas de&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;Ah oui, le pool de clés API, on en était à la structure YAML. Pas de&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;Attention, &amp;lt;code&amp;gt;PlantumlManager&amp;lt;/code&amp;gt; est un objet Kotlin singleton, pas une classe. Pas de&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;Non, on a décidé hier que &amp;lt;code&amp;gt;SyntaxValidationResult&amp;lt;/code&amp;gt; restait une sealed class nested dans &amp;lt;code&amp;gt;PlantumlService&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Tout est à refaire. Ou plutôt : tout est à réexpliquer. Je vais passer les vingt premières minutes de ma session à reconstituer un contexte que l&amp;amp;#8217;agent a déjà eu entre les mains hier. Vingt minutes de tokens brûlés. Vingt minutes où je pourrais coder, mais où je fais du pédagogique obligatoire.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce n&amp;amp;#8217;est pas un bug d&amp;amp;#8217;Opencode. C&amp;amp;#8217;est la nature même des LLM conversationnels : entre deux sessions, la mémoire de travail est &amp;lt;strong&amp;gt;entièrement effacée&amp;lt;/strong&amp;gt;. L&amp;amp;#8217;agent ne se souvient pas de la mission précédente, des décisions prises, des pièges identifiés, du code qu&amp;amp;#8217;on a écrit ensemble.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ai vécu ça des dizaines de fois. Sur quatre projets simultanés. Avec des sessions qui s&amp;amp;#8217;enchaînent sur des semaines. J&amp;amp;#8217;ai calculé : en moyenne, &amp;lt;strong&amp;gt;30 à 40 % du temps de session&amp;lt;/strong&amp;gt; était consacré à recontextualiser l&amp;amp;#8217;agent. À la session 87 du projet &amp;lt;code&amp;gt;plantuml-plugin&amp;lt;/code&amp;gt;, j&amp;amp;#8217;ai craqué. Je ne pouvais plus me permettre de réexpliquer pour la dixième fois que &amp;lt;code&amp;gt;AttemptEntry&amp;lt;/code&amp;gt; est une data class top-level dans &amp;lt;code&amp;gt;DiagramProcessor.kt&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Il me fallait un système. Pas un hack. Une vraie gouvernance.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_genèse_du_chaos_à_la_méthode&amp;quot;&amp;gt;La Genèse : Du Chaos à la Méthode&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_les_premières_sessions_lâge_des_ténèbres&amp;quot;&amp;gt;Les Premières Sessions : L&amp;amp;#8217;Âge des Ténèbres&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mon premier projet avec Opencode, &amp;lt;code&amp;gt;plantuml-plugin&amp;lt;/code&amp;gt;, a démarré sans aucune gouvernance. Je pose une question, l&amp;amp;#8217;agent répond, on itère, la session se termine, et le lendemain on repart de zéro. C&amp;amp;#8217;était la session 1, puis la 2, puis la 3&amp;amp;#8230;&amp;amp;#8203; jusqu&amp;amp;#8217;à la session 62 où je réalise que j&amp;amp;#8217;ai perdu des heures cumulées à réexpliquer la même architecture.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;À la session 62, les chiffres sont là : &amp;lt;strong&amp;gt;198 tests unitaires passent&amp;lt;/strong&amp;gt;, &amp;lt;strong&amp;gt;42 tests fonctionnels validés&amp;lt;/strong&amp;gt;, le plugin fonctionne. Mais le coût cognitif est insupportable. Chaque nouvelle session commence par un monologue de vingt minutes sur la structure du projet.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_lépisode_du_site_yml_détruit_session_2_bakery_plugin&amp;quot;&amp;gt;L&amp;amp;#8217;Épisode du site.yml Détruit (Session 2, bakery-plugin)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La méthode naît aussi d&amp;amp;#8217;une catastrophe. Sur le projet &amp;lt;code&amp;gt;bakery-gradle&amp;lt;/code&amp;gt;, à la session 2, je demande à l&amp;amp;#8217;agent de modifier le fichier &amp;lt;code&amp;gt;site.yml&amp;lt;/code&amp;gt;. L&amp;amp;#8217;agent, sans vérifier si le fichier est versionné, fait un &amp;lt;code&amp;gt;Write&amp;lt;/code&amp;gt; complet qui écrase le contenu. Résultat : les tokens réels (clés API Firebase, secrets de déploiement) sont remplacés par des placeholders factices. Le fichier n&amp;amp;#8217;était pas dans git&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;il était dans &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt; pour protéger les secrets.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Sans sauvegarde. Sans &amp;lt;code&amp;gt;git restore&amp;lt;/code&amp;gt; possible. Je suis bloqué. Il me faut reconstruire manuellement le fichier de configuration, retrouver les tokens dans mes gestionnaires de mots de passe, tout recoller.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est de cette frustration que naît la &amp;lt;strong&amp;gt;Règle Absolue 1b&amp;lt;/strong&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&amp;lt;em&amp;gt;_ &amp;lt;strong&amp;gt;NE JAMAIS écraser&amp;lt;/strong&amp;gt; un fichier config avec un &amp;lt;code&amp;gt;Write&amp;lt;/code&amp;gt; complet quand un &amp;lt;code&amp;gt;Edit&amp;lt;/code&amp;gt; partiel suffit. &amp;lt;strong&amp;gt;NE JAMAIS remplacer&amp;lt;/strong&amp;gt; des valeurs sensibles par des valeurs factices. &amp;lt;strong&amp;gt;Vérifier &amp;lt;code&amp;gt;git check-ignore&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;git ls-files&amp;lt;/code&amp;gt;&amp;lt;/strong&amp;gt; avant toute modification. &amp;lt;/em&amp;gt;_&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Cette règle, aujourd&amp;amp;#8217;hui gravée dans le marbre de tous mes fichiers &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;INDEX.adoc&amp;lt;/code&amp;gt; sur quatre projets, est née d&amp;amp;#8217;une erreur réelle qui m&amp;amp;#8217;a coûté une heure de travail manuel.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_la_migration_markdown_asciidoc_session_1_cheroliv_com&amp;quot;&amp;gt;La Migration Markdown → AsciiDoc (Session 1, cheroliv.com)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le 25 avril 2026, sur &amp;lt;code&amp;gt;cheroliv.com&amp;lt;/code&amp;gt;, je prends une décision radicale : convertir l&amp;amp;#8217;intégralité de la gouvernance de Markdown vers AsciiDoc. Ce n&amp;amp;#8217;est pas esthétique. C&amp;amp;#8217;est fonctionnel. AsciiDoc offre une structure sémantique que les LLM lisent mieux : sections hiérarchiques, tableaux typés, admonitions (&amp;lt;code&amp;gt;NOTE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CAUTION&amp;lt;/code&amp;gt;), attributs de document lisibles par la machine.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La session 1 de &amp;lt;code&amp;gt;cheroliv.com&amp;lt;/code&amp;gt; formalise la structure :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Conversion de &amp;lt;code&amp;gt;AGENTS.md&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Création des agents spécialisés : &amp;lt;code&amp;gt;CODER.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SCRUM_MASTER.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PLANTUML_DESIGNER.adoc&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Création de la structure Eager/Lazy : &amp;lt;code&amp;gt;INDEX.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SESSIONS_HISTORY.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;AGENT_SESSION_MANAGER.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SESSION_CHECKLIST.adoc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;PROCEDURES.adoc&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un seul commit : &amp;lt;code&amp;gt;90975e9 refactor: migrate agent governance from Markdown to AsciiDoc&amp;lt;/code&amp;gt;. Et le site continue de fonctionner.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-timeline&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-1ffbad829836ed4bec6c66e6b3038145.svg&amp;quot; alt=&amp;quot;Timeline de croissance des sessions sur les 4 projets&amp;quot; width=&amp;quot;2373&amp;quot; height=&amp;quot;290&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La timeline ci-dessus illustre la progression réelle. Le point de bascule est la session 87 : c&amp;amp;#8217;est là que la frustration du recontextualisation répétée dépasse le seuil de tolérance, et que la méthode Eager/Lazy cesse d&amp;amp;#8217;être une idée pour devenir une obligation.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_stratégie_eagerlazy_en_profondeur&amp;quot;&amp;gt;La Stratégie : Eager/Lazy en Profondeur&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_philosophie_cache_informatique_appliqué_à_la_cognition&amp;quot;&amp;gt;Philosophie : Cache Informatique Appliqué à la Cognition&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mon approche s&amp;amp;#8217;inspire directement de la gestion de cache informatique. Tout ce qui est &amp;lt;strong&amp;gt;critique et fréquemment utilisé&amp;lt;/strong&amp;gt; doit être immédiatement accessible (&amp;lt;strong&amp;gt;Eager&amp;lt;/strong&amp;gt;). Tout ce qui est &amp;lt;strong&amp;gt;contextuel ou volumineux&amp;lt;/strong&amp;gt; doit être chargé sur demande (&amp;lt;strong&amp;gt;Lazy&amp;lt;/strong&amp;gt;).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.6676%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Eager (Tableau de Bord)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Lazy (Manuel du Propriétaire)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Taille&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;amp;lt; 100 lignes, &amp;amp;lt; 10k tokens&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Illimité, détaillé&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Chargement&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Auto, en début de session&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Sur demande de l&amp;amp;#8217;agent&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Contenu&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Règles absolues, mission courante, état critique&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Archives de sessions, historique complet, procédures détaillées, références techniques&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Rôle&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Orienter immédiatement l&amp;amp;#8217;agent&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Répondre aux questions de contexte profond&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_les_fichiers_eager_le_tableau_de_bord&amp;quot;&amp;gt;Les Fichiers Eager : Le Tableau de Bord&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ces fichiers vivent à la racine de chaque projet et sont chargés automatiquement par l&amp;amp;#8217;agent au début de chaque session. Ils forment le &amp;lt;strong&amp;gt;tableau de bord&amp;lt;/strong&amp;gt;&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;information critique, immédiatement accessible.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-eager-lazy&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-05c08d0c2b5bf285c4c1fee60314a0e7.svg&amp;quot; alt=&amp;quot;Architecture Eager/Lazy des fichiers de gouvernance&amp;quot; width=&amp;quot;1761&amp;quot; height=&amp;quot;5760&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt;&amp;lt;/strong&amp;gt;&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;Le fichier maître. Sur &amp;lt;code&amp;gt;cheroliv.com&amp;lt;/code&amp;gt;, il fait 200 lignes et contient :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Les règles absolues du projet (pas de commit sans permission, pas de &amp;lt;code&amp;gt;rm&amp;lt;/code&amp;gt; sans confirmation)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;La structure du projet et les conventions de code&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Les commandes essentielles (&amp;lt;code&amp;gt;./gradlew serve&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;./gradlew test&amp;lt;/code&amp;gt;)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Les épopées et le backlog produit (user stories priorisées)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Les critères de qualité transverses (accessibilité, responsive, compatibilité)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Sur &amp;lt;code&amp;gt;bakery-plugin&amp;lt;/code&amp;gt;, la Règle 0 est différente : &amp;lt;strong&amp;gt;&amp;lt;code&amp;gt;./gradlew -q publishToMavenLocal&amp;lt;/code&amp;gt; obligatoire après chaque modification du code source&amp;lt;/strong&amp;gt;. Parce que tester le plugin sans republier le JAR local m&amp;amp;#8217;a fait perdre une heure à débugger un code qui n&amp;amp;#8217;était pas encore empaqueté.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;code&amp;gt;PROMPT_REPRISE.adoc&amp;lt;/code&amp;gt;&amp;lt;/strong&amp;gt;&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;La mission de la session en cours. Mis à jour à chaque fin de session, il contient :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le numéro de session et la mission prioritaire&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le résumé de la session précédente (ce qui a été fait, ce qui reste à faire)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Les critères d&amp;amp;#8217;acceptation de la session courante&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Les rappels techniques spécifiques&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;code&amp;gt;.agents/INDEX.adoc&amp;lt;/code&amp;gt;&amp;lt;/strong&amp;gt;&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;Le point d&amp;amp;#8217;entrée. Il résume les règles absolues, les sessions récentes, et surtout le &amp;lt;strong&amp;gt;portefeuille de projets&amp;lt;/strong&amp;gt; gérés avec la même méthodologie. À ce jour, cinq projets y figurent :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code&amp;gt;----
| magic-stick    | Session 23 | SCRIPT_VERIFICATION.adoc | 2026-04-27 |
| bakery-gradle  | Session 11 | TEST_COVERAGE_ANALYSIS   | 2026-04-27 |
| cheroliv.com   | Session 9  | TEST_COVERAGE_ANALYSIS   | 2026-04-27 |
| plantuml-gradle| Session 133| TEST_COVERAGE_ANALYSIS   | 2026-04-23 |
| jhipster-gradle-plugins | Session 1 | TEST_COVERAGE_ANALYSIS | 2026-04-28 |
----

**`*_ESSENTIALS.adoc`** -- Un ajout récent (Session 109, plantuml-plugin) pour optimiser encore le contexte Eager. Au lieu de charger 200 lignes de contexte métier sur le pool de clés API, je charge 50 lignes de l&amp;#39;essentiel, et les 150 autres lignes restent en LAZY dans `*_REFERENCE.adoc`.

Résultat mesuré : passage de **~25k tokens EAGER à ~10k tokens** (gain de 60%). L&amp;#39;agent n&amp;#39;a plus besoin de rappels énergivores.

==== Le Chaînon Manquant : `opencode.json`

Je dois vous avouer une chose que j&amp;#39;ai failli oublier de documenter. Au-dessus de tous ces fichiers .adoc, il y a un minuscule fichier JSON sans lequel rien ne fonctionne. Il s&amp;#39;appelle `opencode.json` et il fait six lignes. Littéralement six lignes.

[source,json]
----
{
  &amp;quot;$schema&amp;quot;: &amp;quot;https://opencode.ai/config.json&amp;quot;,
  &amp;quot;instructions&amp;quot;: [
    &amp;quot;AGENT.adoc&amp;quot;
  ]
}
----

C&amp;#39;est ce fichier qui dit à Opencode : « Au démarrage, charge `AGENT.adoc` automatiquement. » Sans lui, l&amp;#39;agent est une page blanche exactement comme je le décrivais au début de l&amp;#39;article. Avec lui, l&amp;#39;agent a déjà entre les mains les règles absolues, l&amp;#39;architecture du projet, et les commandes essentielles — avant même que je dise bonjour.

J&amp;#39;ai découvert l&amp;#39;importance de ce fichier par hasard. Sur `bakery-plugin`, il n&amp;#39;existait pas. Je me demandais pourquoi l&amp;#39;agent était systématiquement plus « perdu » sur ce projet que sur les autres. Les règles absolues étaient bien dans `AGENT.adoc` — mais `AGENT.adoc` n&amp;#39;était jamais chargé. L&amp;#39;agent ne lisait que ce que je lui disais de lire, manuellement, à chaque session. C&amp;#39;était la session 11 de `bakery-plugin` quand j&amp;#39;ai réalisé l&amp;#39;absence du `opencode.json`. Je l&amp;#39;ai créé — et la session 12 a démarré comme les autres.

Ce fichier est tellement évident pour moi maintenant que je ne pensais même plus à lui. Une erreur classique du développeur qui connaît trop son outil. Aujourd&amp;#39;hui, je le crée systématiquement *avant* `AGENT.adoc`. C&amp;#39;est la première pierre.

==== La Dualité de `INDEX.adoc`

Une autre subtilité qui mérite d&amp;#39;être explicitée : `INDEX.adoc` vit dans `.agents/` — un dossier que j&amp;#39;ai présenté comme LAZY. Pourtant, je le liste comme EAGER dans tous mes tableaux. Il y a une tension apparente ici.

La réalité terrain : les fichiers `.agents/INDEX.adoc` sont bien chargés automatiquement en début de session, au même titre que `AGENT.adoc` et `PROMPT_REPRISE.adoc`. Ils sont dans `.agents/` pour des raisons d&amp;#39;organisation — ne pas envahir la racine — mais leur comportement est EAGER.

Sur `plantuml-plugin`, `INDEX.adoc` fait 200 lignes et contient les règles absolues *complètes* avec leur historique (les leçons des sessions passées), les EPICs avec scores, et le portefeuille de projets. C&amp;#39;est le document que l&amp;#39;agent consulte pour savoir « où on en est ». Sur `bakery-plugin`, il fait 150 lignes avec la roadmap et les sessions récentes.

La redondance volontaire entre `AGENT.adoc` et `INDEX.adoc` peut surprendre. Les règles absolues sont présentes dans les deux. Pourquoi ? Parce qu&amp;#39;elles remplissent deux rôles différents : dans `AGENT.adoc`, elles sont *explicatives* (le storytelling de la règle, la leçon apprise) ; dans `INDEX.adoc`, elles sont *exécutives* (la règle nue, sans justification, pour une consultation rapide). L&amp;#39;agent lit `AGENT.adoc` une fois pour *comprendre* ; il relit `INDEX.adoc` à chaque session pour *appliquer*. Deux usages, deux formats.

[plantuml, format=svg, id=diag-dualite-agent-index, alt=&amp;quot;Comparaison entre AGENT.adoc (narratif) et INDEX.adoc (exécutif)&amp;quot;]
----
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center

title Dualité AGENT.adoc ←→ INDEX.adoc

left to right direction

rectangle &amp;quot;AGENT.adoc\n(Racine — EAGER)&amp;quot; as AGENT #E3F2FD {
  rectangle &amp;quot;📖 **Format Narratif**\nLe storytelling de la règle\nla leçon apprise, le contexte&amp;quot; as NARR
  rectangle &amp;quot;🏗️ **Architecture Complète**\nStructure projet, composants\nBacklog détaillé US&amp;quot; as ARCHI
  rectangle &amp;quot;📋 **Règles Explicatives**\nPourquoi la règle existe\nHistorique de l&amp;#39;incident&amp;quot; as EXPL
}

rectangle &amp;quot;INDEX.adoc\n(.agents/ — EAGER)&amp;quot; as INDEX #E8F5E9 {
  rectangle &amp;quot;⚡ **Format Exécutif**\nLa règle nue, sans justification\nConsultation rapide&amp;quot; as EXEC
  rectangle &amp;quot;📊 **Roadmap &amp;amp;amp; EPICs**\nTableau récapitulatif\nProgression, Score, Priorité&amp;quot; as ROAD
  rectangle &amp;quot;🌐 **Portefeuille Projets**\nVue transverse\n5 projets synchronisés&amp;quot; as PORT
}

AGENT --&amp;amp;gt; INDEX : &amp;quot;Agent lit AGENT.adoc\n1 fois pour **comprendre**&amp;quot;
INDEX --&amp;amp;gt; AGENT : &amp;quot;Agent relit INDEX.adoc\nchaque session pour **appliquer**&amp;quot;

note bottom of AGENT
  Taille max : 200 lignes
end note

note bottom of INDEX
  Taille max : 200 lignes
  Source de vérité en cas de divergence
end note

@enduml
----

Cette redondance assumée est un choix de conception. Elle consomme ~50 lignes supplémentaires de tokens EAGER — mais elle garantit que l&amp;#39;agent a toujours les règles sous les yeux, y compris dans le format concis qui facilite l&amp;#39;obéissance immédiate.

=== Les Fichiers LAZY : Le Manuel du Propriétaire

Ces fichiers vivent dans `.agents/` et ne sont lus que quand l&amp;#39;agent en a besoin. Ils constituent la véritable richesse de la méthode, car ils accumulent la connaissance du projet sans polluer le contexte courant.

[plantuml, format=svg, id=diag-agents-tree, alt=&amp;quot;Arborescence complète du dossier .agents/&amp;quot;]
----
@startuml
skinparam folderBackgroundColor #E3F2FD
skinparam folderBorderColor #1565C0
skinparam fileBackgroundColor #FFF3E0
skinparam fileBorderColor #EF6C00

folder &amp;quot;.agents/&amp;quot; as ROOT {
  file &amp;quot;INDEX.adoc\n(EAGER -- 200 lignes)&amp;quot; as IDX #E8F5E9
  file &amp;quot;AGENT_SESSION_MANAGER.adoc\n(Template session)&amp;quot; as ASM
  file &amp;quot;SESSION_CHECKLIST.adoc\n(Quand changer)&amp;quot; as CHK
  file &amp;quot;PROCEDURES.adoc\n(6 étapes + LAZY/EAGER)&amp;quot; as PRO
  file &amp;quot;SESSIONS_HISTORY.adoc\n(Toutes sessions)&amp;quot; as HIS

  folder &amp;quot;sessions/&amp;quot; as SESS {
    file &amp;quot;1-chore-migration.adoc&amp;quot; as S1
    file &amp;quot;109-formalisation-lazy.adoc&amp;quot; as S109 #FFECB3
    file &amp;quot;133-epic11-article.adoc&amp;quot; as S133
    file &amp;quot;... +130 autres&amp;quot; as SMORE
  }

  folder &amp;quot;archives/&amp;quot; as ARCH {
    file &amp;quot;COMPLETED_TASKS_2026-04.adoc&amp;quot; as CTA
    file &amp;quot;SESSIONS_HISTORY_83-95.adoc&amp;quot; as SHIST
    folder &amp;quot;sessions_summaries/&amp;quot; as SUM {
      file &amp;quot;SESSION_64_SUMMARY.adoc&amp;quot; as SU64
      file &amp;quot;SESSION_73_SUMMARY.adoc&amp;quot; as SU73
      file &amp;quot;...&amp;quot; as SUMORE
    }
    folder &amp;quot;prompts_archive/&amp;quot; as PARCH {
      file &amp;quot;PROMPT_REPRISE_S65.adoc&amp;quot; as PR65
      file &amp;quot;PROMPT_REPRISE_S75.adoc&amp;quot; as PR75
      file &amp;quot;...&amp;quot; as PMORE
    }
  }
}

IDX --&amp;amp;gt; SESS : &amp;quot;Indexe&amp;quot;
IDX --&amp;amp;gt; HIS : &amp;quot;Indexe&amp;quot;
IDX --&amp;amp;gt; ARCH : &amp;quot;Référence&amp;quot;

note right of S109
  Session 109 =
  Formalisation stratégie
  LAZY/EAGER
  Token : ~25k → ~10k
end note

@enduml
----

L&amp;#39;arborescence ci-dessus montre la structure réelle du dossier `.agents/` sur `plantuml-plugin`, le projet le plus mature. Notez la profondeur en trois couches : fichiers racine (métadonnées), dossier `sessions/` (archives chronologiques), et dossier `archives/` (agrégations et résumés). C&amp;#39;est cette profondeur qui transforme la gouvernance d&amp;#39;un simple fichier TODO en une **mémoire organisationnelle complète**.

**`.agents/sessions/{N}-{titre}.adoc`** -- Les archives détaillées de chaque session. Actuellement :

* `plantuml-plugin` : **133 sessions archivées** (de la session 1 à 133)
* `bakery-plugin` : **11 sessions**
* `magic-stick` : **23 sessions**
* `cheroliv.com` : **9 sessions formelles** + 7 sessions pré-système reconstituées rétroactivement

Chaque archive contient le contexte complet de la session, les décisions prises, les problèmes rencontrés et leur résolution, les commandes exécutées et leur output.

**`.agents/SESSIONS_HISTORY.adoc`** -- Un tableau récapitulatif de toutes les sessions avec un score. Exemple sur `cheroliv.com` :&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;| -6 | 2025-05 | chore | Initialisation projet Gradle/JBake | 7/10
|  1 | 2026-04-25 | chore | Migration gouvernance agent | 8/10
|  7 | 2026-04-27 | debug/fix | Correction publishSite | 9/10
|  8 | 2026-04-27 | analyse | Analyse article 0108 | 7/10&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;code&amp;gt;.agents/COMPLETED_TASKS_ARCHIVE_{mois}.adoc&amp;lt;/code&amp;gt;&amp;lt;/strong&amp;gt;&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;Les tâches terminées archivées par mois, pour ne pas surcharger le backlog actif. Quand une user story est terminée, elle migre ici. Le backlog reste lisible : maximum 10 items actifs.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;code&amp;gt;.agents/PROCEDURES.adoc&amp;lt;/code&amp;gt;&amp;lt;/strong&amp;gt;&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;Templates détaillés de la procédure de fin de session. Long, mais lu une seule fois par l&amp;amp;#8217;agent quand il apprend la méthode. Ensuite, la procédure devient mécanique.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;code&amp;gt;.agents/AGENT_MODUS_OPERANDI.adoc&amp;lt;/code&amp;gt;&amp;lt;/strong&amp;gt;&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;La documentation stratégique complète. Sur &amp;lt;code&amp;gt;plantuml-plugin&amp;lt;/code&amp;gt;, ce fichier fait &amp;lt;strong&amp;gt;900+ lignes&amp;lt;/strong&amp;gt; et se nomme en réalité &amp;lt;code&amp;gt;AGENT_METHODOLOGIES.adoc&amp;lt;/code&amp;gt; — j&amp;amp;#8217;ai changé le nom entre l&amp;amp;#8217;écriture de cet article et la mise en place effective. Ce genre de divergence de naming est inévitable dans un système artisanal qui évolue. L&amp;amp;#8217;important est la convention de nommage : si le fichier documente la &amp;lt;strong&amp;gt;méthode&amp;lt;/strong&amp;gt;, il commence par &amp;lt;code&amp;gt;AGENT_&amp;lt;/code&amp;gt; ou un préfixe explicite. Il documente la méthodologie Eager/Lazy, les patterns à suivre, les anti-patterns à éviter. Il est LAZY parce qu&amp;amp;#8217;un agent n&amp;amp;#8217;a pas besoin de relire toute la stratégie à chaque session, seulement quand il y a ambiguïté.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;code&amp;gt;*_REFERENCE.adoc&amp;lt;/code&amp;gt;&amp;lt;/strong&amp;gt;&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;Les références techniques spécifiques au projet. Sur &amp;lt;code&amp;gt;magic-stick&amp;lt;/code&amp;gt;, deux fichiers LAZY denses :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;AB_PARTITION_REFERENCE.adoc&amp;lt;/code&amp;gt; (147 lignes)&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;Architecture partition A/B GPT, scripts &amp;lt;code&amp;gt;update-system.sh&amp;lt;/code&amp;gt;, tailles estimées, mécanisme de rollback&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;BOOT_TEST_REFERENCE.adoc&amp;lt;/code&amp;gt; (144 lignes)&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;Procédure QEMU + VNC pour tester le boot de l&amp;amp;#8217;ISO sans matériel physique, checklist BIOS/UEFI, limitations CI/CD&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Sur &amp;lt;code&amp;gt;plantuml-plugin&amp;lt;/code&amp;gt; :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;ARCHITECTURE.adoc&amp;lt;/code&amp;gt; (134 lignes)&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;Structure des 11 data classes, points d&amp;amp;#8217;attention (pièges à éviter), commandes de test optimisées&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;API_KEY_POOL_REFERENCE.adoc&amp;lt;/code&amp;gt;&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;Détails complets du pool de clés (LAZY pendant que &amp;lt;code&amp;gt;ESSENTIALS&amp;lt;/code&amp;gt; est EAGER)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_les_agents_spécialisés_une_équipe_virtuelle&amp;quot;&amp;gt;Les Agents Spécialisés : Une Équipe Virtuelle&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La gouvernance ne se limite pas à des fichiers passifs. J&amp;amp;#8217;ai formalisé des &amp;lt;strong&amp;gt;rôles d&amp;amp;#8217;agents spécialisés&amp;lt;/strong&amp;gt; dans des fichiers LAZY dédiés, qui définissent le workflow attendu selon le type de tâche.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 6.25%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Agent&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Fichier&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Rôle&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Projet&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;CODER&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;CODER.adoc&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Implémentation FTL/CSS/JS, balises sémantiques, critères d&amp;amp;#8217;accessibilité&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;cheroliv.com&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;SCRUM Master&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;SCRUM_MASTER.adoc&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Planification US, découpage en sous-tâches, détection des dépendances&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;cheroliv.com&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;PlantUML Designer&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;PLANTUML_DESIGNER.adoc&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Création de diagrammes, syntaxe PUML, intégration JBake&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;cheroliv.com&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le fichier &amp;lt;code&amp;gt;CODER.adoc&amp;lt;/code&amp;gt; sur &amp;lt;code&amp;gt;cheroliv.com&amp;lt;/code&amp;gt; contient des règles concrètes : &amp;lt;em&amp;gt;Un seul &amp;lt;code&amp;gt;&amp;amp;lt;h1&amp;amp;gt;&amp;lt;/code&amp;gt; par page&amp;lt;/em&amp;gt;, &amp;lt;em&amp;gt;Préfixer les chemins avec `${content.rootpath}`&amp;lt;/em&amp;gt;, &amp;lt;em&amp;gt;Déclarer la langue `&amp;amp;lt;html lang=&amp;quot;${content.lang!&amp;quot;fr&amp;quot;}&amp;quot;&amp;amp;gt;`&amp;lt;/em&amp;gt;. Ces conventions, écrites une fois, sont respectées automatiquement par l&amp;amp;#8217;agent depuis la session 1.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le fichier &amp;lt;code&amp;gt;SCRUM_MASTER.adoc&amp;lt;/code&amp;gt; impose une structure de livrable : &amp;lt;strong&amp;gt;Objectif&amp;lt;/strong&amp;gt;, &amp;lt;strong&amp;gt;Tâches&amp;lt;/strong&amp;gt; (ordonnées avec assignation), &amp;lt;strong&amp;gt;Critères d&amp;amp;#8217;acceptation&amp;lt;/strong&amp;gt;, &amp;lt;strong&amp;gt;Risques&amp;lt;/strong&amp;gt;. Quand je demande un plan d&amp;amp;#8217;action, l&amp;amp;#8217;agent produit cette structure sans que je l&amp;amp;#8217;aie demandée. La gouvernance &amp;lt;strong&amp;gt;programme&amp;lt;/strong&amp;gt; l&amp;amp;#8217;agent.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_quand_les_agents_spécialisés_deviennent_indispensables&amp;quot;&amp;gt;Quand les Agents Spécialisés Deviennent Indispensables&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La création des agents spécialisés suit une courbe naturelle. Au début d&amp;amp;#8217;un projet, vous n&amp;amp;#8217;en avez pas besoin — &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt; suffit largement. Mais quand le projet grandit (disons, au-delà de 20 sessions), deux signaux doivent vous alerter :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;agent mélange les conventions de deux domaines distincts (ex: syntaxe PlantUML et règles CSS)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Vous passez plus de temps à corriger l&amp;amp;#8217;agent sur des conventions que vous lui avez déjà expliquées 5 fois&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Sur &amp;lt;code&amp;gt;cheroliv.com&amp;lt;/code&amp;gt;, c&amp;amp;#8217;est arrivé à la session&amp;amp;#8230;&amp;amp;#8203; 1. Oui, dès le départ. Parce que ce projet est un site web avec trois langages (FTL, CSS, JS), du contenu AsciiDoc, et des diagrammes PlantUML — trois domaines qui n&amp;amp;#8217;ont rien à voir. L&amp;amp;#8217;agent CODER a besoin de connaître les tailles de police et les media queries ; l&amp;amp;#8217;agent PLANTUML_DESIGNER a besoin de connaître la syntaxe &amp;lt;code&amp;gt;@startuml&amp;lt;/code&amp;gt;. Sans séparation, l&amp;amp;#8217;agent CODER me proposait des diagrammes, et vice versa. Le chaos.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Sur &amp;lt;code&amp;gt;jhipster-gradle-plugins&amp;lt;/code&amp;gt;, j&amp;amp;#8217;ai créé deux agents spécialisés adaptés au développement de plugins Gradle : &amp;lt;code&amp;gt;PLUGIN_DEVELOPER.adoc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;BACKLOG_MANAGER.adoc&amp;lt;/code&amp;gt;. Le premier encode toutes les conventions Kotlin/Gradle (pas de &amp;lt;code&amp;gt;!!&amp;lt;/code&amp;gt;, data classes pour les modèles, &amp;lt;code&amp;gt;@TaskAction&amp;lt;/code&amp;gt; pour les tâches). Le second sait que &amp;lt;code&amp;gt;persistence&amp;lt;/code&amp;gt; doit être stable avant que &amp;lt;code&amp;gt;assistant&amp;lt;/code&amp;gt; ne démarre son développement — une dépendance critique dans un mono-repo.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;erreur à ne pas commettre : créer trop d&amp;amp;#8217;agents trop tôt. &amp;lt;code&amp;gt;plantuml-plugin&amp;lt;/code&amp;gt; a attendu la session 108 avant de formaliser un agent spécialisé pour le pool de clés API. Avant ça, le contexte métier tenait dans &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt;. La règle empirique : un agent spécialisé se justifie quand son domaine métier dépasse 100 lignes de documentation.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_la_convention_de_nommage_des_sessions&amp;quot;&amp;gt;La Convention de Nommage des Sessions&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un détail qui paraît futile mais qui devient critique quand on atteint 100 sessions. Comment nommer les fichiers d&amp;amp;#8217;archive ?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ai appris à mes dépens qu&amp;amp;#8217;une convention est nécessaire — quatre projets, quatre formats différents au début, et je ne m&amp;amp;#8217;y retrouvais plus. Aujourd&amp;amp;#8217;hui, la convention que j&amp;amp;#8217;ai stabilisée est :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code&amp;gt;----
{N}-{type}-{sujet-kebab-case}.adoc
----

Exemples concrets :

* `1-chore-migration-gouvernance-agent.adoc` — session 1, type chore
* `10-solidification-tests.adoc` — session 10, sans type explicite (le sujet suffit)
* `036-debug-graphify-symlink-epic9.adoc` — session 36 avec numéro sur 3 chiffres pour le tri

Le numéro de session est le critère de tri principal. Les projets utilisant des numéros sur 3 chiffres (001, 036, 133) évitent les problèmes de tri lexicographique quand on dépasse 99. C&amp;#39;est ce que j&amp;#39;utilise désormais sur `magic-stick` : `001-init-projet.adoc`, `036-debug-graphify-symlink-epic9.adoc`.

Le type est facultatif et dérivé des mots-clés de la session (debug, feature, refactor, docs, chore, test). Le sujet en kebab-case est la partie la plus importante : il doit permettre de retrouver une session sans ouvrir le fichier. Si vous vous demandez « c&amp;#39;était quelle session où on a corrigé le timeout des tests d&amp;#39;intégration ? », la réponse est `124-fix-timeout-integration-test.adoc`.

Pour les sessions historiques reconstituées (projets nés avant la gouvernance), j&amp;#39;utilise des numéros négatifs. Sur `cheroliv.com`, les sessions -6 à 0 couvrent toute l&amp;#39;histoire pré-gouvernance du projet. Et pour les sessions « non documentées » ou perdues, je crée une entrée dans `SESSIONS_HISTORY.adoc` sans archive correspondante, avec un score `?`. C&amp;#39;est plus honnête que faire semblant.

[plantuml, format=svg, id=diag-naming-convention, alt=&amp;quot;Arbre de décision pour le nommage des fichiers de session&amp;quot;]
----
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam wrapWidth 200

title Convention de Nommage des Sessions

start

:Une session se termine;
note right: Trigger &amp;quot;fin de session&amp;quot;

if (Session antérieure\nà la gouvernance ?) then (oui)
  :Numéro **NÉGATIF**\n-6, -5 ... 0;
  note right: Historique\nreconstitué
  :Suffixe : reconstitution;
else (non)
  :Numéro **POSITIF**\nsur 3 chiffres si &amp;amp;gt; 99;
  note right: 001, 036, 133\npour le tri lexicographique

  :Détecter le **TYPE**;
  if (Mots-clés trouvés ?) then (oui)
    :debug / feature / refactor\ndocs / chore / test;
  else (non)
    :Omettre le type\n(le sujet suffit);
  endif

  :Formuler le **SUJET** en kebab-case;
  note right
    Ex: fix-timeout-integration-test
    Doit permettre de retrouver
    sans ouvrir le fichier
  end note
endif

:Nom final : {N}-{type}-{sujet}.adoc;
note right
  • 1-chore-migration-gouvernance.adoc
  • 036-debug-graphify-symlink.adoc
  • 124-fix-timeout-integration-test.adoc
  • 133-epic11-article-blog-kg.adoc
end note

if (Session documentée ?) then (oui)
  :Créer archive dans sessions/;
  :Ajouter ligne SESSIONS_HISTORY\navec score X/10;
else (non)
  :Ajouter ligne SESSIONS_HISTORY\navec score **?**\n**sans archive**;
  note right: L&amp;#39;honnêteté\nplutôt que le vide
endif

stop
@enduml
----

==== `TEST_COVERAGE_ANALYSIS.adoc` — L&amp;#39;Étape 5 Décortiquée

L&amp;#39;étape 5 de la procédure de fin de session est la plus mystérieuse. Elle dit « Mettre à jour `TEST_COVERAGE_ANALYSIS.adoc` si des tests ont été ajoutés ou modifiés. » Mais à quoi ressemble ce fichier ?

Sur `plantuml-plugin`, il a évolué de quelques lignes à une structure complète. Voici sa forme stabilisée :

[source]
----
= Analyse de Couverture de Tests

== Suivi des Tests
|===
| Classe de test | Type | Tests | Statut | Dernière MAJ
| PlantumlServiceTest | unit | 45/45 | ✅ PASS | 2026-04-23
| ApiKeyPoolTest | integration | 15/15 | ✅ PASS | 2026-04-20
|===

== Historique par Session
| Session | Tests ajoutés | Tests modifiés | Couverture
| 133     | 0             | 2              | 100%
| 132     | 5             | 0              | 100%
|===
----

L&amp;#39;intérêt n&amp;#39;est pas le fichier lui-même — c&amp;#39;est l&amp;#39;obligation de *noter* ce qui a changé. Sans cette étape, après 50 sessions, vous ne savez plus quels tests couvrent quoi. L&amp;#39;agent non plus. Le fichier devient le référentiel unique de vérité sur la couverture de tests du projet.

Pour les projets sans tests traditionnels (comme `magic-stick` qui teste des scripts bash), l&amp;#39;étape 5 est remplacée par `SCRIPT_VERIFICATION.adoc`. Le mécanisme est le même : un fichier qui suit l&amp;#39;état de validation des scripts. Adaptez l&amp;#39;étape 5 à votre projet, mais ne la sautez jamais. Elle est le filet de sécurité qui empêche la régression silencieuse.

Si votre projet n&amp;#39;a *aucun* test — ni unitaire, ni fonctionnel, ni script — créez quand même le fichier vide avec une section « À faire : définir une stratégie de test. » C&amp;#39;est un marque-page qui rappellera à votre futur vous que ce sujet n&amp;#39;est pas traité.

[plantuml, format=svg, id=diag-session-flow, alt=&amp;quot;Flux d&amp;#39;une session type avec Eager/Lazy et agents&amp;quot;]
----
@startuml
skinparam backgroundColor #FEFEFE

start

:Début session;
note right: L&amp;#39;agent est une page blanche

:Chargement EAGER auto;
note right
  * AGENT.adoc (règles absolues)
  * PROMPT_REPRISE.adoc (mission N)
  * INDEX.adoc (état projet)
end note

if (Mission claire ?) then (oui)
  :Exécution directe;
else (non)
  :Charge LAZY sur demande;
  note right
    * SESSIONS_HISTORY.adoc (contexte passé)
    * sessions/{N-1}-*.adoc (décisions)
    * *_REFERENCE.adoc (architechture)
  end note
endif

:Délégation agent spécialisé ?;

if (CODER ?) then (oui)
  :Lit CODER.adoc;
  :Suit conventions FTL/CSS;
elseif (SCRUM Master ?) then (oui)
  :Lit SCRUM_MASTER.adoc;
  :Structure livrable imposée;
elseif (PlantUML ?) then (oui)
  :Lit PLANTUML_DESIGNER.adoc;
  :Syntaxe PUML + intégration;
else (non)
endif

:Travail de la session;

:Fin de session (trigger utilisateur);

:Procédure 6 étapes;
note right
  1. Archive sessions/N-*.adoc
  2. Maj PROMPT_REPRISE.adoc (N+1)
  3. Maj SESSIONS_HISTORY.adoc
  4. Maj INDEX.adoc
  5. Maj TEST_COVERAGE (si applicable)
  6. Maj COMPLETED_TASKS_ARCHIVE.adoc
end note

:Checklist [✅] x 6;

stop
@enduml
----

Le diagramme ci-dessus montre le cycle de vie complet d&amp;#39;une session. Le point clé est la bifurcation après le chargement EAGER : soit la mission est assez claire pour exécuter directement (80% des cas), soit l&amp;#39;agent charge du LAZY pour résoudre une ambiguïté (20% des cas). C&amp;#39;est cette discrimination qui économise les tokens.

== La Procédure de Fin de Session : La Règle d&amp;#39;Or

=== Pourquoi elle est Incontournable

Sans cette procédure, la stratégie Eager/Lazy ne sert à rien. C&amp;#39;est elle qui transforme le travail de la session en information persistante. Elle s&amp;#39;exécute **à la demande explicite de l&amp;#39;utilisateur** (mots-clés : &amp;quot;fin de session&amp;quot;, &amp;quot;je quitte&amp;quot;, etc.), et elle est **obligatoire** -- aucune exception, aucune omission.

Le fichier `SESSION_CHECKLIST.adoc` définit des métriques de session idéale :

* Durée : 15-30 minutes
* Fichiers modifiés : 1-3 maximum
* Échanges LLM : 5-10 messages
* Contexte tokens : &amp;amp;lt; 50k

Et des signes qu&amp;#39;il faut changer de session : _Le LLM répète des erreurs déjà corrigées_, _Plus de 3 fichiers modifiés en parallèle_, _Conversation &amp;amp;gt; 50 messages_. La règle d&amp;#39;or : **Mieux vaut 5 sessions de 20 minutes qu&amp;#39;une session de 2 heures avec debugging chaos.**

=== Le Flux des 6 Étapes (Silencieusement)

[plantuml, format=svg, id=diag-end-session-flow, alt=&amp;quot;Flux de la procédure de fin de session&amp;quot;]
----
@startuml
skinparam defaultTextAlignment center
skinparam wrapWidth 200
skinparam activityBackgroundColor #E3F2FD

start
:L&amp;#39;utilisateur dit &amp;quot;fin de session&amp;quot;;
note right: Mots-clés déclencheurs

:Agent détecte le trigger;

:Étape 1\nCréer archive\n`.agents/sessions/N-*.adoc`;
note right: Tout le contexte de la session

:Étape 2\nMettre à jour\n`PROMPT_REPRISE.adoc`;
note right: Mission N + critères d&amp;#39;acceptation N+1

:Étape 3\nMettre à jour\n`SESSIONS_HISTORY.adoc`;
note right: Ligne récap : # / Date / Type / Sujet / Score

:Étape 4\nMettre à jour\n`INDEX.adoc`;
note right: État courant, roadmap, fichiers modifiés

:Étape 5\nMettre à jour\n`TEST_COVERAGE_ANALYSIS.adoc`;
note right: Si tests ajoutés ou modifiés

:Étape 6\nMettre à jour\n`COMPLETED_TASKS_ARCHIVE.adoc`;
note right: Archiver tâches terminées

:Afficher la checklist de confirmation;
note right: Vérifier que chaque [✅] est mérité

stop
@enduml
----

=== Les Résultats de 150+ Sessions

Voici ce que donne cette procédure appliquée systématiquement sur mes quatre projets :

**plantuml-plugin** :

* **133 sessions** depuis le début du projet
* **240/240 tests PASS** (100% couverture) -- EPICs 1-7 terminées
* **57 scénarios Cucumber BDD** validés
* Règle de sûreté sur les fichiers de config née d&amp;#39;une erreur réelle (Session 2 bakery-plugin)

**bakery-plugin** :

* **11 sessions** en deux semaines
* Migration Supabase → Firebase terminée (9 tests corrigés)
* EPIC 6 (publishProfile) fonctionnel en production
* Règle 0 créée : `publishToMavenLocal` obligatoire après chaque modif

**magic-stick** :

* **23 sessions** pour construire un système live Xubuntu avec partition A/B
* Première ISO générée à la session 10
* Tests de boot QEMU + VNC formalisés (documentation LAZY de 144 lignes)
* CI/CD SourceForge fonctionnel

**cheroliv.com** :

* **9 sessions formelles** + reconstitution de 7 sessions pré-système
* Article 0101 (OpenCode PATH) publié
* Article 0108 (celui-ci) réécrit après analyse de ses lacunes
* Gouvernance complète migrée de Markdown vers AsciiDoc

=== La Checklist Finale

Après exécution silencieuse des 6 étapes, l&amp;#39;agent doit afficher une checklist de confirmation :&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;✅ Procédure de fin de session exécutée
📋 Checklist :
[✅] 1. Archive session N créée
[✅] 2. PROMPT_REPRISE.adoc mis à jour pour session N+1
[✅] 3. SESSIONS_HISTORY.adoc mis à jour
[✅] 4. INDEX.adoc mis à jour
[✅] 5. TEST_COVERAGE_ANALYSIS.adoc mis à jour (si applicable)
[✅] 6. COMPLETED_TASKS_ARCHIVE.adoc mis à jour&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Règle absolue&amp;lt;/strong&amp;gt; : aucune étape ne peut être marquée &amp;lt;code&amp;gt;[✅]&amp;lt;/code&amp;gt; si le fichier n&amp;amp;#8217;a pas été effectivement modifié et vérifié.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_guide_de_bootstrap_jour_1_session_0&amp;quot;&amp;gt;Le Guide de Bootstrap : Jour 1, Session 0&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Vous êtes convaincu par la méthode. Vous voulez l&amp;amp;#8217;appliquer à un nouveau projet. Par où commencer ?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ai vécu ce moment le 28 avril 2026. J&amp;amp;#8217;ouvre Opencode sur &amp;lt;code&amp;gt;jhipster-gradle-plugins&amp;lt;/code&amp;gt;, mon mono-repo de deux plugins Gradle JHipster. C&amp;amp;#8217;est un projet qui existe déjà — le code est là, les tâches Gradle fonctionnent. Mais la gouvernance agent ? Zéro. Page blanche. Comme &amp;lt;code&amp;gt;plantuml-plugin&amp;lt;/code&amp;gt; à sa session 1, il y a des mois.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Voici la procédure exacte que j&amp;amp;#8217;ai suivie, et que je suivrai pour tout nouveau projet. Notez bien l&amp;amp;#8217;ordre — il est important.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-bootstrap&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-e11aa343b861c2c558099445242ab4be.svg&amp;quot; alt=&amp;quot;Flux de bootstrap en 6 étapes pour initialiser la gouvernance agent sur un nouveau projet&amp;quot; width=&amp;quot;1736&amp;quot; height=&amp;quot;3371&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_étape_0_créer_opencode_json&amp;quot;&amp;gt;Étape 0 : Créer &amp;lt;code&amp;gt;opencode.json&amp;lt;/code&amp;gt;&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est le premier fichier. Pas &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt;, pas &amp;lt;code&amp;gt;INDEX.adoc&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;opencode.json&amp;lt;/code&amp;gt; d&amp;amp;#8217;abord, pour une raison simple : si vous créez &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt; en premier, vous allez oublier de créer le pont qui le charge automatiquement. Je l&amp;amp;#8217;ai fait sur &amp;lt;code&amp;gt;bakery-plugin&amp;lt;/code&amp;gt;, je sais de quoi je parle.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_étape_1_créer_les_dossiers&amp;quot;&amp;gt;Étape 1 : Créer les Dossiers&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;mkdir -p .agents/sessions .agents/archives&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Deux dossiers vides. &amp;lt;code&amp;gt;sessions/&amp;lt;/code&amp;gt; recevra les archives de chaque session. &amp;lt;code&amp;gt;archives/&amp;lt;/code&amp;gt; recevra les COMPLETED_TASKS_ARCHIVE mensuels. Ces dossiers doivent exister &amp;lt;strong&amp;gt;avant&amp;lt;/strong&amp;gt; que l&amp;amp;#8217;agent n&amp;amp;#8217;ait besoin d&amp;amp;#8217;écrire dedans. Un agent qui doit créer le dossier ET le fichier en même temps, c&amp;amp;#8217;est un agent qui peut échouer silencieusement.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_étape_2_créer_agent_adoc_le_fichier_maître&amp;quot;&amp;gt;Étape 2 : Créer &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt; — Le Fichier Maître&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Structure minimale pour la première version (elle grandira) :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code&amp;gt;= {NOM_PROJET} — Directives Agent

[CAUTION]&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;ARRÊT OBLIGATOIRE&amp;lt;/strong&amp;gt; avant rm, Write, suppression :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;LIRE le fichier en entier&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;VÉRIFIER git ls-files&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;DEMANDER confirmation&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;ATTENDRE &amp;quot;oui&amp;quot;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_projet&amp;quot;&amp;gt;Projet&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Nom&amp;lt;/strong&amp;gt; : &amp;amp;#8230;&amp;amp;#8203; &amp;lt;strong&amp;gt;Stack&amp;lt;/strong&amp;gt; : &amp;amp;#8230;&amp;amp;#8203; &amp;lt;strong&amp;gt;Documentation&amp;lt;/strong&amp;gt; : AsciiDoc&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_règles_absolues&amp;quot;&amp;gt;Règles Absolues&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_0_environnement_de_dev&amp;quot;&amp;gt;0. ENVIRONNEMENT DE DEV&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Commandes essentielles&amp;amp;#8230;&amp;amp;#8203;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_1_commitsgit&amp;quot;&amp;gt;1. COMMITS/GIT&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Interdiction formelle&amp;amp;#8230;&amp;amp;#8203;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_1b_fichiers_de_configuration_règle_absolue_de_sûreté&amp;quot;&amp;gt;1b. FICHIERS DE CONFIGURATION — RÈGLE ABSOLUE DE SÛRETÉ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ne jamais écraser&amp;amp;#8230;&amp;amp;#8203;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_2_tests_en_fin_de_session&amp;quot;&amp;gt;2. TESTS EN FIN DE SESSION&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Interdiction formelle&amp;amp;#8230;&amp;amp;#8203;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_3_procédure_de_fin_de_session&amp;quot;&amp;gt;3. PROCÉDURE DE FIN DE SESSION&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Les 6 étapes obligatoires&amp;amp;#8230;&amp;amp;#8203;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_gestion_du_contexte_lazyeager&amp;quot;&amp;gt;Gestion du Contexte — LAZY/EAGER&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Fichiers EAGER / Fichiers LAZY&amp;amp;#8230;&amp;amp;#8203;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce template minimal permet à l&amp;amp;#8217;agent de démarrer. La version riche — avec la structure du projet, les composants clés, les EPICs, le backlog — viendra à la session 1, quand l&amp;amp;#8217;agent aura déjà les règles de base en main et pourra vous aider à enrichir le document.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_étape_3_créer_prompt_reprise_adoc_la_mission_session_1&amp;quot;&amp;gt;Étape 3 : Créer &amp;lt;code&amp;gt;PROMPT_REPRISE.adoc&amp;lt;/code&amp;gt; — La Mission Session 1&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un fichier qui dit explicitement : « Ceci est la session 1, mission à définir. » Maximum 70 lignes, avec une section Session 0 (résumé du bootstrap) et une section Session 1 (priorités à définir avec l&amp;amp;#8217;utilisateur).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_étape_4_créer_agentsindex_adoc_le_point_dentrée&amp;quot;&amp;gt;Étape 4 : Créer &amp;lt;code&amp;gt;.agents/INDEX.adoc&amp;lt;/code&amp;gt; — Le Point d&amp;amp;#8217;Entrée&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le fichier qui contiendra les règles absolues (version exécutive) et le tableau des sessions. Pour le bootstrap, il liste les règles 0 à 3 dans leur format concis, le portefeuille de projets (en incluant le nouveau projet avec un emoji 🆕), et la roadmap vide prête à être remplie.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_étape_5_créer_les_fichiers_lazy_structurants&amp;quot;&amp;gt;Étape 5 : Créer les Fichiers LAZY Structurants&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Dans l&amp;amp;#8217;ordre :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;.agents/SESSIONS_HISTORY.adoc&amp;lt;/code&amp;gt; — un tableau avec uniquement la session 0&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;.agents/SESSION_CHECKLIST.adoc&amp;lt;/code&amp;gt; — le template « Quand changer de session »&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;.agents/PROCEDURES.adoc&amp;lt;/code&amp;gt; — la procédure complète des 6 étapes + EAGER/LAZY&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;.agents/AGENT_SESSION_MANAGER.adoc&amp;lt;/code&amp;gt; — le template d&amp;amp;#8217;archive&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;.agents/TEST_COVERAGE_ANALYSIS.adoc&amp;lt;/code&amp;gt; — le tableau de suivi des tests, vide au départ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Si votre projet a un domaine métier complexe (comme &amp;lt;code&amp;gt;jhipster-gradle-plugins&amp;lt;/code&amp;gt; avec son mono-repo persistence/assistant), créez les agents spécialisés dès maintenant :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;.agents/PLUGIN_DEVELOPER.adoc&amp;lt;/code&amp;gt; — les conventions de code et le boundary de dépendances (si plugin)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;.agents/BACKLOG_MANAGER.adoc&amp;lt;/code&amp;gt; — la structure de planification et les risques identifiés&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ne créez pas d&amp;amp;#8217;agents que vous n&amp;amp;#8217;utiliserez pas. Un agent sans conventions concrètes à encoder est un fichier mort qui pollue &amp;lt;code&amp;gt;.agents/&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_étape_6_ajouter_le_projet_au_portefeuille_de_tous_les_projets&amp;quot;&amp;gt;Étape 6 : Ajouter le Projet au Portefeuille de TOUS les Projets&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est l&amp;amp;#8217;étape qu&amp;amp;#8217;on oublie systématiquement. Chaque &amp;lt;code&amp;gt;INDEX.adoc&amp;lt;/code&amp;gt; de chaque projet contient un tableau « Portefeuille de Projets » qui liste TOUS les projets avec la même méthodologie. Quand vous créez un nouveau projet, vous devez :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Ajouter une ligne dans le portefeuille du nouveau projet (logique)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Ajouter une ligne dans le portefeuille de TOUS les projets existants — oui, tous&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Sur mes quatre (maintenant cinq) projets, cela veut dire ouvrir les &amp;lt;code&amp;gt;INDEX.adoc&amp;lt;/code&amp;gt; de &amp;lt;code&amp;gt;magic-stick&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bakery-gradle&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;cheroliv.com&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;plantuml-gradle&amp;lt;/code&amp;gt; et y ajouter la ligne &amp;lt;code&amp;gt;jhipster-gradle-plugins | Session 1 | &amp;amp;#8230;&amp;amp;#8203; | 2026-04-28 🆕&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est fastidieux. C&amp;amp;#8217;est manuel. C&amp;amp;#8217;est aussi la seule façon de garantir que, quel que soit le projet sur lequel vous travaillez, l&amp;amp;#8217;agent sait quels autres projets existent et quel est leur état. À la session 012 de &amp;lt;code&amp;gt;magic-stick&amp;lt;/code&amp;gt;, l&amp;amp;#8217;agent a détecté deux incohérences dans le portefeuille — &amp;lt;code&amp;gt;bakery-gradle&amp;lt;/code&amp;gt; avait son COMPLETED_TASKS_ARCHIVE en retard, et &amp;lt;code&amp;gt;plantuml-gradle&amp;lt;/code&amp;gt; avait un décalage entre sa documentation de procédure (5 étapes) et son INDEX (6 étapes). Sans ce tableau transverse, ces incohérences seraient restées invisibles.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-portfolio-graph&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-c2b21ca8d7481b154894427d05899032.svg&amp;quot; alt=&amp;quot;Graphe du portefeuille de projets — références croisées entre INDEX.adoc&amp;quot; width=&amp;quot;1501&amp;quot; height=&amp;quot;802&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Je vous entends d&amp;amp;#8217;ici : « Mais c&amp;amp;#8217;est de la duplication ! » Oui. C&amp;amp;#8217;est de la duplication volontaire. Chaque &amp;lt;code&amp;gt;INDEX.adoc&amp;lt;/code&amp;gt; est autonome. Si vous ouvrez une session sur &amp;lt;code&amp;gt;magic-stick&amp;lt;/code&amp;gt;, l&amp;amp;#8217;agent doit savoir que &amp;lt;code&amp;gt;plantuml-gradle&amp;lt;/code&amp;gt; en est à la session 133 sans avoir à ouvrir un fichier dans un autre répertoire. C&amp;amp;#8217;est le prix de l&amp;amp;#8217;indépendance entre projets — et il est de 5 lignes par portefeuille.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ce_que_le_bootstrap_coûte&amp;quot;&amp;gt;Ce que le Bootstrap Coûte&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Tout ça prend 20 minutes. Vingt minutes une fois, pour ne plus jamais en perdre vingt au début de chaque session. Le ROI est immédiat : dès la session 2, l&amp;amp;#8217;agent reprend là où vous avez laissé la session 1.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Sur &amp;lt;code&amp;gt;jhipster-gradle-plugins&amp;lt;/code&amp;gt;, ce bootstrap m&amp;amp;#8217;a pris exactement 18 minutes — de &amp;lt;code&amp;gt;mkdir .agents/&amp;lt;/code&amp;gt; au dernier &amp;lt;code&amp;gt;INDEX.adoc&amp;lt;/code&amp;gt; mis à jour dans le portefeuille de &amp;lt;code&amp;gt;magic-stick&amp;lt;/code&amp;gt;. La session 1, qui suivra, démarrera avec un agent qui connaît déjà la structure du mono-repo, les commandes Gradle, et le boundary critique entre &amp;lt;code&amp;gt;persistence/&amp;lt;/code&amp;gt; (lightweight) et &amp;lt;code&amp;gt;assistant/&amp;lt;/code&amp;gt; (lourd). Vingt minutes bien investies.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_les_4_maintenant_5_projets_5_gouvernances_1_méthode&amp;quot;&amp;gt;Les 4 (maintenant 5) Projets, 5 Gouvernances, 1 Méthode&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le système Eager/Lazy n&amp;amp;#8217;est pas un boilerplate copié-collé. Chaque projet a adapté la méthode à ses spécificités.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_cheroliv_com_le_site_personnel&amp;quot;&amp;gt;cheroliv.com : Le Site Personnel&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Spécificité&amp;lt;/strong&amp;gt; : Contenu éditorial, accessibilité WCAG 2.1 AA, JBake statique. &amp;lt;strong&amp;gt;Adaptation&amp;lt;/strong&amp;gt; : Six épopées priorisées (P0-P4), agents spécialisés (CODER, SCRUM_MASTER, PLANTUML_DESIGNER), critères d&amp;amp;#8217;acceptation transverses sur l&amp;amp;#8217;accessibilité. &amp;lt;strong&amp;gt;Règle emblématique&amp;lt;/strong&amp;gt; : &amp;lt;code&amp;gt;./gradlew serve&amp;lt;/code&amp;gt; obligatoire, interdiction formelle du script &amp;lt;code&amp;gt;jbake.sh&amp;lt;/code&amp;gt; externe.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_bakery_gradle_le_plugin_multi_purpose&amp;quot;&amp;gt;bakery-gradle : Le Plugin Multi-Purpose&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Spécificité&amp;lt;/strong&amp;gt; : Plugin Gradle avec tâches de publication, génération de code Firebase, parsing YAML. &amp;lt;strong&amp;gt;Adaptation&amp;lt;/strong&amp;gt; : Règle 0 (publishToMavenLocal), règle de sûreté sur les fichiers de config renforcée par l&amp;amp;#8217;incident du &amp;lt;code&amp;gt;site.yml&amp;lt;/code&amp;gt;, EPIC 9 et 10 sur la configuration multi-fichiers. &amp;lt;strong&amp;gt;Règle emblématique&amp;lt;/strong&amp;gt; : &amp;lt;code&amp;gt;publishToMavenLocal&amp;lt;/code&amp;gt; après chaque modification du code source du plugin.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_plantuml_gradle_le_plugin_ia&amp;quot;&amp;gt;plantuml-gradle : Le Plugin IA&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Spécificité&amp;lt;/strong&amp;gt; : Intégration LangChain4j, génération de diagrammes PlantUML via LLM, tests avec clés API cloud. &amp;lt;strong&amp;gt;Adaptation&amp;lt;/strong&amp;gt; : Documentation LAZY dense (ARCHITECTURE, API_KEY_POOL_REFERENCE, DATASET_FINETUNING), EPICs numérotés (1-11 terminés, 107+ en cours), séparation EAGER/LAZY optimisée (gain de 60% de tokens). &amp;lt;strong&amp;gt;Règle emblématique&amp;lt;/strong&amp;gt; : Fichiers &amp;lt;code&amp;gt;*_ESSENTIALS.adoc&amp;lt;/code&amp;gt; (50 lignes) vs &amp;lt;code&amp;gt;*_REFERENCE.adoc&amp;lt;/code&amp;gt; (illimité) pour le pool de clés API.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_magic_stick_le_système_live&amp;quot;&amp;gt;magic-stick : Le Système Live&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Spécificité&amp;lt;/strong&amp;gt; : Build d&amp;amp;#8217;ISO Linux live (Xubuntu), partitionnement GPT A/B, CI/CD avec SourceForge. &amp;lt;strong&amp;gt;Adaptation&amp;lt;/strong&amp;gt; : Références techniques LAZY complexes (AB_PARTITION, BOOT_TEST), SCRIPT_VERIFICATION.adoc comme étape 5 spécifique (pas de tests traditionnels, mais vérification de scripts bash). &amp;lt;strong&amp;gt;Règle emblématique&amp;lt;/strong&amp;gt; : &amp;lt;code&amp;gt;isoTestAB&amp;lt;/code&amp;gt; skipé en CI (runners non privilégiés), tests réservés aux environnements locaux avec Docker &amp;lt;code&amp;gt;--privileged&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_règles_absolues_transverses&amp;quot;&amp;gt;Règles Absolues Transverses&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Quelques règles critiques qui apparaissent dans le fichier &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt; Eager et s&amp;amp;#8217;appliquent à toutes les sessions sur tous les projets :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Environnement de dev&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;✅ Utiliser la commande propre au projet (&amp;lt;code&amp;gt;./gradlew serve&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;./gradlew functionalTest&amp;lt;/code&amp;gt;, etc.)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;❌ Interdit d&amp;amp;#8217;utiliser des scripts externes non versionnés&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Git&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;✅ Lecture seule autorisée (&amp;lt;code&amp;gt;git status&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;git diff&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;git log&amp;lt;/code&amp;gt;)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;❌ &amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;git commit&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;git push&amp;lt;/code&amp;gt; interdits sans permission explicite&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;❌ &amp;lt;code&amp;gt;git commit --amend&amp;lt;/code&amp;gt; interdit sauf conditions méticuleusement respectées&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Fichiers de Configuration&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;❌ Ne jamais écraser un fichier config avec un &amp;lt;code&amp;gt;Write&amp;lt;/code&amp;gt; complet quand un &amp;lt;code&amp;gt;Edit&amp;lt;/code&amp;gt; partiel suffit&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;❌ Ne jamais remplacer des valeurs sensibles par des valeurs factices&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;❌ Vérifier &amp;lt;code&amp;gt;git check-ignore&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;git ls-files&amp;lt;/code&amp;gt; avant toute modification&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Tests&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;❌ Ne jamais lancer de tests en procédure de fin de session sans permission explicite&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Outils Interdits&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;❌ &amp;lt;code&amp;gt;TodoWrite&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;Task&amp;lt;/code&amp;gt;&amp;amp;#8201;&amp;amp;#8212;&amp;amp;#8201;la gouvernance se fait via les fichiers AsciiDoc, pas via des outils externes&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_les_anti_patterns_ce_que_150_sessions_mont_appris&amp;quot;&amp;gt;Les Anti-Patterns : Ce Que 150+ Sessions M&amp;amp;#8217;ont Appris&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avec le recul, certaines erreurs sont devenues des patterns tellement prévisibles que je peux les lister comme des anti-patterns — des pièges dans lesquels tout nouveau projet tombera probablement. Les voici, classés par ordre de fréquence.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-antipatterns&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-c4b4c7d8bfdda0f1287bc4f14752a381.svg&amp;quot; alt=&amp;quot;Les 7 anti-patterns de la gouvernance agent — arbre des pièges à éviter&amp;quot; width=&amp;quot;1784&amp;quot; height=&amp;quot;5600&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_anti_pattern_1_lagent_sans_opencode_json&amp;quot;&amp;gt;Anti-Pattern 1 : L&amp;amp;#8217;Agent sans &amp;lt;code&amp;gt;opencode.json&amp;lt;/code&amp;gt;&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est l&amp;amp;#8217;erreur numéro un. Vous avez écrit un magnifique &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt; de 200 lignes, mais il n&amp;amp;#8217;est jamais chargé automatiquement. L&amp;amp;#8217;agent démarre nu. Vous passez 20 minutes à le recontextualiser — exactement ce que la méthode est censée éviter.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Symptôme&amp;lt;/strong&amp;gt; : L&amp;amp;#8217;agent pose des questions basiques sur la structure du projet alors que tout est dans &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt;. &amp;lt;strong&amp;gt;Correction&amp;lt;/strong&amp;gt; : Créer &amp;lt;code&amp;gt;opencode.json&amp;lt;/code&amp;gt; avec le bloc &amp;lt;code&amp;gt;instructions: [&amp;quot;AGENT.adoc&amp;quot;]&amp;lt;/code&amp;gt;. Vérifier que le fichier existe dans le working directory d&amp;amp;#8217;Opencode.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_anti_pattern_2_trop_dagents_trop_tôt&amp;quot;&amp;gt;Anti-Pattern 2 : Trop d&amp;amp;#8217;Agents Trop Tôt&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;À la session 2 de votre projet, vous créez 5 agents spécialisés. Aucun n&amp;amp;#8217;a de contenu réel, ce sont tous des stubs. Résultat : &amp;lt;code&amp;gt;.agents/&amp;lt;/code&amp;gt; est pollué de fichiers vides, et l&amp;amp;#8217;agent hésite sur lequel charger.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Symptôme&amp;lt;/strong&amp;gt; : Des fichiers d&amp;amp;#8217;agent contenant uniquement « À définir » ou une structure vide de 10 lignes. &amp;lt;strong&amp;gt;Correction&amp;lt;/strong&amp;gt; : Un agent spécialisé se justifie quand son domaine métier dépasse 100 lignes ou qu&amp;amp;#8217;il encode au moins 5 règles concrètes. En dessous, le contenu tient dans &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_anti_pattern_3_le_prompt_reprise_fantôme&amp;quot;&amp;gt;Anti-Pattern 3 : Le PROMPT_REPRISE Fantôme&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;PROMPT_REPRISE.adoc&amp;lt;/code&amp;gt; est mis à jour&amp;amp;#8230;&amp;amp;#8203; mais uniquement à la fin de la session, quand l&amp;amp;#8217;agent exécute la procédure. Entre-temps, la mission réelle de la session a dérivé — on a corrigé un bug imprévu au lieu d&amp;amp;#8217;implémenter la feature planifiée. Le &amp;lt;code&amp;gt;PROMPT_REPRISE.adoc&amp;lt;/code&amp;gt; de fin de session ne reflète pas ce qui s&amp;amp;#8217;est &amp;lt;strong&amp;gt;vraiment&amp;lt;/strong&amp;gt; passé.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Symptôme&amp;lt;/strong&amp;gt; : La section « Priorités » de &amp;lt;code&amp;gt;PROMPT_REPRISE.adoc&amp;lt;/code&amp;gt; mentionne une feature qui n&amp;amp;#8217;a pas été touchée, alors que vous avez passé la session sur un bug critique. &amp;lt;strong&amp;gt;Correction&amp;lt;/strong&amp;gt; : Mettre à jour &amp;lt;code&amp;gt;PROMPT_REPRISE.adoc&amp;lt;/code&amp;gt; en temps réel quand la session dérive de sa mission initiale. Ne pas attendre la procédure de fin de session pour documenter le changement de cap. 30 secondes d&amp;amp;#8217;édition pendant la session valent mieux qu&amp;amp;#8217;un &amp;lt;code&amp;gt;PROMPT_REPRISE&amp;lt;/code&amp;gt; mensonger.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_anti_pattern_4_larchive_vide&amp;quot;&amp;gt;Anti-Pattern 4 : L&amp;amp;#8217;Archive Vide&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La procédure de fin de session crée l&amp;amp;#8217;archive&amp;amp;#8230;&amp;amp;#8203; mais l&amp;amp;#8217;agent, pressé d&amp;amp;#8217;afficher sa checklist, remplit le template avec des placeholders. &amp;lt;code&amp;gt;{detail}&amp;lt;/code&amp;gt; devient « Détail à compléter plus tard ». Ce « plus tard » n&amp;amp;#8217;arrive jamais.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Symptôme&amp;lt;/strong&amp;gt; : Des archives de session contenant les mots « TODO », « à compléter », ou des sections vides. &amp;lt;strong&amp;gt;Correction&amp;lt;/strong&amp;gt; : La règle absolue dit qu&amp;amp;#8217;aucune étape ne peut être marquée [✅] si le fichier n&amp;amp;#8217;a pas été effectivement modifié. Appliquez-la à vous-même : relisez l&amp;amp;#8217;archive avant d&amp;amp;#8217;afficher la checklist. Si une section est vide, remplissez-la maintenant.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_anti_pattern_5_le_portefeuille_fantôme&amp;quot;&amp;gt;Anti-Pattern 5 : Le Portefeuille Fantôme&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Vous créez un nouveau projet avec une gouvernance parfaite. Mais vous oubliez de l&amp;amp;#8217;ajouter au portefeuille des autres projets. Trois semaines plus tard, vous ouvrez une session sur &amp;lt;code&amp;gt;magic-stick&amp;lt;/code&amp;gt; et l&amp;amp;#8217;agent vous dit que vous avez 4 projets. Vous en avez 5. L&amp;amp;#8217;agent ne le sait pas.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Symptôme&amp;lt;/strong&amp;gt; : Le comptage des projets dans les portefeuilles ne correspond pas à la réalité. &amp;lt;strong&amp;gt;Correction&amp;lt;/strong&amp;gt; : Scriptez la mise à jour du portefeuille, ou au minimum maintenez une checklist post-bootstrap qui inclut « Mettre à jour le portefeuille de tous les projets existants ». C&amp;amp;#8217;est l&amp;amp;#8217;étape la plus fastidieuse de la méthode, et donc la plus souvent omise.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_anti_pattern_6_la_redondance_cachée&amp;quot;&amp;gt;Anti-Pattern 6 : La Redondance Cachée&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Vous copiez-collez le même backlog de 50 lignes dans &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;INDEX.adoc&amp;lt;/code&amp;gt;. À la session suivante, vous mettez à jour l&amp;amp;#8217;un mais pas l&amp;amp;#8217;autre. Vos deux fichiers EAGER se contredisent.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Symptôme&amp;lt;/strong&amp;gt; : Des divergences entre les EPICs listées dans &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt; et celles dans &amp;lt;code&amp;gt;INDEX.adoc&amp;lt;/code&amp;gt;. &amp;lt;strong&amp;gt;Correction&amp;lt;/strong&amp;gt; : La redondance doit être &amp;lt;strong&amp;gt;assumée et bornée&amp;lt;/strong&amp;gt;. &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt; contient le backlog détaillé avec user stories. &amp;lt;code&amp;gt;INDEX.adoc&amp;lt;/code&amp;gt; contient UNIQUEMENT le tableau récapitulatif des EPICs (nom, progression, priorité). Si les deux divergent, c&amp;amp;#8217;est &amp;lt;code&amp;gt;INDEX.adoc&amp;lt;/code&amp;gt; qui fait foi — parce que c&amp;amp;#8217;est lui qui est mis à jour à chaque fin de session. Documentez cette règle dans votre &amp;lt;code&amp;gt;AGENT.adoc&amp;lt;/code&amp;gt; : « En cas de divergence entre AGENT.adoc et INDEX.adoc, INDEX.adoc est la source de vérité. »&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_anti_pattern_7_la_session_trop_longue&amp;quot;&amp;gt;Anti-Pattern 7 : La Session Trop Longue&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Vous ignorez les signaux du &amp;lt;code&amp;gt;SESSION_CHECKLIST.adoc&amp;lt;/code&amp;gt;. 2 heures, 85 messages, 12 fichiers modifiés. L&amp;amp;#8217;agent tourne en boucle, vous aussi. Vous auriez dû changer de session il y a 45 minutes.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Symptôme&amp;lt;/strong&amp;gt; : Le LLM répète des erreurs déjà corrigées, le contexte tokens dépasse 80k, vous avez modifié à la fois &amp;lt;code&amp;gt;persistence/&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;assistant/&amp;lt;/code&amp;gt; dans la même session. &amp;lt;strong&amp;gt;Correction&amp;lt;/strong&amp;gt; : Le &amp;lt;code&amp;gt;SESSION_CHECKLIST.adoc&amp;lt;/code&amp;gt; existe pour une raison. Respectez-le. La règle d&amp;amp;#8217;or n&amp;amp;#8217;est pas une suggestion. 5 sessions de 20 minutes &amp;amp;gt; 1 session de 2 heures.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_pourquoi_asciidoc&amp;quot;&amp;gt;Pourquoi AsciiDoc ?&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ai choisi AsciiDoc pour plusieurs raisons pragmatiques qui ont un impact direct sur l&amp;amp;#8217;efficacité de la gouvernance :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Structure sémantique riche&amp;lt;/strong&amp;gt; : sections, tableaux, admonitions, attributs de document. Un agent lit mieux un document structuré qu&amp;amp;#8217;un fond de texte.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Attributs de document&amp;lt;/strong&amp;gt; (&amp;lt;code&amp;gt;:jbake-type:&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;:jbake-status:&amp;lt;/code&amp;gt;) qui permettent de définir des métadonnées lisibles par la machine et l&amp;amp;#8217;humain.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Compatibilité avec JBake&amp;lt;/strong&amp;gt; : mon site statique est généré par JBake, qui traite nativement l&amp;amp;#8217;AsciiDoc. Les fichiers de gouvernance et les articles de blog partagent le même format. Mon article de blog &amp;lt;strong&amp;gt;sur&amp;lt;/strong&amp;gt; la gouvernance est écrit dans le même format que la gouvernance elle-même.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Longévité&amp;lt;/strong&amp;gt; : AsciiDoc est un format de documentation technique éprouvé, avec une spécification stable.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_résultat_une_continuité_sans_couture&amp;quot;&amp;gt;Résultat : Une Continuité sans Couture&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Depuis que j&amp;amp;#8217;ai mis ce système en place, passer d&amp;amp;#8217;une session Opencode à l&amp;amp;#8217;autre est devenu fluide. L&amp;amp;#8217;agent reprend exactement où je l&amp;amp;#8217;ai laissé, sans que j&amp;amp;#8217;aie à recontextualiser quoi que ce soit.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Les décisions prises à la session 3 sont accessibles à la session 133. Le backlog reste cohérent sur cinq projets simultanés. Les règles de sécurité (notamment sur git et les fichiers de config) sont respectées parce qu&amp;amp;#8217;elles sont omniprésentes dans le fichier Eager.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Les chiffres parlent :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;150+ sessions archivées&amp;lt;/strong&amp;gt; au total&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;60% de tokens EAGER économisés&amp;lt;/strong&amp;gt; après optimisation (Session 109)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Zéro rappel nécessaire&amp;lt;/strong&amp;gt; sur le contexte métier du pool de clés API&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;100% des tests PASS&amp;lt;/strong&amp;gt; sur plantuml-plugin (240/240)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Une seule catastrophe&amp;lt;/strong&amp;gt; (Session 2 bakery-plugin) qui a donné naissance à la règle de sûreté absolue&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est un &amp;lt;strong&amp;gt;système artisanal&amp;lt;/strong&amp;gt;, construit avec les outils du métier (AsciiDoc, git, Gradle), sans dépendance à une plateforme propriétaire. Il reflète ma conviction fondamentale : &amp;lt;strong&amp;gt;un développeur crédible construit et utilise ses propres outils&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_liens&amp;quot;&amp;gt;Liens&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Mon site : [cheroliv.com](&amp;lt;a href=&amp;quot;https://cheroliv.com&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://cheroliv.com&amp;lt;/a&amp;gt;)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le projet &amp;lt;code&amp;gt;bakery-gradle&amp;lt;/code&amp;gt; : [github.com/cheroliv/bakery-gradle-plugin](&amp;lt;a href=&amp;quot;https://github.com/cheroliv/bakery-gradle-plugin&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://github.com/cheroliv/bakery-gradle-plugin&amp;lt;/a&amp;gt;)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le projet &amp;lt;code&amp;gt;plantuml-gradle&amp;lt;/code&amp;gt; : [github.com/cheroliv/plantuml-gradle-plugin](&amp;lt;a href=&amp;quot;https://github.com/cheroliv/plantuml-gradle-plugin&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://github.com/cheroliv/plantuml-gradle-plugin&amp;lt;/a&amp;gt;)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le projet &amp;lt;code&amp;gt;magic-stick&amp;lt;/code&amp;gt; : [github.com/cheroliv/magic-stick](&amp;lt;a href=&amp;quot;https://github.com/cheroliv/magic-stick&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://github.com/cheroliv/magic-stick&amp;lt;/a&amp;gt;)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le projet &amp;lt;code&amp;gt;cheroliv.com&amp;lt;/code&amp;gt; : [github.com/cheroliv/cheroliv.github.io](&amp;lt;a href=&amp;quot;https://github.com/cheroliv/cheroliv.github.io&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://github.com/cheroliv/cheroliv.github.io&amp;lt;/a&amp;gt;)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Le code qu&amp;amp;#8217;on écrit pour soi est le laboratoire du code qu&amp;amp;#8217;on enseigne aux autres.&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>क्यों `serve` एक भद्दा साइट दिखा रहा था जबकि `publishSite` पूर्ण था</title>
            <link >https://cheroliv.com/blog/2026/0107_jbake_serve_rendering_bug_fix_post.html</link>
            <pubDate>Wed, 22 Apr 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0107_jbake_serve_rendering_bug_fix_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_दृश्य_चार_स्क्रीनशॉट_दो_रेंडर&amp;quot;&amp;gt;दृश्य: चार स्क्रीनशॉट, दो रेंडर&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_rendu_local&amp;quot;&amp;gt;Rendu local&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ऑनलाइन_रेंडर&amp;quot;&amp;gt;�ऑनलाइन रेंडर&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निदान_serve_सही_फ़ोल्डर_की_ओर_इशारा_नहीं_कर_रहा_था&amp;quot;&amp;gt;निदान : &amp;lt;code&amp;gt;serve&amp;lt;/code&amp;gt; सही फ़ोल्डर की ओर इशारा नहीं कर रहा था&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_मूल_कारण_jbake_cli_ऐसा_काम_नहीं_करता_है&amp;quot;&amp;gt;मूल कारण: JBake CLI ऐसा काम नहीं करता है&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समाधान_स्थिति_आधारित_तर्क_फ़्लैग_नहीं&amp;quot;&amp;gt;समाधान : स्थिति-आधारित तर्क, फ़्लैग नहीं&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_curl_के_साथ_त्वरित_सत्यापन&amp;quot;&amp;gt;curl के साथ त्वरित सत्यापन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_यह_बग_घातक_क्यों_था&amp;quot;&amp;gt;यह बग घातक क्यों था?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;पढ़ने का समय: 10 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;क्या आप वह क्षण जानते हैं जब आपका स्थानीय साइट कुछ भी नहीं दिखता, लेकिन एक बार ऑनलाइन तैनात करने पर सब कुछ सही हो जाता है? यही मेरे साथ मेरे Gradle JBake प्लगइन के साथ हुआ। काम`serve`वर्गाकार बटन दिखा रहा था, काली पृष्ठभूमि पर गहरा टेक्स्ट, और एक अजीब रूप से गायब CSS. फिर भी`publishSite`वह समान साइट उत्पन्न कर रहा था — और वह निर्दोष था। दोषी CSS नहीं था, न ब्राउज़र, न कैश। यह कोटलिन की एक कोड लाइन थी — और कमांड लाइन तर्कों के साथ एक बुरी आदत।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;सामग्री&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;[]&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_दृश्य_चार_स्क्रीनशॉट_दो_रेंडर&amp;quot;&amp;gt;दृश्य: चार स्क्रीनशॉट, दो रेंडर&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह सिस्टम क्रैश के बाद की बात थी। मैंने स्थानीय रेंडरिंग की तुलना करने के लिए चार स्क्रीनशॉट लिए थे (&amp;lt;code&amp;gt;./gradlew serve`पर`localhost:8820&amp;lt;/code&amp;gt;) ऑनलाइन रेंडरिंग के साथ (`publishSite`प्रत्येक पृष्ठ पर दो स्क्रीनशॉट : ऊपर और नीचे.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_rendu_local&amp;quot;&amp;gt;Rendu local&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;पृष्ठ के शीर्ष&amp;lt;/strong&amp;gt;— बटन &amp;lt;strong&amp;gt;Project&amp;lt;/strong&amp;gt; और &amp;lt;strong&amp;gt;Template&amp;lt;/strong&amp;gt; हैं&amp;lt;strong&amp;gt;छोटे, आयताकार&amp;lt;/strong&amp;gt;, मानक रंगों (नीला और हरा) में। कार्ड &amp;lt;strong&amp;gt;Start Writing&amp;lt;/strong&amp;gt; के पास एक&amp;lt;strong&amp;gt;सादा काला पृष्ठभूमि&amp;lt;/strong&amp;gt;, फ्रेम के बिना&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/screen_local1.png&amp;quot; alt=&amp;quot;Rendu local - haut de page&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;फ़ुटर&amp;lt;/strong&amp;gt;— उपशीर्षक &amp;lt;strong&amp;gt;&amp;quot;नवीनतम लेख और संसाधन&amp;quot;&amp;lt;/strong&amp;gt; है&amp;lt;strong&amp;gt;लगभग अपठनीय&amp;lt;/strong&amp;gt;, बहुत गहरा काले पृष्ठभूमि पर. ब्लॉग चित्रों के नीचे की तारीखें (&amp;quot;17 October 2013&amp;quot;, आदि) हैं&amp;lt;strong&amp;gt;अनुपस्थित&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/screen_local2.png&amp;quot; alt=&amp;quot;Rendu local - bas de page&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ऑनलाइन_रेंडर&amp;quot;&amp;gt;�ऑनलाइन रेंडर&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;पृष्ठ का शीर्ष&amp;lt;/strong&amp;gt;— उसी बटन हैं&amp;lt;strong&amp;gt;बड़े, ovaux, चमकीला निऑन हरा&amp;lt;/strong&amp;gt;, अपरकेस पाठ. कार्ड में एक&amp;lt;strong&amp;gt;गोल कोने वाला सफेद फ्रेम जिस पर ड्रॉप शैडो है&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/screen_online1.png&amp;quot; alt=&amp;quot;Rendu en ligne - haut de page&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;फ़ूटर&amp;lt;/strong&amp;gt; — Le sous-titre est &amp;lt;strong&amp;gt;स्पष्ट रूप से पढ़ने योग्य&amp;lt;/strong&amp;gt;. तारीखें हैं&amp;lt;strong&amp;gt;दृश्य&amp;lt;/strong&amp;gt;. अनुच्छेदों के कार्ड्स कुछ हैं&amp;lt;strong&amp;gt;गोल कोने&amp;lt;/strong&amp;gt;और शीर्षक हैं&amp;lt;strong&amp;gt;बोल्ड&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/screen_online2.png&amp;quot; alt=&amp;quot;Rendu en ligne - bas de page&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पहला रिफ्लेक्स: थीम। मैं डायनामिक थीम सिस्टम (हल्का, गहरा, high-contrast) आधारित उपयोग करता हूँ।&amp;lt;code&amp;gt;localStorage&amp;lt;/code&amp;gt;. शायद local store ने high-contrast थीम ट्रिगर की थी? नहीं। मैंने पहले ही लिख दिया थाhttps://cheroliv.com/blog/2025/0098_preloading_css_variable_post.html[थीम्स के प्रीलोडिंग पर एक पूरा लेख], मुझे पता है कि यह कैसे काम करता है. और साथ ही, हाई-कंट्रास्ट मोड में भी, CSS संरचना (अंडाकार बटन, छायाएँ) वहां होनी चाहिए थी. वह वहां नहीं थी.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;दूसरा प्रतिक्रिया: ब्राउज़र कैश। नहीं, मैंने स्वच्छ प्रोफ़ाइल के साथ परीक्षण किया था। अंतर बना रहा था।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;तीसरा प्रतिक्रिया :`serve`यह समान फ़ाइलों की सेवा नहीं दे रहा था`publishSite`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निदान_serve_सही_फ़ोल्डर_की_ओर_इशारा_नहीं_कर_रहा_था&amp;quot;&amp;gt;निदान : &amp;lt;code&amp;gt;serve&amp;lt;/code&amp;gt; सही फ़ोल्डर की ओर इशारा नहीं कर रहा था&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मेरा प्लगइन Gradle`bakery`दो मुख्य कार्य हैं:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;bake&amp;lt;/code&amp;gt;: स्थिर साइट में उत्पन्न करता है`build/bake/`&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;serve&amp;lt;/code&amp;gt;: एक स्थानीय वेब सर्वर शुरू करता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;publishSite&amp;lt;/code&amp;gt;: बढ़ता है`build/bake/`की ओर GitHub Pages&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;असहमति केवल वहां से आ सकती थी`serve`. Si &amp;lt;code&amp;gt;publishSite`वह सही सामग्री प्रकाशित कर रहा था, यह है कि`build/bake/`अच्छा था. अगर`serve`वह कुछ और दिखा रहा था, इसका मतलब यह था कि यह उपयोगी नहीं था`build/bake/&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;चलो कोड देखते हैं। में`SiteManager.kt`, काम`serve`इस प्रकार परिभाषित है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;SiteManager.kt — La tâche serve (version buggy)&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;tasks.register(&amp;quot;serve&amp;quot;, JavaExec::class.java) { task -&amp;amp;gt;
    task.apply {
        mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
        classpath = jbakeRuntime
        environment(&amp;quot;GEM_PATH&amp;quot;, jbakeRuntime.asPath)
        jvmArgs(/* ... */)
        args = listOf(
            &amp;quot;-b&amp;quot;, file(site.bake.srcPath).absolutePath,
            &amp;quot;-s&amp;quot;, layout.buildDirectory.get()
                .asFile.resolve(site.bake.destDirPath)
                .absolutePath
        )
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;org.jbake.launcher.Main`JBake CLI 2.7.0 का प्रवेश बिंदु है। आधार विचार: पारित करना&amp;lt;/code&amp;gt;-b`स्रोत फ़ोल्डर के लिए और`-s`लक्ष्य फ़ोल्डर के लिए, फिर सर्वर मोड शुरू करें। सिवाय इसके कि&amp;amp;#8230;&amp;amp;#8203;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_मूल_कारण_jbake_cli_ऐसा_काम_नहीं_करता_है&amp;quot;&amp;gt;मूल कारण: JBake CLI ऐसा काम नहीं करता है&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;JBake 2.7.0 कुछ का इंतजार कर रहा है&amp;lt;strong&amp;gt;स्थितिगत आर्गुमेंट&amp;lt;/strong&amp;gt;स्रोत और गंतव्य के लिए, फिर वैकल्पिक फ्लैग। हस्ताक्षर है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;jbake &amp;amp;lt;source&amp;amp;gt; &amp;amp;lt;destination&amp;amp;gt; [options]&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;लेकिन मेरे कोड में, मैं लिख रहा था:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;args = listOf(&amp;quot;-b&amp;quot;, &amp;quot;/path/to/site&amp;quot;, &amp;quot;-s&amp;quot;, &amp;quot;/path/to/build/bake&amp;quot;)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;JBake ने इसे इस तरह से समझा:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;-b&amp;lt;/code&amp;gt;→ फ़्लैग &amp;quot;bake&amp;quot; का पार्स करें (बूलियन), उपभोग किया गया&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;/path/to/site&amp;lt;/code&amp;gt;→ बन जाता है स्थितीय आर्ग्युमेंट 1 (स्रोत)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;-s&amp;lt;/code&amp;gt;→ पार्स फ़्लैग &amp;quot;serve&amp;quot; (बूलियन), सर्वर शुरू&amp;lt;strong&amp;gt;तुरंत&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;/path/to/build/bake&amp;lt;/code&amp;gt;→ बन जाता है एक अनाथ तर्क, अनदेखा या गलत तरीके से समझा गया&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;परिणाम: JBake ले रहा था`/path/to/site`comme स्रोत,&amp;lt;strong&amp;gt;गंतव्य को ध्यान में नहीं रखा&amp;lt;/strong&amp;gt;दी गई (&amp;lt;code&amp;gt;build/bake&amp;lt;/code&amp;gt;), और यह अपने डिफ़ॉल्ट निर्देशिका का उपयोग कर रहा था (सचं`./output`या एक अस्थायी प्रतिलिपि). फ़ाइल`css/styles.css`बिल्ड इसलिए ओवरराइट कर दिया गया या अनदेखा कर दिया गया, और यह एक पुराना डिफ़ॉल्ट CSS (कस्टम चर नहीं, कोने गोल नहीं, छाया नहीं) था जो परोसा जा रहा था।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;तुलना में,&amp;lt;code&amp;gt;bake&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;publishSite`वे उपयोग करते हैं&amp;lt;strong&amp;gt;आधिकारिक JBake Gradle प्लगइन&amp;lt;/strong&amp;gt;(`jbake-gradle-plugin&amp;lt;/code&amp;gt;) जो साफ़‑सुथरे ढंग से लिखता है में`build/bake/`Gradle API के माध्यम से। वे CLI के माध्यम से नहीं गुज़रते।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समाधान_स्थिति_आधारित_तर्क_फ़्लैग_नहीं&amp;quot;&amp;gt;समाधान : स्थिति-आधारित तर्क, फ़्लैग नहीं&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सुधार साधारण है — एक बार जब आप जानते हैं। स्रोत और गंतव्य को स्थिति आर्गुमेंट्स के रूप में पास करना ही पर्याप्त है, फिर`-s`अंत में:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;SiteManager.kt — La tâche serve (version corrigée)&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;args = listOf(
    file(site.bake.srcPath).absolutePath,
    layout.buildDirectory.get()
        .asFile.resolve(site.bake.destDirPath)
        .absolutePath,
    &amp;quot;-s&amp;quot;
)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह सब है। तीन पंक्तियाँ बदल दी गई हैं, बग ठीक हो गया।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;प्लगिन की स्थानीय प्रकाशन के बाद (&amp;lt;code&amp;gt;publishToMavenLocal&amp;lt;/code&amp;gt;), un `./gradlew serve`JBake को सही सिंटैक्स के साथ लॉन्च करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;jbake /home/user/project/site /home/user/project/build/bake -s&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;और इस बार, JBake में अंतर्निहित Jetty सर्वर सामग्री को अच्छी तरह से परोसता है`build/bake/`— ऑनलाइन प्रकाशित जैसा ही&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/serve-vs-publish-diagram.svg&amp;quot; alt=&amp;quot;serve vs publish diagram&amp;quot; width=&amp;quot;1747&amp;quot; height=&amp;quot;5496&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_curl_के_साथ_त्वरित_सत्यापन&amp;quot;&amp;gt;curl के साथ त्वरित सत्यापन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सुनिश्चित करने के लिए कि सर्वर सही सामग्री प्रदान कर रहा है, एक साधारण`curl`पुष्टि करता है कि`index.html`समाविष्ट है`data-bs-theme=&amp;quot;light&amp;quot;`और कि`build/bake/css/styles.css`इसे 31 402 बाइट्स का भार होता है — उत्पन्न फ़ाइल के समान`bake`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ ./gradlew serve
# Dans un autre terminal :
$ curl -s http://localhost:8820/ | grep data-bs-theme
&amp;amp;lt;html ... data-bs-theme=&amp;quot;light&amp;quot; ...&amp;amp;gt;

$ curl -I http://localhost:8820/css/styles.css
HTTP/1.1 200 OK
Content-Length: 31402
Content-Type: text/css&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;स्थानीय रेंडरिंग अब&amp;lt;strong&amp;gt;पिक्सेल-समान&amp;lt;/strong&amp;gt;डिप्लॉयड रेंडरिंग पर.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_यह_बग_घातक_क्यों_था&amp;quot;&amp;gt;यह बग घातक क्यों था?&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;क्या आप देखते हैं कि इसे पकड़ना क्यों कठिन था?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;कोई स्पष्ट त्रुटि नहीं&amp;lt;/strong&amp;gt;: JBake क्रैश नहीं हो रहा था। यह &amp;quot;कार्य कर रहा था&amp;quot;, बस एक गलत फ़ोल्डर के साथ।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;बिल्ड काम कर रहा था&amp;lt;/strong&amp;gt;:`./gradlew bake`फ़ाइलों को सही तरीके से उत्पन्न कर रहा था`build/bake/`.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;डिप्लॉयमेंट काम कर रहा था&amp;lt;/strong&amp;gt;(No output)`publishSite`अच्छी सामग्री का प्रचार ऑनलाइन कर रहा था&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;केवल &amp;lt;code&amp;gt;serve&amp;lt;/code&amp;gt; टूटा हुआ था&amp;lt;/strong&amp;gt;: विकास कार्य, जिसे हम लगातार पुनरावृत्ति के लिए उपयोग करते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;-key value` की आदत&amp;lt;/strong&amp;gt;एक डेवलपर के रूप में, हम यूनिक्स CLI के वर्षों से प्रभावित होते हैं`-o output`, `-i input`JBake CLI एक अपवाद है — स्रोत और गंतव्य स्थितिपरक हैं।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यदि आप JBake (या कोई CLI टूल) को लपेटने वाला एक Gradle प्लगइन बनाए रखते हैं,&amp;lt;strong&amp;gt;तर्कों के दस्तावेज़ पढ़ें&amp;lt;/strong&amp;gt;即使你认为你认识它们。一个隐含的假设(&amp;lt;code&amp;gt;-s&amp;lt;/code&amp;gt;= &amp;quot;set destination&amp;quot;) यह आपको दृश्य डिबगिंग में घंटे खर्च कर सकता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ, फिक्स लिटरल रूप से बदलने के लिए:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;args = listOf(&amp;quot;-b&amp;quot;, src, &amp;quot;-s&amp;quot;, dest)   // ❌ BUG&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;en :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;args = listOf(src, dest, &amp;quot;-s&amp;quot;)         // ✅ FIX&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;तीन टोकन स्थानांतरित हो गए, और मेरा स्थानीय साइट फिर से उत्पादन साइट जितना सुंदर बन गया।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;पाठ&amp;lt;/strong&amp;gt;: जब रेंडर स्थानीय और उत्पादन के बीच बिना स्पष्ट कारण के भिन्न हो, तो पहले &amp;lt;strong&amp;gt;pipeline&amp;lt;/strong&amp;gt; के बारे में संदेह करें — CSS नहीं, ब्राउज़र नहीं, और बिल्कुल भी फ्रेमवर्क नहीं। अक्सर वह चरण जो रेंडर से ठीक पहले होती है, धोखा देती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>OpenCode et le PATH incomplet : pourquoi vos outils n&#39;étaient pas dans le shell de l&#39;agent</title>
            <link >https://cheroliv.com/blog/2026/0106_opencode_path_sdkman_nvm_post.html</link>
            <pubDate>Tue, 21 Apr 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0106_opencode_path_sdkman_nvm_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_scène_un_agent_aveugle_dans_un_monde_doutils&amp;quot;&amp;gt;La scène : un agent aveugle dans un monde d&amp;amp;#8217;outils&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_anatomie_du_bug_deux_shells_deux_mondes&amp;quot;&amp;gt;Anatomie du bug : deux shells, deux mondes&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_les_coupables_zshrc_vs_zshenv&amp;quot;&amp;gt;Les coupables : .zshrc vs .zshenv&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_diagnostic_pas_à_pas&amp;quot;&amp;gt;Diagnostic pas à pas&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_1_vérifier_le_path_de_lagent&amp;quot;&amp;gt;1. Vérifier le PATH de l&amp;amp;#8217;agent&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_2_identifier_ce_qui_est_dans_zshrc_mais_pas_dans_zshenv&amp;quot;&amp;gt;2. Identifier ce qui est dans .zshrc mais pas dans .zshenv&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_3_vérifier_si_zshenv_existe&amp;quot;&amp;gt;3. Vérifier si .zshenv existe&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_solution_zshenv_les_bons_chemins&amp;quot;&amp;gt;La solution : .zshenv + les bons chemins&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_créer_zshenv_avec_tous_les_chemins_essentiels&amp;quot;&amp;gt;Créer .zshenv avec tous les chemins essentiels&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pourquoi_pas_source_sdkman_init_sh_dans_zshenv&amp;quot;&amp;gt;Pourquoi pas &amp;lt;code&amp;gt;source sdkman-init.sh&amp;lt;/code&amp;gt; dans .zshenv ?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_cas_nvm_quand_le_gestionnaire_de_versions_oublie_de_laisser_une_trace&amp;quot;&amp;gt;Le cas NVM : quand le gestionnaire de versions oublie de laisser une trace&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_le_problème_nvm&amp;quot;&amp;gt;Le problème NVM&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_la_solution_créer_le_symlink_current_pour_nvm&amp;quot;&amp;gt;La solution : créer le symlink &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt; pour NVM&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_automatiser_la_mise_à_jour_du_symlink&amp;quot;&amp;gt;Automatiser la mise à jour du symlink&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_tableau_récapitulatif_des_chemins&amp;quot;&amp;gt;Tableau récapitulatif des chemins&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pièges_et_mitigations&amp;quot;&amp;gt;Pièges et mitigations&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_leçons_apprises&amp;quot;&amp;gt;Leçons apprises&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_vérification_finale&amp;quot;&amp;gt;Vérification finale&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_liens&amp;quot;&amp;gt;Liens&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_documentation_officielle&amp;quot;&amp;gt;Documentation officielle&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_outils_mentionnés&amp;quot;&amp;gt;Outils mentionnés&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pour_aller_plus_loin&amp;quot;&amp;gt;Pour aller plus loin&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;temps de lecture : 13 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Vous lancez OpenCode dans votre terminal, tout fonctionne. L&amp;amp;#8217;agent tente un &amp;lt;code&amp;gt;gh&amp;lt;/code&amp;gt; — introuvable. Un &amp;lt;code&amp;gt;java -version&amp;lt;/code&amp;gt; — absent. Un &amp;lt;code&amp;gt;node&amp;lt;/code&amp;gt; — nulle part. Pourtant, ces outils sont bien là dans &amp;lt;em&amp;gt;votre&amp;lt;/em&amp;gt; shell. Le problème ? OpenCode lance des shells &amp;lt;strong&amp;gt;non-interactifs&amp;lt;/strong&amp;gt; qui ne lisent jamais votre &amp;lt;code&amp;gt;.zshrc&amp;lt;/code&amp;gt;. Voici comment diagnostiquer et corriger ça proprement.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;toc&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;[]&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_scène_un_agent_aveugle_dans_un_monde_doutils&amp;quot;&amp;gt;La scène : un agent aveugle dans un monde d&amp;amp;#8217;outils&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;était un mardi soir. Je venais d&amp;amp;#8217;installer &amp;lt;a href=&amp;quot;https://opencode.ai&amp;quot;&amp;gt;OpenCode&amp;lt;/a&amp;gt;, l&amp;amp;#8217;agent IA qui promettait de transformer ma façon de coder. Premier test : lui demander de lister mes dépôts GitHub.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ opencode
&amp;amp;gt; Utilise gh pour lister mes repos
❌ bash: gh: command not found&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Étrange. &amp;lt;code&amp;gt;gh&amp;lt;/code&amp;gt; fonctionnait parfaitement dans mon terminal. J&amp;amp;#8217;essaie autre chose :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;&amp;amp;gt; Vérifie la version de Java
❌ bash: java: command not found&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Puis :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;&amp;amp;gt; Lance le build Gradle
❌ bash: gradle: command not found&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Java, Gradle, Node, &amp;lt;code&amp;gt;gh&amp;lt;/code&amp;gt; — tout était invisible pour l&amp;amp;#8217;agent. Mon terminal, lui, voyait tout. Comme si l&amp;amp;#8217;agent et moi vivions dans deux mondes parallèles.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;J&amp;amp;#8217;ai mis des heures à comprendre. Des heures de &amp;lt;code&amp;gt;echo $PATH&amp;lt;/code&amp;gt;, de &amp;lt;code&amp;gt;which java&amp;lt;/code&amp;gt;, de frustration croissante. J&amp;amp;#8217;ai fini par comprendre que le problème n&amp;amp;#8217;était pas les outils — c&amp;amp;#8217;était le &amp;lt;strong&amp;gt;shell&amp;lt;/strong&amp;gt;. OpenCode, comme tout agent qui lance des sous-processus, travaille dans des shells &amp;lt;strong&amp;gt;non-interactifs&amp;lt;/strong&amp;gt;. Et Zsh, dans ces shells-là, ignore purement et simplement votre &amp;lt;code&amp;gt;.zshrc&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce qui suit est le récit complet de ce diagnostic, de la résolution, et de la leçon que j&amp;amp;#8217;ai tirée. Si vous utilisez un agent IA — OpenCode, Aider, Cursor, ou même des scripts cron — ce problème vous concernera un jour.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_anatomie_du_bug_deux_shells_deux_mondes&amp;quot;&amp;gt;Anatomie du bug : deux shells, deux mondes&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Quand vous ouvrez un terminal, Zsh le traite comme un shell &amp;lt;strong&amp;gt;interactif&amp;lt;/strong&amp;gt;. Il charge &amp;lt;code&amp;gt;.zshrc&amp;lt;/code&amp;gt;, qui initialise tout : SDKMAN, NVM, pnpm, les aliases, votre joli prompt. Votre environnement est complet.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Mais quand OpenCode exécute une commande, il ne lance pas un terminal interactif. Il lance un shell &amp;lt;strong&amp;gt;non-interactif&amp;lt;/strong&amp;gt; — un shell de tâche, sans humain derrière l&amp;amp;#8217;écran. Et Zsh, dans ce contexte, saute &amp;lt;code&amp;gt;.zshrc&amp;lt;/code&amp;gt;. Il ne lit que &amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pourquoi cette distinction existe-t-elle ? Parce qu&amp;amp;#8217;un shell non-interactif est conçu pour exécuter des scripts, pas pour servir un utilisateur humain. Charger les aliases, le prompt et les complétons dans un script qui tourne en background serait un gaspillage. Le problème, c&amp;amp;#8217;est que votre PATH — l&amp;amp;#8217;information la plus critique pour trouver les exécutables — est souvent initialisé dans &amp;lt;code&amp;gt;.zshrc&amp;lt;/code&amp;gt;, pas dans &amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/probleme-path.svg&amp;quot; alt=&amp;quot;probleme path&amp;quot; width=&amp;quot;558&amp;quot; height=&amp;quot;434&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La racine du problème : &amp;lt;strong&amp;gt;Zsh ne source &amp;lt;code&amp;gt;.zshrc&amp;lt;/code&amp;gt; que pour les shells interactifs&amp;lt;/strong&amp;gt;. OpenCode, comme tout agent IA qui lance des sous-processus, utilise des shells non-interactifs. Ces shells ne lisent que &amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_les_coupables_zshrc_vs_zshenv&amp;quot;&amp;gt;Les coupables : .zshrc vs .zshenv&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Zsh dispose de &amp;lt;strong&amp;gt;quatre fichiers d&amp;amp;#8217;initialisation&amp;lt;/strong&amp;gt;, chacun avec un rôle précis. C&amp;amp;#8217;est un design élégant — mais c&amp;amp;#8217;est aussi le nœud du problème :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 5%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Fichier&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Sourcé quand&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Rôle&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Modifie le PATH ?&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Toujours&amp;lt;/strong&amp;gt; (interactif + non-interactif + login)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Variables d&amp;amp;#8217;environnement essentielles, PATH&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅ Oui — c&amp;amp;#8217;est SA place&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;.zprofile&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Shells de login uniquement&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Commandes lentes (une fois par session)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Possible&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;.zshrc&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Shells interactifs uniquement&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Alias, prompt, complétion, outils interactifs&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;❌ Pas pour les variables critiques&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;.zlogin&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Shells de login (après .zshrc)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Messages de bienvenue, finalisation&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Rarement&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le tableau donne un indice, mais il faut le comprendre en profondeur. Pensez-y comme les pièces d&amp;amp;#8217;une maison :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt; est le &amp;lt;strong&amp;gt;hall d&amp;amp;#8217;entrée&amp;lt;/strong&amp;gt; — tout le monde passe par là, visiteur ou résident. Si vous mettez quelque chose ici, tout shell pourra le voir.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;.zshrc&amp;lt;/code&amp;gt; est le &amp;lt;strong&amp;gt;salon&amp;lt;/strong&amp;gt; — seuls les résidents (shells interactifs) y entrent. Les visiteurs (shells non-interactifs) restent dans le hall.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;.zprofile&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.zlogin&amp;lt;/code&amp;gt; sont des pièces spécialisées pour les shells de login (comme quand vous vous connectez en SSH).&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le drame, c&amp;amp;#8217;est que la plupart d&amp;amp;#8217;entre nous mettons le PATH dans le salon. Et l&amp;amp;#8217;agent IA, lui, n&amp;amp;#8217;a jamais le droit d&amp;amp;#8217;y entrer.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le problème en un diagramme :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/zsh-init-flow.svg&amp;quot; alt=&amp;quot;zsh init flow&amp;quot; width=&amp;quot;543&amp;quot; height=&amp;quot;404&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Quand vous ouvrez un terminal, Zsh est interactif : il lit &amp;lt;code&amp;gt;.zshrc&amp;lt;/code&amp;gt;, tout fonctionne. Quand OpenCode lance un shell pour exécuter une commande, Zsh est non-interactif : il saute &amp;lt;code&amp;gt;.zshrc&amp;lt;/code&amp;gt;, ne lit que &amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt;. Et si &amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt; n&amp;amp;#8217;existe pas ou ne contient pas le PATH — c&amp;amp;#8217;est le désert.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;Note&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Pourquoi Zsh fait-il ça ?&amp;lt;/strong&amp;gt; C&amp;amp;#8217;est un choix de conception hérité d&amp;amp;#8217;Unix. Un shell non-interactif doit être &amp;lt;strong&amp;gt;rapide&amp;lt;/strong&amp;gt; et &amp;lt;strong&amp;gt;reproductible&amp;lt;/strong&amp;gt;. Charger les aliases, les prompts colorés et les initialisations lourdes de SDKMAN dans un script de cron ou un agent IA serait lent et fragile. La séparation est donc logique : &amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt; pour l&amp;amp;#8217;essentiel (variables, PATH), &amp;lt;code&amp;gt;.zshrc&amp;lt;/code&amp;gt; pour le confort (aliases, prompt, complétons). Le problème survient quand on met l&amp;amp;#8217;essentiel dans le confort.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_diagnostic_pas_à_pas&amp;quot;&amp;gt;Diagnostic pas à pas&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avant de corriger, il faut comprendre exactement ce qui manque. Voici une méthode de diagnostic reproductible — gardez-la en favoris si vous travaillez avec des agents IA.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_1_vérifier_le_path_de_lagent&amp;quot;&amp;gt;1. Vérifier le PATH de l&amp;amp;#8217;agent&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;On compare ce que voit votre terminal interactif avec ce que voit un shell non-interactif — c&amp;amp;#8217;est-à-dire ce que voit OpenCode.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Dans votre terminal interactif (tout fonctionne)
echo $PATH | tr &amp;#39;:&amp;#39; &amp;#39;\n&amp;#39; | grep -v &amp;#39;^/usr&amp;#39; | sort&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Résultat typique :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;/home/cheroliv/apps
/home/cheroliv/.nvm/versions/node/v22.19.0/bin
/home/cheroliv/.sdkman/candidates/java/current/bin
/home/cheroliv/.sdkman/candidates/gradle/current/bin
/home/cheroliv/.local/share/pnpm
/home/cheroliv/.local/bin&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Maintenant, simulons ce que voit l&amp;amp;#8217;agent — un shell non-interactif :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Shell non-interactif : pas de .zshrc
zsh -c &amp;#39;echo $PATH&amp;#39; | tr &amp;#39;:&amp;#39; &amp;#39;\n&amp;#39; | grep -v &amp;#39;^/usr&amp;#39; | sort&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Résultat :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;/home/cheroliv/.local/bin&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Cinq chemins sur six ont disparu.&amp;lt;/strong&amp;gt; L&amp;amp;#8217;agent est amputé de 83% de son environnement. C&amp;amp;#8217;est comme si on vous demandait de cuisiner sans la moitié de vos ustensiles — vous pourriez faire bouillir de l&amp;amp;#8217;eau, mais pas grand-chose d&amp;amp;#8217;autre.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock warning&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-warning&amp;quot; title=&amp;quot;Warning&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La commande &amp;lt;code&amp;gt;zsh -c &amp;#39;echo $PATH&amp;#39;&amp;lt;/code&amp;gt; est votre &amp;lt;strong&amp;gt;outil de diagnostic numéro 1&amp;lt;/strong&amp;gt;. Si un outil que vous utilisez au quotidien est absent du résultat, votre agent IA ne pourra pas le voir non plus. Testez-la avant et après chaque modification de &amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_2_identifier_ce_qui_est_dans_zshrc_mais_pas_dans_zshenv&amp;quot;&amp;gt;2. Identifier ce qui est dans .zshrc mais pas dans .zshenv&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Maintenant, on cherche le coupable dans &amp;lt;code&amp;gt;.zshrc&amp;lt;/code&amp;gt;. On filtre les lignes qui mentionnent nos outils :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;grep -n &amp;#39;apps\|SDKMAN\|NVM\|PNPM\|PATH&amp;#39; ~/.zshrc&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;On retrouve typiquement :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;119: PATH=&amp;quot;/usr/bin/python3:$HOME/apps:$PATH&amp;quot;           # ← pas exporté !
171: export NVM_DIR=&amp;quot;$HOME/.nvm&amp;quot;
172: [ -s &amp;quot;$NVM_DIR/nvm.sh&amp;quot; ] &amp;amp;amp;&amp;amp;amp; \. &amp;quot;$NVM_DIR/nvm.sh&amp;quot;   # ← NVM init
176: nvm use --lts --silent                              # ← active une version
179: export PNPM_HOME=&amp;quot;/home/cheroliv/.local/share/pnpm&amp;quot;
187: export SDKMAN_DIR=&amp;quot;$HOME/.sdkman&amp;quot;
188: [[ -s &amp;quot;$HOME/.sdkman/bin/sdkman-init.sh&amp;quot; ]] &amp;amp;amp;&amp;amp;amp; source &amp;quot;$HOME/.sdkman/bin/sdkman-init.sh&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Tout ça est &amp;lt;strong&amp;gt;invisible&amp;lt;/strong&amp;gt; pour OpenCode. Et le &amp;lt;code&amp;gt;PATH&amp;lt;/code&amp;gt; de la ligne 119 n&amp;amp;#8217;est même pas &amp;lt;code&amp;gt;export`é — il ne quitte jamais le shell courant. C&amp;amp;#8217;est un détail technique crucial : une variable sans `export&amp;lt;/code&amp;gt; reste locale au shell qui la définit. Les sous-shells — comme ceux lancés par OpenCode — ne l&amp;amp;#8217;héritent jamais.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_3_vérifier_si_zshenv_existe&amp;quot;&amp;gt;3. Vérifier si .zshenv existe&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;cat ~/.zshenv 2&amp;amp;gt;/dev/null || echo &amp;quot;FICHIER ABSENT&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Si la réponse est « FICHIER ABSENT », c&amp;amp;#8217;est là que tout se joue.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_la_solution_zshenv_les_bons_chemins&amp;quot;&amp;gt;La solution : .zshenv + les bons chemins&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La stratégie est simple, mais elle demande de la précision : mettre dans &amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt; &amp;lt;strong&amp;gt;uniquement&amp;lt;/strong&amp;gt; les chemins essentiels, sans sourcer les scripts d&amp;amp;#8217;initialisation lourds. On ne déplace pas &amp;lt;code&amp;gt;.zshrc&amp;lt;/code&amp;gt; dans &amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt; — on extrait l&amp;amp;#8217;essentiel.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_créer_zshenv_avec_tous_les_chemins_essentiels&amp;quot;&amp;gt;Créer .zshenv avec tous les chemins essentiels&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt; est le &amp;lt;strong&amp;gt;seul fichier&amp;lt;/strong&amp;gt; que Zsh garantit de sourcer dans &amp;lt;strong&amp;gt;tous&amp;lt;/strong&amp;gt; les contextes. C&amp;amp;#8217;est là que doit aller le PATH.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;export SDKMAN_DIR=&amp;quot;$HOME/.sdkman&amp;quot;
export NVM_DIR=&amp;quot;$HOME/.nvm&amp;quot;
export PNPM_HOME=&amp;quot;$HOME/.local/share/pnpm&amp;quot;
export PATH=&amp;quot;$HOME/apps:$HOME/.sdkman/candidates/java/current/bin:$HOME/.sdkman/candidates/gradle/current/bin:$HOME/.nvm/current/bin:$PNPM_HOME:$HOME/.local/bin:$HOME/.local/share/JetBrains/Toolbox/scripts:/usr/bin/python3:$PATH&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;Note&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;On utilise &amp;lt;code&amp;gt;$HOME/.nvm/current/bin&amp;lt;/code&amp;gt; et non &amp;lt;code&amp;gt;$HOME/.nvm/versions/node/v22.19.0/bin&amp;lt;/code&amp;gt;. La raison : les versions Node changent. Un chemin en dur devient faux au prochain &amp;lt;code&amp;gt;nvm install&amp;lt;/code&amp;gt;. Plus de détails dans la section suivante.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_pourquoi_pas_source_sdkman_init_sh_dans_zshenv&amp;quot;&amp;gt;Pourquoi pas &amp;lt;code&amp;gt;source sdkman-init.sh&amp;lt;/code&amp;gt; dans .zshenv ?&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;L&amp;amp;#8217;approche la plus tentante serait de simplement reproduire dans &amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt; ce qu&amp;amp;#8217;on fait dans &amp;lt;code&amp;gt;.zshrc&amp;lt;/code&amp;gt; — sourcer les scripts d&amp;amp;#8217;initialisation. On &amp;lt;strong&amp;gt;pourrait&amp;lt;/strong&amp;gt; être tenté de faire :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# ❌ MAUVAISE IDÉE
[[ -s &amp;quot;$HOME/.sdkman/bin/sdkman-init.sh&amp;quot; ]] &amp;amp;amp;&amp;amp;amp; source &amp;quot;$HOME/.sdkman/bin/sdkman-init.sh&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Problèmes :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Lent&amp;lt;/strong&amp;gt; : &amp;lt;code&amp;gt;sdkman-init.sh&amp;lt;/code&amp;gt; fait des résolutions réseau et des vérifications à chaque shell. Dans un shell non-interactif, c&amp;amp;#8217;est un coût inutile.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Fragile&amp;lt;/strong&amp;gt; : SDKMAN s&amp;amp;#8217;attend à un contexte interactif. Son initialisation peut échouer silencieusement dans un pipe ou un sous-shell.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Inutile&amp;lt;/strong&amp;gt; : SDKMAN place ses candidats dans &amp;lt;code&amp;gt;~/.sdkman/candidates/&amp;amp;lt;tool&amp;amp;gt;/current/bin&amp;lt;/code&amp;gt; — des symlinks stables pointant vers la version active. On peut les utiliser &amp;lt;strong&amp;gt;directement&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;La bonne approche : contourner l&amp;amp;#8217;initialisation de SDKMAN et pointer directement sur les symlinks &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt;. C&amp;amp;#8217;est la clé de toute la solution : &amp;lt;strong&amp;gt;utiliser la structure de fichiers comme contrat, plutôt que le code d&amp;amp;#8217;initialisation&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/sdkman-approach.svg&amp;quot; alt=&amp;quot;sdkman approach&amp;quot; width=&amp;quot;338&amp;quot; height=&amp;quot;321&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_le_cas_nvm_quand_le_gestionnaire_de_versions_oublie_de_laisser_une_trace&amp;quot;&amp;gt;Le cas NVM : quand le gestionnaire de versions oublie de laisser une trace&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_le_problème_nvm&amp;quot;&amp;gt;Le problème NVM&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;C&amp;amp;#8217;est ici que l&amp;amp;#8217;enquête m&amp;amp;#8217;a mené le plus loin. SDKMAN a un design élégant : quand on fait &amp;lt;code&amp;gt;sdk install java 25.0.2-tem&amp;lt;/code&amp;gt;, il crée un symlink :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;~/.sdkman/candidates/java/current -&amp;amp;gt; ~/.sdkman/candidates/java/25.0.2-tem&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ce symlink est &amp;lt;strong&amp;gt;toujours à jour&amp;lt;/strong&amp;gt;. Pointez dessus dans &amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt; et vous êtes couvert, quel que soit le shell. Beautiful.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;NVM, lui, ne crée &amp;lt;strong&amp;gt;rien&amp;lt;/strong&amp;gt; de tel. Pas de symlink &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt;. Pas de point d&amp;amp;#8217;ancrage stable. On doit pointer sur un chemin versionné en dur, qui ressemble à ça :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;~/.nvm/versions/node/v22.19.0/bin/node&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Au prochain &amp;lt;code&amp;gt;nvm install 24&amp;lt;/code&amp;gt;, ce chemin est mort. Votre &amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt; pointera vers une version qui n&amp;amp;#8217;est plus la version active. C&amp;amp;#8217;est une bombe à retardement.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;Note&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Pourquoi NVM fait-il ça ?&amp;lt;/strong&amp;gt; NVM fonctionne en modifiant dynamiquement le PATH à chaque &amp;lt;code&amp;gt;nvm use&amp;lt;/code&amp;gt;. C&amp;amp;#8217;est conçu pour des développeurs qui changent de version souvent, dans un shell interactif. Le symlink &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt; n&amp;amp;#8217;était pas dans les spécifications initiales — c&amp;amp;#8217;est un oubli de design que nous allons corriger nous-mêmes.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/nvm-vs-sdkman.svg&amp;quot; alt=&amp;quot;nvm vs sdkman&amp;quot; width=&amp;quot;1773&amp;quot; height=&amp;quot;5676&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_la_solution_créer_le_symlink_current_pour_nvm&amp;quot;&amp;gt;La solution : créer le symlink &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt; pour NVM&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Puisque NVM ne le fait pas, on le fait nous-mêmes. Le principe est le même que SDKMAN — un symlink &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt; qui pointe toujours vers la version active. On le crée une fois, puis on l&amp;amp;#8217;automatise pour qu&amp;amp;#8217;il se mette à jour tout seul.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Créer le symlink initial
ln -sfn &amp;quot;$HOME/.nvm/versions/node/v22.19.0&amp;quot; &amp;quot;$HOME/.nvm/current&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Maintenant, dans &amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt;, on utilise :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$HOME/.nvm/current/bin&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Plutôt que :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# ❌ Chemin en dur — cassé au prochain changement de version
$HOME/.nvm/versions/node/v22.19.0/bin&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_automatiser_la_mise_à_jour_du_symlink&amp;quot;&amp;gt;Automatiser la mise à jour du symlink&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Un symlink ne vaut rien s&amp;amp;#8217;il ne se met pas à jour. Le symlink &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt; doit se mettre à jour quand on fait &amp;lt;code&amp;gt;nvm use&amp;lt;/code&amp;gt; ou &amp;lt;code&amp;gt;nvm install&amp;lt;/code&amp;gt;. La solution : un &amp;lt;strong&amp;gt;wrapper&amp;lt;/strong&amp;gt; — une fonction qui enveloppe la vraie commande &amp;lt;code&amp;gt;nvm&amp;lt;/code&amp;gt; et met à jour le symlink après chaque appel.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# À la fin de .zshrc, APRÈS le chargement de NVM
nvm use --lts --silent
ln -sfn &amp;quot;$(nvm_version_path &amp;quot;$(nvm current)&amp;quot;)&amp;quot; &amp;quot;$NVM_DIR/current&amp;quot;

_nvm() {
  command nvm &amp;quot;$@&amp;quot;
  local rc=$?
  ln -sfn &amp;quot;$(nvm_version_path &amp;quot;$(nvm current)&amp;quot;)&amp;quot; &amp;quot;$NVM_DIR/current&amp;quot;
  return $rc
}
alias nvm=&amp;#39;_nvm&amp;#39;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Comment ça marche, en détail :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/nvm-wrapper-flow.svg&amp;quot; alt=&amp;quot;nvm wrapper flow&amp;quot; width=&amp;quot;676&amp;quot; height=&amp;quot;393&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le wrapper &amp;lt;code&amp;gt;_nvm&amp;lt;/code&amp;gt; appelle la vraie commande &amp;lt;code&amp;gt;nvm&amp;lt;/code&amp;gt;, puis met à jour le symlink. L&amp;amp;#8217;alias &amp;lt;code&amp;gt;nvm=&amp;#39;_nvm&amp;#39;&amp;lt;/code&amp;gt; fait en sorte qu&amp;amp;#8217;en tapant &amp;lt;code&amp;gt;nvm&amp;lt;/code&amp;gt;, on passe par le wrapper. Et à l&amp;amp;#8217;initialisation du shell, on fait de même après &amp;lt;code&amp;gt;nvm use --lts&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock tip&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-tip&amp;quot; title=&amp;quot;Tip&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;nvm_version_path&amp;lt;/code&amp;gt; est une fonction interne de NVM qui résout le chemin complet d&amp;amp;#8217;une version. Ça évite de reconstruire le chemin manuellement.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_tableau_récapitulatif_des_chemins&amp;quot;&amp;gt;Tableau récapitulatif des chemins&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Avant de passer aux pièges, un résumé visuel de la transformation. Sur la gauche, ce que vous aviez (tout dans &amp;lt;code&amp;gt;.zshrc&amp;lt;/code&amp;gt;, invisible pour l&amp;amp;#8217;agent). Sur la droite, ce que vous avez maintenant (les chemins essentiels dans &amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt;, visibles partout).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Outil&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Avant (.zshrc seulement)&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Après (.zshenv + symlink)&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Visible par OpenCode ?&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;~/apps&amp;lt;/code&amp;gt; (gh, vscode)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;PATH non exporté dans .zshrc&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;$HOME/apps&amp;lt;/code&amp;gt; dans .zshenv&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;SDKMAN Java&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;sdkman-init.sh&amp;lt;/code&amp;gt; sourcé dans .zshrc&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;$HOME/.sdkman/candidates/java/current/bin&amp;lt;/code&amp;gt; dans .zshenv&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;SDKMAN Gradle&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;sdkman-init.sh&amp;lt;/code&amp;gt; sourcé dans .zshrc&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;$HOME/.sdkman/candidates/gradle/current/bin&amp;lt;/code&amp;gt; dans .zshenv&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;NVM Node&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;nvm use --lts&amp;lt;/code&amp;gt; dans .zshrc&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;$HOME/.nvm/current/bin&amp;lt;/code&amp;gt; dans .zshenv (symlink)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;pnpm&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;$PNPM_HOME&amp;lt;/code&amp;gt; dans .zshrc&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;$PNPM_HOME&amp;lt;/code&amp;gt; dans .zshenv&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;JetBrains Toolbox&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Auto-ajouté par Toolbox dans .zshrc&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;$HOME/.local/share/JetBrains/Toolbox/scripts&amp;lt;/code&amp;gt; dans .zshenv&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Python 3&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;/usr/bin/python3&amp;lt;/code&amp;gt; dans PATH .zshrc&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Explicitement dans .zshenv&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;✅&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_pièges_et_mitigations&amp;quot;&amp;gt;Pièges et mitigations&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Tout n&amp;amp;#8217;est pas parfait avec cette approche. Voici les problèmes que j&amp;amp;#8217;ai rencontrés, et comment les contourner.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3334%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Piège&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Mitigation&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;PATH dupliqué&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Si .zshenv et .zshrc ajoutent le même chemin, il apparaît deux fois&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt; est sourcé &amp;lt;strong&amp;gt;avant&amp;lt;/strong&amp;gt; .zshrc. Les deux sont lus dans un shell interactif. Le PATH peut doublonner. C&amp;amp;#8217;est cosmétique, pas fonctionnel. Pour l&amp;amp;#8217;éviter : ne mettre dans .zshenv que les chemins &amp;lt;em&amp;gt;absents&amp;lt;/em&amp;gt; du PATH par défaut.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;NVM : version en dur dans .zshenv&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Mettre &amp;lt;code&amp;gt;~/.nvm/versions/node/v22.19.0/bin&amp;lt;/code&amp;gt; en dur devient faux au prochain &amp;lt;code&amp;gt;nvm install&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Utiliser le symlink &amp;lt;code&amp;gt;$HOME/.nvm/current/bin&amp;lt;/code&amp;gt; + le wrapper &amp;lt;code&amp;gt;_nvm&amp;lt;/code&amp;gt; dans .zshrc&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;SDKMAN : source sdkman-init.sh dans .zshenv&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Lent, fragile, inutile dans un shell non-interactif&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Utiliser les symlinks &amp;lt;code&amp;gt;candidates/&amp;amp;lt;tool&amp;amp;gt;/current/bin&amp;lt;/code&amp;gt; directement&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Alias manquant après modification&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Le wrapper &amp;lt;code&amp;gt;nvm=&amp;#39;_nvm&amp;#39;&amp;lt;/code&amp;gt; dans .zshrc ne prend effet qu&amp;amp;#8217;après rechargement&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Relancer le shell ou &amp;lt;code&amp;gt;source ~/.zshrc&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;OpenCode ne voit pas les changements&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;L&amp;amp;#8217;agent a déjà lancé ses sous-shells avec l&amp;amp;#8217;ancien .zshenv&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Redémarrer OpenCode après modification de .zshenv&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;.zshenv trop chargé&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Mettre des fonctions lourdes ou des initialisations interactives dans .zshenv&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;.zshenv = variables d&amp;amp;#8217;environnement + PATH uniquement. Pas de &amp;lt;code&amp;gt;source&amp;lt;/code&amp;gt;, pas de fonctions lourdes, pas de prompts.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_leçons_apprises&amp;quot;&amp;gt;Leçons apprises&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;code&amp;gt;.zshrc&amp;lt;/code&amp;gt; est interactif, &amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt; est universel&amp;lt;/strong&amp;gt; — Si une variable doit exister dans &amp;lt;em&amp;gt;tous&amp;lt;/em&amp;gt; les shells (agents IA, cron, scripts, IDE), elle va dans &amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt;. Le salon est confortable, mais le hall d&amp;amp;#8217;entrée est le seul endroit où tout le monde passe.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Les gestionnaires de versions ne sont pas égaux&amp;lt;/strong&amp;gt; — SDKMAN crée des symlinks &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt; par design. NVM non. Il faut combler ce manque manuellement. C&amp;amp;#8217;est une leçon importante : avant de configurer votre PATH, vérifiez si votre gestionnaire offre un point d&amp;amp;#8217;ancrage stable.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Ne pas sourcer les init scripts dans .zshenv&amp;lt;/strong&amp;gt; — &amp;lt;code&amp;gt;sdkman-init.sh&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;nvm.sh&amp;lt;/code&amp;gt; sont conçus pour un shell interactif. Ils sont lents et fragiles dans un contexte non-interactif. Les symlinks &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt; suffisent et sont instantanés.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Toujours tester en shell non-interactif&amp;lt;/strong&amp;gt; — &amp;lt;code&amp;gt;zsh -c &amp;#39;echo $PATH&amp;#39;&amp;lt;/code&amp;gt; simule exactement ce que voit un agent. C&amp;amp;#8217;est le test de validation. Sans ce test, vous ne savez pas si votre configuration fonctionne pour les agents.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Le wrapper pattern est réutilisable&amp;lt;/strong&amp;gt; — Le même pattern &amp;lt;code&amp;gt;_nvm&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;alias nvm=&amp;#39;_nvm&amp;#39;&amp;lt;/code&amp;gt; s&amp;amp;#8217;applique à tout outil qui modifie le PATH dynamiquement sans laisser de trace stable. C&amp;amp;#8217;est un outil de plus dans votre boîte à idées.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/avant-apres.svg&amp;quot; alt=&amp;quot;avant apres&amp;quot; width=&amp;quot;238&amp;quot; height=&amp;quot;306&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_vérification_finale&amp;quot;&amp;gt;Vérification finale&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Après avoir créé &amp;lt;code&amp;gt;.zshenv&amp;lt;/code&amp;gt; et le symlink NVM, validez que tout fonctionne — dans les deux contextes :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Shell interactif (votre terminal)
gh --version &amp;amp;amp;&amp;amp;amp; java -version &amp;amp;amp;&amp;amp;amp; node --version&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Shell non-interactif (simulation OpenCode)
zsh -c &amp;#39;gh --version &amp;amp;amp;&amp;amp;amp; java -version &amp;amp;amp;&amp;amp;amp; node --version&amp;#39;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Les deux doivent réussir. Si oui, votre agent IA verra les mêmes outils que vous. Si non, revenez au diagnostic pas à pas — vous avez probablement oublié un chemin ou le symlink NVM n&amp;amp;#8217;est pas à jour.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock tip&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-tip&amp;quot; title=&amp;quot;Tip&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Automatisez ce test.&amp;lt;/strong&amp;gt; Ajoutez cette vérification dans un script de healthcheck que vous lancez après chaque mise à jour de vos outils. Un &amp;lt;code&amp;gt;zsh -c &amp;#39;which java &amp;amp;amp;&amp;amp;amp; which node &amp;amp;amp;&amp;amp;amp; which gh&amp;#39;&amp;lt;/code&amp;gt; en CI, c&amp;amp;#8217;est une assurance contre les surprises.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&amp;lt;em&amp;gt;_ Un shell non-interactif est comme un invité silencieux : il ne lit que ce qui est affiché sur la porte d&amp;amp;#8217;entrée. Si le PATH est dans le salon, il ne le verra jamais. &amp;lt;/em&amp;gt;_&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_liens&amp;quot;&amp;gt;Liens&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_documentation_officielle&amp;quot;&amp;gt;Documentation officielle&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://zsh.sourceforge.io/Doc/Release/Files.html&amp;quot;&amp;gt;Zsh documentation : Startup Files&amp;lt;/a&amp;gt; — La référence officielle sur les fichiers d&amp;amp;#8217;initialisation de Zsh. C&amp;amp;#8217;est là que tout est expliqué, même si on l&amp;amp;#8217;oublie souvent.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://opencode.ai/docs/config/&amp;quot;&amp;gt;OpenCode : configuration&amp;lt;/a&amp;gt; — Comment configurer OpenCode et son environnement d&amp;amp;#8217;exécution.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_outils_mentionnés&amp;quot;&amp;gt;Outils mentionnés&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/nvm-sh/nvm&amp;quot;&amp;gt;NVM sur GitHub&amp;lt;/a&amp;gt; — Node Version Manager. Gestionnaire de versions Node.js.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://sdkman.io&amp;quot;&amp;gt;SDKMAN — site officiel&amp;lt;/a&amp;gt; — SDKMAN! Le gestionnaire de versions pour la JVM (Java, Kotlin, Gradle&amp;amp;#8230;&amp;amp;#8203;)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://sdkman.io/install&amp;quot;&amp;gt;SDKMAN : installation&amp;lt;/a&amp;gt; — Guide d&amp;amp;#8217;installation de SDKMAN.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://cli.github.com&amp;quot;&amp;gt;&amp;lt;code&amp;gt;gh&amp;lt;/code&amp;gt; — GitHub CLI&amp;lt;/a&amp;gt; — L&amp;amp;#8217;outil en ligne de commande GitHub, indispensable pour tout développeur.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://gradle.org&amp;quot;&amp;gt;Gradle — site officiel&amp;lt;/a&amp;gt; — Le système de build que nous installons via SDKMAN.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://pnpm.io&amp;quot;&amp;gt;pnpm — site officiel&amp;lt;/a&amp;gt; — Le gestionnaire de paquets Node.js rapide et économe en espace.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://www.jetbrains.com/toolbox-app/&amp;quot;&amp;gt;JetBrains Toolbox&amp;lt;/a&amp;gt; — Le gestionnaire d&amp;amp;#8217;IDE JetBrains, qui ajoute ses scripts au PATH.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_pour_aller_plus_loin&amp;quot;&amp;gt;Pour aller plus loin&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://blog.andy2003.org/posts/2022/zsh-dotfiles/&amp;quot;&amp;gt;Zsh dotfiles : un guide complet&amp;lt;/a&amp;gt; — Article approfondi sur la gestion des dotfiles Zsh.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://wiki.archlinux.org/title/Zsh&amp;quot;&amp;gt;Zsh sur ArchWiki&amp;lt;/a&amp;gt; — L&amp;amp;#8217;une des meilleures documentations communautaires sur Zsh.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/nvm-sh/nvm/issues&amp;quot;&amp;gt;NVM issues GitHub&amp;lt;/a&amp;gt; — Pour voir les discussions autour du symlink &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt; et des problèmes de PATH.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Graphify को Gradle वर्कफ़्लो में एकीकृत करें : Knowledge Graph से PlantUML आरेख तक एक ही आदेश में</title>
            <link >https://cheroliv.com/blog/2026/0105_integrer_graphify_workflow_gradle_post.html</link>
            <pubDate>Sun, 19 Apr 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0105_integrer_graphify_workflow_gradle_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_कोड_से_हमेशा_पीछे_रहने_वाले_आरेख&amp;quot;&amp;gt;समस्या: कोड से हमेशा पीछे रहने वाले आरेख&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_हल_एक_निर्धारित_knowledge_graph_plantuml&amp;quot;&amp;gt;हल : एक निर्धारित Knowledge Graph → PlantUML&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_1_graphify_स्थापित_करें_और_knowledge_graph_निकालें&amp;quot;&amp;gt;चरण 1 : Graphify स्थापित करें और Knowledge Graph निकालें&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_स्थापना&amp;quot;&amp;gt;स्थापना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अपवर्जन_कॉन्फ़िगर_करें&amp;quot;&amp;gt;अपवर्जन कॉन्फ़िगर करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_knowledge_graph_निकालें&amp;quot;&amp;gt;Knowledge Graph निकालें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_2_gradle_प्लगिन_knowledge_graph_को_plantuml_में_परिवर्तित_करता_है&amp;quot;&amp;gt;चरण 2 : Gradle प्लगिन Knowledge Graph को PlantUML में परिवर्तित करता है&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पाइपलाइन_आर्किटेक्चर&amp;quot;&amp;gt;पाइपलाइन आर्किटेक्चर&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_आंतरिक_घटक&amp;quot;&amp;gt;आंतरिक घटक&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_रेंडरिंग_के_नियम&amp;quot;&amp;gt;रेंडरिंग के नियम&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_3_दैनिक_उपयोग&amp;quot;&amp;gt;चरण 3: दैनिक उपयोग&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पूर्ण_आरेख&amp;quot;&amp;gt;पूर्ण आरेख&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समुदाय_द्वारा_फ़िल्टर_करें&amp;quot;&amp;gt;समुदाय द्वारा फ़िल्टर करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_किनारे_के_प्रकार_द्वारा_फ़िल्टर_करें&amp;quot;&amp;gt;किनारे के प्रकार द्वारा फ़िल्टर करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_नोड_प्रकार_और_विश्वास_द्वारा_फ़िल्टर&amp;quot;&amp;gt;नोड प्रकार और विश्वास द्वारा फ़िल्टर&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_कस्टम_आउटपुट_निर्देशिका&amp;quot;&amp;gt;कस्टम आउटपुट निर्देशिका&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_référence_complète_des_propriétés&amp;quot;&amp;gt;Référence complète des propriétés&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ग्रैडल_वर्कफ़्लो_में_पूर्ण_पाइपलाइन&amp;quot;&amp;gt;ग्रैडल वर्कफ़्लो में पूर्ण पाइपलाइन&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_workflow_type&amp;quot;&amp;gt;Workflow type&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_विकास_चक्र_में_एकीकरण&amp;quot;&amp;gt;विकास चक्र में एकीकरण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_इंक्रीमेंटल_अपडेट&amp;quot;&amp;gt;इंक्रीमेंटल अपडेट&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_डॉगफ़ूडिंग_प्लगइन_स्वयं_दस्तावेज़ित_करता_है&amp;quot;&amp;gt;डॉगफ़ूडिंग : प्लगइन स्वयं दस्तावेज़ित करता है&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_यह_क्यों_निर्धारित_है_और_यह_क्यों_मायने_रखता_है&amp;quot;&amp;gt;यह क्यों निर्धारित है (और यह क्यों मायने रखता है)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_generate_the_site_jbake_b&amp;quot;&amp;gt;Bake (generate) the site jbake -b&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_and_serve_locally_jbake_b_s&amp;quot;&amp;gt;Bake and serve locally jbake -b -s&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_and_watch_for_changes_jbake_b_reset&amp;quot;&amp;gt;Bake and watch for changes jbake -b --reset&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_specify_source_and_destination_jbake_source_folder_output_folder&amp;quot;&amp;gt;Specify source and destination jbake source_folder output_folder&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_clear_the_output_directory_before_baking_jbake_b_output_reset&amp;quot;&amp;gt;Clear the output directory before baking jbake -b . output --reset &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt;&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पाइपलाइन_के_स्वयं_के_आरेख&amp;quot;&amp;gt;पाइपलाइन के स्वयं के आरेख&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परियोजना_शासन_में_एकीकरण&amp;quot;&amp;gt;परियोजना शासन में एकीकरण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_स्थापना_5_मिनट_की_चेकलिस्ट&amp;quot;&amp;gt;स्थापना: 5 मिनट की चेकलिस्ट&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_जाल_और_उपाय&amp;quot;&amp;gt;जाल और उपाय&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_जो_अंत_में_प्राप्त_होता_है&amp;quot;&amp;gt;जो अंत में प्राप्त होता है&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_लिंक&amp;quot;&amp;gt;लिंक&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;पढ़ने का समय : 12 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;आपका कोडबेस बढ़ रहा है। मॉड्यूल के बीच की निर्भरताएँ बढ़ रही हैं। आर्किटेक्चर दस्तावेज़ लिखे जाने से पहले ही पुराना हो जाता है। और यदि आपका Gradle बिल्ड &amp;lt;em&amp;gt;स्वचालित रूप से&amp;lt;/em&amp;gt; वास्तविक कोड संरचना से अप-टू-डेट डायग्राम उत्पन्न कर सके ? यह बिल्कुल वही है जो Graphify + PlantUML Gradle प्लगइन पाइपलाइन करता है :`graphify . --no-viz`Knowledge Graph का अंश,`./gradlew generateKnowledgeGraphDiagram`यह PlantUML डायग्राम में बदल देता है। शून्य LLM, शून्य मैनुअल, 100% निर्धारित।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;टोक&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;(No output)&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या_कोड_से_हमेशा_पीछे_रहने_वाले_आरेख&amp;quot;&amp;gt;समस्या: कोड से हमेशा पीछे रहने वाले आरेख&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;कु�ुछ हज़ार पंक्तियों से अधिक वाली हर परियोजना इस सिंड्रोम को जानती है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;प्रोजेक्ट के प्रारंभ में एक आर्किटेक्चर डायग्राम बनाया जाता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कोड विकसित हो रहा है, निर्भरताएँ बदल रही हैं&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आरेख एक सजावटी झूठ बन जाता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कोई इसे अपडेट नहीं करता क्योंकि यह परेशान करने वाला है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;नए आगंतुक इस पर भरोसा करते हैं और गलतियाँ करते हैं&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/probleme-diagrammes-obsoletes.svg&amp;quot; alt=&amp;quot;probleme diagrammes obsoletes&amp;quot; width=&amp;quot;824&amp;quot; height=&amp;quot;418&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;क्या चित्र होना चाहिए ?&amp;lt;/em&amp;gt; — हर कोई जानता है कि हाँ। प्रश्न यह है :&amp;lt;strong&amp;gt;कौन उन्हें अपडेट रखता है?&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जवाब: कोई नहीं. सिवाय तब जब यह स्वचालित हो।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_हल_एक_निर्धारित_knowledge_graph_plantuml&amp;quot;&amp;gt;हल : एक निर्धारित Knowledge Graph → PlantUML&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सिद्धांत सरल है : हाथ से आरेख बनाने के बजाय, हम उन्हें&amp;lt;strong&amp;gt;वास्तविक कोड संरचना से उत्पन्न&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 7) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

actor Développeur
component &amp;quot;ग्राफ़िफाई\n(pip install graphifyy)&amp;quot; as Graphify
collections &amp;quot;graphify-out/graph.json
^^^^^
 Syntax Error? (Assumed diagram type: component)

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

actor Développeur
component &amp;quot;ग्राफ़िफाई\n(pip install graphifyy)&amp;quot; as Graphify
collections &amp;quot;graphify-out/graph.json
(ज्ञान ग्राफ़)&amp;quot; as KGJSON
component &amp;quot;PlantUML Gradle प्लगइन
(generateKnowledgeGraphDiagram)&amp;quot; as Plugin
component &amp;quot;नॉलेजग्राफ़पार्सर&amp;quot; as Parser
component &amp;quot;KnowledgeGraphRenderer&amp;quot; as Renderer
component &amp;quot;PlantumlService
(सत्यापन + PNG रेंडर)&amp;quot; as PS
collections &amp;quot;आरेख/ज्ञान-ग्राफ/\n(.puml + .png)&amp;quot; as Output

Développeur --&amp;amp;gt; Graphify : graphify . --no-viz
Graphify --&amp;amp;gt; KGJSON : extrait la structure\ndu code source
Développeur --&amp;amp;gt; Plugin : ./gradlew generateKnowledgeGraphDiagram
Plugin --&amp;amp;gt; Parser : parse(graph.json)
Parser --&amp;amp;gt; Plugin : KnowledgeGraph\n(noeuds + arêtes + communautés)
Plugin --&amp;amp;gt; Renderer : render(graph, filters)
Renderer --&amp;amp;gt; Plugin : code PlantUML\ndéterministe
Plugin --&amp;amp;gt; PS : validateSyntax + generateImage
PS --&amp;amp;gt; Output : .puml + .png

note bottom of Plugin
  Pipeline DÉTERMINISTE
  Aucun appel LLM
  Résultat reproductible
end note

@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;दो कमांड। यही सब।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Étape 1 : extraire le Knowledge Graph
graphify . --no-viz

# Étape 2 : générer les diagrammes PlantUML
./gradlew generateKnowledgeGraphDiagram&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;परिणाम? फ़ाइलें`.puml` et &amp;lt;code&amp;gt;.png`में`diagrams/knowledge-graph/&amp;lt;/code&amp;gt;, Git में संस्करणित, कोड के साथ हमेशा अद्यतन.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_चरण_1_graphify_स्थापित_करें_और_knowledge_graph_निकालें&amp;quot;&amp;gt;चरण 1 : Graphify स्थापित करें और Knowledge Graph निकालें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_स्थापना&amp;quot;&amp;gt;स्थापना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Graphify एक Python उपकरण है जो आपके कोडबेस का विश्लेषण करता है और एक संरचित ज्ञान ग्राफ़ बनाता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Méthode recommandée
uv tool install graphifyy &amp;amp;amp;&amp;amp;amp; graphify install --platform opencode

# Alternative avec pip
pip install graphifyy &amp;amp;amp;&amp;amp;amp; graphify install --platform opencode&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_अपवर्जन_कॉन्फ़िगर_करें&amp;quot;&amp;gt;अपवर्जन कॉन्फ़िगर करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक फ़ाइल बनाएँ`.graphifyignore`परियोजना के मूल पर व्यापार तर्क का हिस्सा न होने वाले फ़ाइलों को बाहर रखने के लिए:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-gitignore hljs&amp;quot; data-lang=&amp;quot;gitignore&amp;quot;&amp;gt;# Secrets — JAMAIS dans le graphe
*-context.yml
*.env

# Fichiers générés
build/
.gradle/

# Tests fonctionnels
src/functionalTest/&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_knowledge_graph_निकालें&amp;quot;&amp;gt;Knowledge Graph निकालें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;graphify . --no-viz&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;झंडा`--no-viz`HTML जनरेशन को छोड़ दें (Gradle पाइपलाइन में अनावश्यक)। परिणाम एक फ़ाइल है`graphify-out/graph.json`शामिल :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;नोड&amp;lt;/strong&amp;gt;: क्लासेस, फ़ंक्शन, फ़ाइलें — उनके प्रकार और समुदाय के साथ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;किनारों&amp;lt;/strong&amp;gt;नोड्स के बीच संबंध (EXTRACTED कोड से, INFERRED LLM द्वारा)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;समुदाय&amp;lt;/strong&amp;gt;: संबंधित नोड्स के स्वचालित समूह&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Exemple de structure &amp;lt;code&amp;gt;graph.json&amp;lt;/code&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-json hljs&amp;quot; data-lang=&amp;quot;json&amp;quot;&amp;gt;{
  &amp;quot;nodes&amp;quot;: [
    {&amp;quot;id&amp;quot;: &amp;quot;0&amp;quot;, &amp;quot;label&amp;quot;: &amp;quot;LlmService&amp;quot;, &amp;quot;file_type&amp;quot;: &amp;quot;code&amp;quot;, &amp;quot;community&amp;quot;: 0},
    {&amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;label&amp;quot;: &amp;quot;ApiKeyPool&amp;quot;, &amp;quot;file_type&amp;quot;: &amp;quot;code&amp;quot;, &amp;quot;community&amp;quot;: 0},
    {&amp;quot;id&amp;quot;: &amp;quot;2&amp;quot;, &amp;quot;label&amp;quot;: &amp;quot;PlantumlService&amp;quot;, &amp;quot;file_type&amp;quot;: &amp;quot;code&amp;quot;, &amp;quot;community&amp;quot;: 1}
  ],
  &amp;quot;links&amp;quot;: [
    {&amp;quot;source&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;target&amp;quot;: &amp;quot;0&amp;quot;, &amp;quot;relation&amp;quot;: &amp;quot;uses&amp;quot;, &amp;quot;confidence&amp;quot;: &amp;quot;EXTRACTED&amp;quot;, &amp;quot;weight&amp;quot;: 0.9},
    {&amp;quot;source&amp;quot;: &amp;quot;0&amp;quot;, &amp;quot;target&amp;quot;: &amp;quot;2&amp;quot;, &amp;quot;relation&amp;quot;: &amp;quot;calls&amp;quot;, &amp;quot;confidence&amp;quot;: &amp;quot;INFERRED&amp;quot;, &amp;quot;weight&amp;quot;: 0.7}
  ]
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;Note&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;स्रोत कोड (&amp;lt;code&amp;gt;.kt&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.java`पेड़-सिटर द्वारा स्थानीय रूप से विश्लेषित किया जाता है,&amp;lt;strong&amp;gt;अपील के बिना LLM&amp;lt;/strong&amp;gt;. केवल दस्तावेज़ फ़ाइलें (&amp;lt;/code&amp;gt;.adoc`, &amp;lt;code&amp;gt;.md&amp;lt;/code&amp;gt;) को SEMANTIC EXTRACTION के लिए LLM कॉल की आवश्यकता होती है। इसलिए`--update`कोटलिन कोड पर यह लगभग तात्कालिक है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_चरण_2_gradle_प्लगिन_knowledge_graph_को_plantuml_में_परिवर्तित_करता_है&amp;quot;&amp;gt;चरण 2 : Gradle प्लगिन Knowledge Graph को PlantUML में परिवर्तित करता है&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_पाइपलाइन_आर्किटेक्चर&amp;quot;&amp;gt;पाइपलाइन आर्किटेक्चर&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;प्लगइन`com.cheroliv.plantuml`एक कार्य शामिल करता है`generateKnowledgeGraphDiagram`जो बदलता है`graph.json`PlantUML डायग्रामों में तरीके से&amp;lt;strong&amp;gt;पूरी तरह से निर्धारक&amp;lt;/strong&amp;gt;:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/architecture-pipeline-kg.svg&amp;quot; alt=&amp;quot;architecture pipeline kg&amp;quot; width=&amp;quot;1109&amp;quot; height=&amp;quot;450&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_आंतरिक_घटक&amp;quot;&amp;gt;आंतरिक घटक&amp;lt;/h3&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 50%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 50%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;घटक&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;भूमिका&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;KnowledgeGraphParser&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;पार्स`graph.json`— 3 प्रारूपों का समर्थन करता है : नैटिव graphify (&amp;lt;code&amp;gt;nodes&amp;lt;/code&amp;gt;+&amp;lt;code&amp;gt;links&amp;lt;/code&amp;gt;), legacy (&amp;lt;code&amp;gt;communities&amp;lt;/code&amp;gt;), flat. संख्यात्मक IDs को लेबल में बदलता है.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;KnowledgeGraphRenderer&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक का निर्धारित रूप से रूपांतरण करें`KnowledgeGraph`कोड में PlantUML. प्रकार के अनुसार समूह, पैकेज में समुदाय, स्वचालित कथा।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;GenerateKnowledgeGraphDiagramTask&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;ग्रेडल टास्क जो पार्स → रेंडर → वैलिडेट → PNG को ऑर्केस्ट्रेट करता है। ग्रेडल प्रॉपर्टीज़ द्वारा कॉन्फ़िगर योग्य।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;kgmodels.kt&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;डेटा मॉडल:`KnowledgeGraph`, &amp;lt;code&amp;gt;KnowledgeGraphNode&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;KnowledgeGraphEdge&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;KnowledgeGraphCommunity&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;EdgeType&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;PlantumlService&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;सिंटैक्स मान्यता + PNG रेंडरिंग (प्लगिन के सभी कार्यों द्वारा पुनः उपयोग किया जाता है).&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_रेंडरिंग_के_नियम&amp;quot;&amp;gt;रेंडरिंग के नियम&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;रेंडरर निर्धारित दृश्य सम्मेलनों को लागू करता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3334%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;किनारे का प्रकार&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;नोटेशन PlantUML&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;अर्थ&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;निकाला&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;-&amp;amp;#8594;&amp;lt;/code&amp;gt;(सॉलिड स्ट्रोक, काला)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;स्रोत कोड से निकाला गया संबंध (निश्चितता)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;अनुमानित&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;..&amp;amp;gt;&amp;lt;/code&amp;gt;(टूटा-फूटा रेखा)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;LLM द्वारा अनुमानित संबंध (विश्वास स्कोर)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;अस्पष्ट&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;--x&amp;lt;/code&amp;gt;(लाल बिंदुदार रेखा)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;अस्पष्ट संबंध (सत्यापित करने के लिए)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;समुदायों को PlantUML पैकेज के रूप में स्वचालित रंग पैलेट के साथ प्रस्तुत किया जाता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_चरण_3_दैनिक_उपयोग&amp;quot;&amp;gt;चरण 3: दैनिक उपयोग&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_पूर्ण_आरेख&amp;quot;&amp;gt;पूर्ण आरेख&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Générer le diagramme du Knowledge Graph complet
./gradlew generateKnowledgeGraphDiagram&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आउटपुट :`diagrams/knowledge-graph/knowledge-graph-full.puml`(output empty string as no French text was provided for translation)&amp;lt;code&amp;gt;.png&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_समुदाय_द्वारा_फ़िल्टर_करें&amp;quot;&amp;gt;समुदाय द्वारा फ़िल्टर करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Une seule communauté
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.community=community_0

# Limiter le nombre de noeuds (lisibilité)
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.community=community_0 \
  -Pplantuml.kg.maxNodes=15&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_किनारे_के_प्रकार_द्वारा_फ़िल्टर_करें&amp;quot;&amp;gt;किनारे के प्रकार द्वारा फ़िल्टर करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Uniquement les relations certaines (EXTRACTED)
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.edgeTypes=EXTRACTED

# Relations certaines + inférées
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.edgeTypes=EXTRACTED,INFERRED&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_नोड_प्रकार_और_विश्वास_द्वारा_फ़िल्टर&amp;quot;&amp;gt;नोड प्रकार और विश्वास द्वारा फ़िल्टर&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Uniquement les classes de code
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.nodeTypes=code

# Seuil de confiance minimum (pour les INFERRED)
./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.minConfidence=0.7&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_कस्टम_आउटपुट_निर्देशिका&amp;quot;&amp;gt;कस्टम आउटपुट निर्देशिका&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;./gradlew generateKnowledgeGraphDiagram \
  -Pplantuml.kg.outputDir=docs/architecture&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_référence_complète_des_propriétés&amp;quot;&amp;gt;Référence complète des propriétés&amp;lt;/h3&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3334%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;संपत्ति&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;दोष&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;विवरण&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;plantuml.kg.community&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;em&amp;gt;(सभी)&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;नाम द्वारा समुदाय फ़िल्टर करें (उप-स्ट्रिंग मिलान)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;plantuml.kg.edgeTypes&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;(सभी)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;कॉमा द्वारा पृथक किनारा प्रकार:`EXTRACTED`, &amp;lt;code&amp;gt;INFERRED&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;AMBIGUOUS&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;plantuml.kg.minConfidence&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;0.0&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;किनारों के लिए विश्वास की न्यूनतम सीमा&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;plantuml.kg.maxNodes&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;em&amp;gt;(असीमित)&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;प्रदर्शित करने के लिए अधिकतम नोड्स की संख्या&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;plantuml.kg.nodeTypes&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;em&amp;gt;(सभी)&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;विराम चिह्नों द्वारा अलग किए गए नोड प्रकार (उदाहरण`class`, &amp;lt;code&amp;gt;code&amp;lt;/code&amp;gt;)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;plantuml.kg.outputDir&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;diagrams/knowledge-graph&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;फ़ाइलों के लिए आउटपुट निर्देशिका`.puml` et &amp;lt;code&amp;gt;.png&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_ग्रैडल_वर्कफ़्लो_में_पूर्ण_पाइपलाइन&amp;quot;&amp;gt;ग्रैडल वर्कफ़्लो में पूर्ण पाइपलाइन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_workflow_type&amp;quot;&amp;gt;Workflow type&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/workflow-complet.svg&amp;quot; alt=&amp;quot;workflow complet&amp;quot; width=&amp;quot;618&amp;quot; height=&amp;quot;714&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_विकास_चक्र_में_एकीकरण&amp;quot;&amp;gt;विकास चक्र में एकीकरण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पाइपलाइन विकास के प्रमुख चरणों में सहजता से एकीकृत होती है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 5) ]

@startuml
skinparam backgroundColor #FEFEFE

state &amp;quot;विकास&amp;quot; as dev
state &amp;quot;निष्कर्षण
^^^^^
 Syntax Error? (Assumed diagram type: state)

@startuml
skinparam backgroundColor #FEFEFE

state &amp;quot;विकास&amp;quot; as dev
state &amp;quot;निष्कर्षण
graphify . --no-viz&amp;quot; as extract
state &amp;quot;पीढ़ी
./gradlew generateKnowledgeGraphDiagram&amp;quot; as generate
state &amp;quot;Commit
वर्ज़न किए गए आरेख&amp;quot; as commit

[*] --&amp;amp;gt; dev
dev --&amp;amp;gt; extract : Code modifié
extract --&amp;amp;gt; generate : graph.json à jour
generate --&amp;amp;gt; commit : .puml + .png générés
commit --&amp;amp;gt; dev : Diagrammes dans le repo

note right of extract
  Quasi instantané sur du code Kotlin
  (tree-sitter, pas de LLM)
end note

note right of generate
  Déterministe
  Pas de LLM
  Résultat reproductible
end note

@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_इंक्रीमेंटल_अपडेट&amp;quot;&amp;gt;इंक्रीमेंटल अपडेट&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जब कोड बदलता है, हम शून्य से पूरे ग्राफ को फिर से नहीं बनाते :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Mise à jour incrémentale (fichiers modifiés uniquement)
graphify . --update

# Puis régénérer les diagrammes
./gradlew generateKnowledgeGraphDiagram&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;Note&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;--update`यह केवल संशोधित फ़ाइलों को फिर से निकालता है (SHA256 द्वारा पता लगाए गए में`graphify-out/cache/&amp;lt;/code&amp;gt;). Kotlin कोड पर, यह लगभग तात्कालिक है क्योंकि tree-sitter स्थानीय रूप से काम करता है, कोई LLM कॉल नहीं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_डॉगफ़ूडिंग_प्लगइन_स्वयं_दस्तावेज़ित_करता_है&amp;quot;&amp;gt;डॉगफ़ूडिंग : प्लगइन स्वयं दस्तावेज़ित करता है&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;PlantUML प्लगइन प्रॉम्प्ट को डायग्राम में बदलने के लिए मौजूद है। यह अपने &amp;lt;em&amp;gt;propre&amp;lt;/em&amp;gt; कोडबेस के Knowledge Graph को भी दस्तावेज़ीकरण डायग्राम में बदल सकता है। यह &amp;lt;em&amp;gt;dogfooding&amp;lt;/em&amp;gt; है: प्लगइन अपनी ही सेवा का उपभोग करता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 6) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package &amp;quot;सामान्य पाइपलाइन
(उपयोगकर्ता → आरेख)&amp;quot; as normal {
^^^^^
 Syntax Error? (Assumed diagram type: activity)

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package &amp;quot;सामान्य पाइपलाइन
(उपयोगकर्ता → आरेख)&amp;quot; as normal {
    [Fichier .prompt] as prompt
    [LlmService\n+ ApiKeyPool] as llm1
    [ProcessPlantumlPromptsTask] as task1
    [Diagramme PNG] as out1

    prompt --&amp;amp;gt; task1
    task1 --&amp;amp;gt; llm1
    llm1 --&amp;amp;gt; out1
}

package &amp;quot;पाइपलाइन ज्ञान ग्राफ
(निर्धारित, LLM नहीं)&amp;quot; as kg {
    [graphify-out/graph.json] as kgjson
    [KnowledgeGraphParser] as parser
    [KnowledgeGraphRenderer] as renderer
    [PlantumlService] as ps
    [Diagramme PNG\n(documentation du plugin)] as out2

    kgjson --&amp;amp;gt; parser
    parser --&amp;amp;gt; renderer
    renderer --&amp;amp;gt; ps
    ps --&amp;amp;gt; out2
}

package &amp;quot;पाइपलाइन डॉगफूडिंग
(LLM → प्लगइन की दस्तावेज़ीकरण)&amp;quot; as dogfood {
    [GraphifyPromptAdapter] as gpa
    [Fichiers .prompt\nauto-générés] as auto_prompt
    [LlmService\n+ ApiKeyPool] as llm2
    [ProcessPlantumlPromptsTask] as task2
    [Diagramme PNG\n(documentation LLM)] as out3

    kgjson --&amp;amp;gt; gpa
    gpa --&amp;amp;gt; auto_prompt
    auto_prompt --&amp;amp;gt; task2
    task2 --&amp;amp;gt; llm2
    llm2 --&amp;amp;gt; out3
}

note &amp;quot;एक ही LlmService, एक ही ApiKeyPool,
एक ही PlantumlService
— शून्य डुप्लीकेशन&amp;quot; as N

@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सम्बद्ध Gradle कार्य :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3334%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;कार्य&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;LLM ?&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;generateKnowledgeGraphDiagram&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;नहीं&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;बदलो`graph.json`PlantUML (निर्धारित) में&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;generateDiagramDocs&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;हाँ&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;कुछ उत्पन्न करें`.prompt`ग्राफ़ से, इसे LLM के माध्यम से संसाधित करता है (dogfooding)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Documentation déterministe (rapide, pas de LLM)
./gradlew generateKnowledgeGraphDiagram

# Documentation LLM (plus riche, consomme des tokens)
./gradlew generateDiagramDocs&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_यह_क्यों_निर्धारित_है_और_यह_क्यों_मायने_रखता_है&amp;quot;&amp;gt;यह क्यों निर्धारित है (और यह क्यों मायने रखता है)&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पाइपलाइन का मुख्य बिंदु`generateKnowledgeGraphDiagram`:&amp;lt;strong&amp;gt;वह किसी भी LLM को नहीं बुलाता&amp;lt;/strong&amp;gt;. परिवर्तन`graph.json`&amp;lt;mark&amp;gt;#&amp;lt;/mark&amp;gt; JBake CLI Commands &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; # Initialize a new JBake project jbake -i&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;h1 id=&amp;quot;_bake_generate_the_site_jbake_b&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake (generate) the site jbake -b&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_and_serve_locally_jbake_b_s&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake and serve locally jbake -b -s&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_and_watch_for_changes_jbake_b_reset&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake and watch for changes jbake -b --reset&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_specify_source_and_destination_jbake_source_folder_output_folder&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Specify source and destination jbake source_folder output_folder&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_clear_the_output_directory_before_baking_jbake_b_output_reset&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Clear the output directory before baking jbake -b . output --reset &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt;&amp;lt;/h1&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;PlantUML एक शुद्ध फ़ंक्शन है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 16) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

rectangle &amp;quot;पाइपलाइन निर्धारित\n(generateKnowledgeGraphDiagram)&amp;quot; as det {
    [graph.json] as json
    [KnowledgeGraphParser] as parser
    [KnowledgeGraphRenderer] as renderer
    [PlantUML code] as puml

    json --&amp;amp;gt; parser : parse
    parser --&amp;amp;gt; renderer : KnowledgeGraph
    renderer --&amp;amp;gt; puml : render (fonction pure)
}

rectangle &amp;quot;Pipeline LLM
^^^^^
 Syntax Error? (Assumed diagram type: component)

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

rectangle &amp;quot;पाइपलाइन निर्धारित\n(generateKnowledgeGraphDiagram)&amp;quot; as det {
    [graph.json] as json
    [KnowledgeGraphParser] as parser
    [KnowledgeGraphRenderer] as renderer
    [PlantUML code] as puml

    json --&amp;amp;gt; parser : parse
    parser --&amp;amp;gt; renderer : KnowledgeGraph
    renderer --&amp;amp;gt; puml : render (fonction pure)
}

rectangle &amp;quot;Pipeline LLM
(processPlantumlPrompts)&amp;quot; as llm {
    [.prompt] as prompt
    [LlmService] as llmSvc
    [ChatModel] as model
    [PlantUML code] as puml2

    prompt --&amp;amp;gt; llmSvc
    llmSvc --&amp;amp;gt; model : API call
    model --&amp;amp;gt; puml2 : réponse non-déterministe
}

note bottom of det
  Même entrée → même sortie
  Pas de latence réseau
  Pas de coût en tokens
  Reproductible en CI
end note

note bottom of llm
  Même entrée → sortie variable
  Latence réseau (1-5s)
  Coût en tokens
  Nécessite une clave API
end note

@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;वास्तविक लाभ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 50%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 50%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;लाभ&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;प्रभाव&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;पुनरावृत्ति योग्यता&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;भी`graph.json`→ एक ही आरेख. सटीक रूप से. हर बार.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;शून्य लागत&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;कोई LLM कॉल नहीं = कोई टोकन नहीं = कोई API बिल नहीं&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;शून्य विलंब&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Parse + render ~100ms लेता है, 1-5 सेकंड नहीं&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;संगत CI&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;कोई API कुंजी आवश्यक नहीं है। कोई अस्थिर परीक्षण नहीं है जो परिवर्तनशील LLM प्रतिक्रिया के कारण हो।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;संस्करणीय&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Le &amp;lt;code&amp;gt;.puml`जेनरेट किया गया पाठ है। हम इसे कर सकते हैं।`diff&amp;lt;/code&amp;gt;, PR में समीक्षक, Git में वर्ज़न करें।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_पाइपलाइन_के_स्वयं_के_आरेख&amp;quot;&amp;gt;पाइपलाइन के स्वयं के आरेख&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पाइपलाइन को पूरा करने के लिए, यहाँ प्लगइन द्वारा उत्पन्न किया जाने वाला पाइपलाइन का आरेख दिया गया है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/pipeline-sequence.svg&amp;quot; alt=&amp;quot;pipeline sequence&amp;quot; width=&amp;quot;1634&amp;quot; height=&amp;quot;554&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परियोजना_शासन_में_एकीकरण&amp;quot;&amp;gt;परियोजना शासन में एकीकरण&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारे प्रोजेक्ट में, यह पाइपलाइन AI एजेंट के लिए EAGER/LAZY संदर्भ प्रबंधन रणनीति में एकीकृत है। Knowledge Graph मानव-निर्मित आर्किटेक्चर दस्तावेज़ीकरण को एक संरचित, क्वेरी योग्य और स्वचालित रूप से अपडेट किए जाने वाले ग्राफ़ से बदलता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 11) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package &amp;quot;EAGER\n(हमेशा चार्ज)&amp;quot; as eager {
    [PROMPT_REPRISE.adoc\n(contexte session)] as pr
    [INDEX.adoc\n(vue d&amp;#39;ensemble)] as idx
    [GRAPH_REPORT.adoc\n(~50 lignes)] as gr
}

package &amp;quot;LAZY — रणनीति
^^^^^
 Syntax Error? (Assumed diagram type: component)

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package &amp;quot;EAGER\n(हमेशा चार्ज)&amp;quot; as eager {
    [PROMPT_REPRISE.adoc\n(contexte session)] as pr
    [INDEX.adoc\n(vue d&amp;#39;ensemble)] as idx
    [GRAPH_REPORT.adoc\n(~50 lignes)] as gr
}

package &amp;quot;LAZY — रणनीति
(अनुरोध पर)&amp;quot; as lazy_strat {
    [Méthodologies] as meth
    [Archives sessions] as sessions
}

package &amp;quot;LAZY — Graphify
(लक्षित प्रश्न)&amp;quot; as lazy_graph {
    [graph.json] as gj
    [Queries\n(query/path/explain)] as queries
}

package &amp;quot;Pipeline PlantUML
(स्वचालित रूप से उत्पन्न)&amp;quot; as puml {
    [generateKnowledgeGraphDiagram] as kgTask
    [generateDiagramDocs] as ddTask
    [Diagrammes PNG] as diagrams
}

Agent --&amp;amp;gt; eager : Lit en début de session
Agent ..&amp;amp;gt; lazy_strat : Charge si type détecté
Agent ..&amp;amp;gt; lazy_graph : Query si besoin structurel
kgTask --&amp;amp;gt; diagrams : Déterministe
ddTask --&amp;amp;gt; diagrams : Via LLM

note right of gr
  Condensé du Knowledge Graph
  God nodes + communautés
  Remplace ECOSYSTEM_OVERVIEW
  (225 lignes → 50 lignes)
end note

@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;दो प्रणालियों का विवाह पूरक है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;रणनीति कब और कैसे का प्रबंधन करती है&amp;lt;/strong&amp;gt;— शासन, वर्कफ़्लो, संग्रह&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Graphify QUOI और OÙ का प्रबंधन करता है&amp;lt;/strong&amp;gt;— कोड संरचना, संबंध, लक्षित प्रश्न&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;(No output) सत्र रणनीति प्रबंधन करती है&amp;lt;strong&amp;gt;जब&amp;lt;/strong&amp;gt; et le &amp;lt;strong&amp;gt;कैसे&amp;lt;/strong&amp;gt;(शासन, वर्कफ़्लो, सीमाएं), Graphify इसे प्रबंधित करता है&amp;lt;strong&amp;gt;क्या&amp;lt;/strong&amp;gt; et le &amp;lt;strong&amp;gt;कहाँ&amp;lt;/strong&amp;gt;(कोड संरचना, संबंध, लक्षित क्वेरीज़)। PlantUML पाइपलाइन इसे प्रबंधित करता है&amp;lt;strong&amp;gt;किससे&amp;lt;/strong&amp;gt;(निर्धारित आरेख, संस्करणित, हमेशा अद्यतन). (No output)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_स्थापना_5_मिनट_की_चेकलिस्ट&amp;quot;&amp;gt;स्थापना: 5 मिनट की चेकलिस्ट&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3334%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;(no output)&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;चरण&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;आदेश&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;1&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;इंस्टॉल Graphify&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;uv tool install graphifyy&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;2&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;अपवर्जन को कॉन्फ़िगर करें&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;बनाना`.graphifyignore`&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;3&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;नॉलेज ग्राफ़ निकालें&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;graphify . --no-viz&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;4&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;आरेख तैयार करें&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;./gradlew generateKnowledgeGraphDiagram&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;5&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;परिणामों को कमिट करें&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;git add diagrams/knowledge-graph/&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Script complet en 5 commandes
uv tool install graphifyy
cat &amp;amp;gt; .graphifyignore &amp;amp;lt;&amp;amp;lt; &amp;#39;EOF&amp;#39;
*-context.yml
*.env
build/
.gradle/
EOF
graphify . --no-viz
./gradlew generateKnowledgeGraphDiagram
git add graphify-out/GRAPH_REPORT.adoc graphify-out/graph.json diagrams/knowledge-graph/&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_जाल_और_उपाय&amp;quot;&amp;gt;जाल और उपाय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3334%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;जाल&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;शमन&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;बहुत घना ग्राफ़&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक बड़े प्रोजेक्ट से सैकड़ों अपठनीय नोड्स उत्पन्न होते हैं&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;उपयोग करना`-Pplantuml.kg.maxNodes=30`और समुदाय द्वारा फ़िल्टर करें&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;बहुत व्यापक बहिष्करण&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;बहुत सी फ़ाइलें में`.graphifyignore`यह ग्राफ़ के मान को कम करता है&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;सिर्फ credentials और build को छोड़कर शुरू करें&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;तीरों की दिशा&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;अनुमानित किनारे INFERRED की दिशा अस्पष्ट होसकती है&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;फ़िल्टर द्वारा`-Pplantuml.kg.edgeTypes=EXTRACTED`केवल कुछ संबंधों के लिए&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;अप्रचलित ग्राफ़&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;कोड बदलता है लेकिन ग्राफ़ पुनर्निर्मित नहीं होता&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;उपयोग करना`graphify . --update`नियमित रूप से या गिट हुक`graphify hook install`&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;अपडेटेड लागत&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;चरणबद्ध अपडेट लगभग मुफ्त हैं (स्थानीय ट्री‑सिटर)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;केवल दस्तावेज़ (&amp;lt;code&amp;gt;.adoc&amp;lt;/code&amp;gt;) LLM टोकन खपत करते हैं&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_जो_अंत_में_प्राप्त_होता_है&amp;quot;&amp;gt;जो अंत में प्राप्त होता है&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 6) ]

@startuml
skinparam backgroundColor #FEFEFE

rectangle &amp;quot;पहले&amp;quot; as avant {
    card &amp;quot;हाथ से खींचे गए आरेख
हमेशा अप्रचलित
^^^^^
 Syntax Error? (Assumed diagram type: activity)

@startuml
skinparam backgroundColor #FEFEFE

rectangle &amp;quot;पहले&amp;quot; as avant {
    card &amp;quot;हाथ से खींचे गए आरेख
हमेशा अप्रचलित
कोई उन्हें अपडेट नहीं करता&amp;quot; as av1 #FDEDEC
}

rectangle &amp;quot;के बाद&amp;quot; as apres {
    card &amp;quot;स्वचालित रूप से बनाए गए आरेख
हमेशा कोड के साथ अप-टू-डेट
Git में संस्करणबद्ध
निर्धारित और पुन:उत्पादन योग्य&amp;quot; as ap1 #E8F8E8
}

avant --&amp;amp;gt; apres : graphify . --no-viz\n+ ./gradlew generateKnowledgeGraphDiagram

@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;वास्तविक लाभ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 50%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 50%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;लाभ&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;विवरण&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;दस्तावेज़ हमेशा अद्यतन&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;डायग्राम वर्तमान कोड को दर्शाते हैं, कोई मैनुअल स्नैपशॉट नहीं&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;शून्य रखरखाव का प्रयास&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;आरेख प्रत्येक बिल्ड के साथ पुनः उत्पन्न होते हैं&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;तकनीकी ऋण में कमी&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;अब आरेख को हाथ से रखरखाव करने की ज़रूरत नहीं है&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;दृश्य संदर्भ नए के लिए&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक नया डेवलपर आरेख देखकर आर्किटेक्चर समझता है&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;संभावित सूक्ष्म समायोजन&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;जोड़ियाँ (सब-ग्राफ़ → आरेख) IA प्रशिक्षण के उदाहरण हैं&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;स्वचालित सत्यापन&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;`PlantumlService.validateSyntax()`प्रत्येक उत्पन्न आरेख की जाँच करता है&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;तेज़ ऑनबोर्डिंग&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;5 आरेख = आर्किटेक्चर का पूर्ण दृश्य&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;(No output) जिसके पास एक &amp;lt;em&amp;gt;kyon&amp;lt;/em&amp;gt; है वह सभी &amp;lt;em&amp;gt;kaise&amp;lt;/em&amp;gt; को सह सकता है। [No output]&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;क्यों&amp;lt;/em&amp;gt; : हमेशा अद्यतन चित्र। &amp;lt;em&amp;gt;कैसे&amp;lt;/em&amp;gt; : एक Gradle पाइपलाइन में दो कमांड।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_लिंक&amp;quot;&amp;gt;लिंक&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/nicholasgasior/graphify&amp;quot;&amp;gt;GitHub पर Graphify&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/cheroliv/plantuml-gradle&amp;quot;&amp;gt;PlantUML Gradle प्लगइन&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;/blog/2026/0104_fg_command_super_tips_post.html&amp;quot;&amp;gt;fg कमांड के सुपर टिप्स&amp;lt;/a&amp;gt;— पिछला आलेख टर्मिनल वर्कफ़्लो पर&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>फ़ग कमांड के सुपर टिप्स: जब Ctrl+Z आपके टर्मिनल सत्र को बचाता है</title>
            <link >https://cheroliv.com/blog/2026/0104_fg_command_super_tips_post.html</link>
            <pubDate>Sat, 18 Apr 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0104_fg_command_super_tips_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_एक_व्यस्त_टर्मिनल&amp;quot;&amp;gt;समस्या : एक व्यस्त टर्मिनल&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_तीन_अनिवार्य_आदेश&amp;quot;&amp;gt;तीन अनिवार्य आदेश&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ctrlz_रोकें_sigtstp&amp;quot;&amp;gt;Ctrl+Z — रोकें (SIGTSTP)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_fg_अग्रभूमि_में_लाएँ&amp;quot;&amp;gt;fg — अग्रभूमि में लाएँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bg_पृष्ठभूमि_में_जारी_रखना&amp;quot;&amp;gt;bg — पृष्ठभूमि में जारी रखना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_jobs_शेल_के_कार्यों_को_सूचीबद्ध_करना&amp;quot;&amp;gt;jobs — शेल के कार्यों को सूचीबद्ध करना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिदृश्य_1_लंबा_बिल्ड&amp;quot;&amp;gt;परिदृश्य 1 : लंबा बिल्ड&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_दर_चरण&amp;quot;&amp;gt;चरण-दर-चरण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_स्केनेरियो_2_भुला_हुआ_संपादक&amp;quot;&amp;gt;स्केनेरियो 2: भुला हुआ संपादक&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिदृश्य_3_opencode_प्रक्रिया_निलंबित&amp;quot;&amp;gt;परिदृश्य 3: opencode प्रक्रिया निलंबित&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिदृश्य_4_कई_जॉब्स_को_एक_साथ_प्रबंधित_करें&amp;quot;&amp;gt;परिदृश्य 4: कई जॉब्स को एक साथ प्रबंधित करें&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_कार्यों_के_आदेशों_का_सारांश&amp;quot;&amp;gt;कार्यों के आदेशों का सारांश&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_fg_bg_ctrlz_ctrlc_और_के_अंतर&amp;quot;&amp;gt;fg, bg, Ctrl+Z, Ctrl+C और &amp;amp;amp; के अंतर&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_generate_the_site_jbake_b&amp;quot;&amp;gt;Bake (generate) the site jbake -b&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_and_serve_locally_jbake_b_s&amp;quot;&amp;gt;Bake and serve locally jbake -b -s&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_and_watch_for_changes_jbake_b_reset&amp;quot;&amp;gt;Bake and watch for changes jbake -b --reset&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_specify_source_and_destination_jbake_source_folder_output_folder&amp;quot;&amp;gt;Specify source and destination jbake source_folder output_folder&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_clear_the_output_directory_before_baking_jbake_b_output_resetगैर_विध्वंसक_jbake_cli_commands_initialize_a_new_jbake_project_jbake_i&amp;quot;&amp;gt;Clear the output directory before baking jbake -b . output --reset&amp;lt;strong&amp;gt;गैर-विध्वंसक&amp;lt;/strong&amp;gt;&amp;lt;mark&amp;gt;#&amp;lt;/mark&amp;gt; JBake CLI Commands &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; # Initialize a new JBake project jbake -i&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_generate_the_site_jbake_b_2&amp;quot;&amp;gt;Bake (generate) the site jbake -b&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_and_serve_locally_jbake_b_s_2&amp;quot;&amp;gt;Bake and serve locally jbake -b -s&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_and_watch_for_changes_jbake_b_reset_2&amp;quot;&amp;gt;Bake and watch for changes jbake -b --reset&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_specify_source_and_destination_jbake_source_folder_output_folder_2&amp;quot;&amp;gt;Specify source and destination jbake source_folder output_folder&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_clear_the_output_directory_before_baking_jbake_b_output_reset&amp;quot;&amp;gt;Clear the output directory before baking jbake -b . output --reset &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt;&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_एक_जॉब_का_पूरा_जीवन_चक्र&amp;quot;&amp;gt;एक जॉब का पूरा जीवन चक्र&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_उन्नत_टिप्स&amp;quot;&amp;gt;उन्नत टिप्स&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_fg_नौकरी_के_साथ_सबसे_नया_और_अल्टरनेन्स&amp;quot;&amp;gt;fg नौकरी के साथ सबसे नया और अल्टरनेन्स&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_काम_को_सही_तरीके_से_पूरा_करना&amp;quot;&amp;gt;काम को सही तरीके से पूरा करना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_désown_शेल_से_अलग_करें&amp;quot;&amp;gt;désown : शेल से अलग करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_nohup_के_साथ_मिलाएँ_लंबी_प्रक्रियाओं_के_लिए&amp;quot;&amp;gt;nohup के साथ मिलाएँ लंबी प्रक्रियाओं के लिए&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_जाल_और_सामान्य_त्रुटियाँ&amp;quot;&amp;gt;जाल और सामान्य त्रुटियाँ&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ctrlz_और_ctrlc_को_भ्रमित_करना&amp;quot;&amp;gt;Ctrl+Z और Ctrl+C को भ्रमित करना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_जॉब्स_शेल_के_लिए_स्थानीय_होते_हैं&amp;quot;&amp;gt;जॉब्स शेल के लिए स्थानीय होते हैं&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_जॉब्स_शेल_बंद_होने_पर_जीवित_नहीं_रहते&amp;quot;&amp;gt;जॉब्स शेल बंद होने पर जीवित नहीं रहते।&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_इंटरएक्टिव_प्रक्रियाएँ_और_fg&amp;quot;&amp;gt;इंटरएक्टिव प्रक्रियाएँ और fg&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सारांश_आरेख&amp;quot;&amp;gt;सारांश आरेख&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_fg_क्यों_कम_आंका_गया&amp;quot;&amp;gt;fg क्यों कम आंका गया&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_generate_the_site_jbake_b_3&amp;quot;&amp;gt;Bake (generate) the site jbake -b&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_and_serve_locally_jbake_b_s_3&amp;quot;&amp;gt;Bake and serve locally jbake -b -s&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_and_watch_for_changes_jbake_b_reset_3&amp;quot;&amp;gt;Bake and watch for changes jbake -b --reset&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_specify_source_and_destination_jbake_source_folder_output_folder_3&amp;quot;&amp;gt;Specify source and destination jbake source_folder output_folder&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_clear_the_output_directory_before_baking_jbake_b_output_reset_है&amp;quot;&amp;gt;Clear the output directory before baking jbake -b . output --reset &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; है :&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_तकनीकी_ज्ञापन_संकेत&amp;quot;&amp;gt;तकनीकी ज्ञापन : संकेत&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संदर्भ&amp;quot;&amp;gt;संदर्भ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;पढ़ने का समय : 10 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;आप फेंकते हैं`./gradlew build`, टर्मिनल 3 मिनट के लिए ब्लॉक किया गया है, और आपको कुछ और करने की आवश्यकता है &amp;lt;em&amp;gt;en attendant&amp;lt;/em&amp;gt; ? नए टैब खोलने की आवश्यकता नहीं है.`Ctrl+Z`प्रक्रिया को सस्पेंड करें`fg`इसे बिल्कुल वहीं लाया जाता है जहाँ आपने उसे छोड़ा था। यह डेवलपर के दैनिक जीवन का सबसे कम आंका जाने वाला यूनिक्स टिप है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;सामग्री की तालिका&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;[]&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या_एक_व्यस्त_टर्मिनल&amp;quot;&amp;gt;समस्या : एक व्यस्त टर्मिनल&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हर डेवलपर ने इस स्थिति को अनुभव किया है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ ./gradlew build
&amp;amp;gt; Building...&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;और आपको एक फ़ाइल देखनी है, एक लॉन्च करना है`git status`, या एक व्यस्त पोर्ट की जांच करें।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 6) ]

@startuml
skinparam backgroundColor #FEFEFE

actor Développeur as dev
participant &amp;quot;टर्मिनल&amp;quot; as term
participant &amp;quot;Gradle
^^^^^
 Syntax Error? (Assumed diagram type: sequence)

@startuml
skinparam backgroundColor #FEFEFE

actor Développeur as dev
participant &amp;quot;टर्मिनल&amp;quot; as term
participant &amp;quot;Gradle
( प्रक्रिया )&amp;quot; as gradle

dev -&amp;amp;gt; term : ./gradlew build
term -&amp;amp;gt; gradle : Lance le build
gradle -&amp;amp;gt; term : Occupe le terminal\n(pas de prompt)
dev -&amp;amp;gt; term : veut taper une commande
term --&amp;amp;gt; dev : ❌ Terminal bloqué

note right of dev
  Le développeur est
  paralysé pendant
  toute la durée du build
end note
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अधिकांश डेवलपर्स एक नया टर्मिनल खोलते हैं। लेकिन एक अधिक सुंदर, तेज़ और मूल समाधान मौजूद है: जॉब प्रबंधन।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_तीन_अनिवार्य_आदेश&amp;quot;&amp;gt;तीन अनिवार्य आदेश&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ctrlz_रोकें_sigtstp&amp;quot;&amp;gt;Ctrl+Z — रोकें (SIGTSTP)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;`Ctrl+Z`सिग्नल भेजो`SIGTSTP`अग्रभूमि प्रक्रिया में. प्रक्रिया है&amp;lt;strong&amp;gt;निलंबित&amp;lt;/strong&amp;gt;— नहीं मारा गया — और टर्मिनल अपना प्रॉम्प्ट फिर से प्राप्त करता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ ./gradlew build
&amp;amp;gt; Building...
^Z
[1]+  Stoppé    ./gradlew build
$&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;कोष्ठकों के बीच की संख्या`[1]` est le &amp;lt;strong&amp;gt;जॉब नंबर&amp;lt;/strong&amp;gt;. Le `+`डिफ़ॉल्ट जॉब को दर्शाता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_fg_अग्रभूमि_में_लाएँ&amp;quot;&amp;gt;fg — अग्रभूमि में लाएँ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;`fg`यह निलंबित कार्य को अग्रभूमि में लाता है। प्रक्रिया ठीक उसी स्थान से फिर से शुरू हो जाती है जहाँ वह रुकी थी।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ fg
./gradlew build
&amp;amp;gt; Building... (reprend où il en était)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक विशिष्ट जॉब नंबर के साथ:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ fg %2&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_bg_पृष्ठभूमि_में_जारी_रखना&amp;quot;&amp;gt;bg — पृष्ठभूमि में जारी रखना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;`bg`प्रक्रिया को टर्मिनल ब्लॉक किए बिना फिर से शुरू करता है। लंबे बील्ड्स के लिए आदर्श।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ bg
[1]+ ./gradlew build &amp;amp;amp;
$&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le `&amp;amp;amp;`अंत में इसका मतलब है कि प्रक्रिया बैकग्राउंड में चल रही है.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_jobs_शेल_के_कार्यों_को_सूचीबद्ध_करना&amp;quot;&amp;gt;jobs — शेल के कार्यों को सूचीबद्ध करना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ jobs
[1]-  Stoppé    vim README.md
[2]+  En cours   ./gradlew build&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 6) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif

state &amp;quot;अग्रभूमि\n(ब्लॉक्ड टर्मिनल)&amp;quot; as fg #LightCoral
state &amp;quot;निलंबित
^^^^^
 Syntax Error? (Assumed diagram type: state)

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif

state &amp;quot;अग्रभूमि\n(ब्लॉक्ड टर्मिनल)&amp;quot; as fg #LightCoral
state &amp;quot;निलंबित
(Ctrl+Z)&amp;quot; as stopped #LightYellow
state &amp;quot;पृष्ठभूमि\n(bg)&amp;quot; as bg_ #LightGreen

[*] --&amp;amp;gt; fg : Lance une commande
fg --&amp;amp;gt; stopped : Ctrl+Z\n(SIGTSTP)
stopped --&amp;amp;gt; fg : fg\nreprend en avant-plan
stopped --&amp;amp;gt; bg_ : bg\nreprend en arrière-plan
bg_ --&amp;amp;gt; fg : fg\nramène en avant-plan
fg --&amp;amp;gt; [*] : Commande terminée

note right of stopped
  Le processus est figé
  mais _pas_ tué
end note

note left of bg_
  Le terminal est libre
  le build continue
end note
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिदृश्य_1_लंबा_बिल्ड&amp;quot;&amp;gt;परिदृश्य 1 : लंबा बिल्ड&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह सबसे सामान्य उपयोग का मामला है। आप एक Gradle बिल्ड शुरू करते हैं, टर्मिनल ब्लॉक हो जाता है, और आपको कुछ अन्य करने की आवश्यकता होती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 8) ]

@startuml
skinparam backgroundColor #FEFEFE
autonumber

actor Développeur as dev
participant &amp;quot;टर्मिनल&amp;quot; as term
participant &amp;quot;Gradle&amp;quot; as gradle
database &amp;quot;स्थिति
^^^^^
 Syntax Error? (Assumed diagram type: sequence)

@startuml
skinparam backgroundColor #FEFEFE
autonumber

actor Développeur as dev
participant &amp;quot;टर्मिनल&amp;quot; as term
participant &amp;quot;Gradle&amp;quot; as gradle
database &amp;quot;स्थिति
प्रक्रिया&amp;quot; as state

dev -&amp;amp;gt; term : ./gradlew build
term -&amp;amp;gt; gradle : Lance le build
gradle -&amp;amp;gt; state : En cours (FG)
dev -&amp;amp;gt; term : Ctrl+Z
term -&amp;amp;gt; state : Suspendu (job [1])
term --&amp;amp;gt; dev : Prompt libre $

dev -&amp;amp;gt; term : git status
term --&amp;amp;gt; dev : working tree clean

dev -&amp;amp;gt; term : fg
term -&amp;amp;gt; state : Reprend (FG)
gradle --&amp;amp;gt; dev : Build réussi ✓

note right of state
  Le processus Gradle
  n&amp;#39;a jamais été tué
  Il reprend exactement
  où il s&amp;#39;était arrêté
end note
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_चरण_दर_चरण&amp;quot;&amp;gt;चरण-दर-चरण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ ./gradlew build
&amp;amp;gt; Building...
^Z
[1]+  Stoppé    ./gradlew build

$ git status
On branch main
nothing to commit, working tree clean

$ fg
./gradlew build
&amp;amp;gt; Building...
BUILD SUCCESSFUL in 2m 34s&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_स्केनेरियो_2_भुला_हुआ_संपादक&amp;quot;&amp;gt;स्केनेरियो 2: भुला हुआ संपादक&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आप में हैं`vim`, आपको किसी अन्य फ़ाइल को देखना है बिना बाहर निकले`vim`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Dans vim, en mode commande :
:shell
$ cat /path/to/other/file.txt
$ exit
# Retour dans vim&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;लेकिन यह भारी है। के साथ`Ctrl+Z`, यह तुरंत है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Dans vim, n&amp;#39;importe quel moment :
Ctrl+Z
[1]+  Stoppé    vim README.md

$ cat /path/to/other/file.txt
# ... lire le fichier ...

$ fg
vim README.md
# Retour exact là où on en était, curseur en place&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/vim-suspend.svg&amp;quot; alt=&amp;quot;vim suspend&amp;quot; width=&amp;quot;406&amp;quot; height=&amp;quot;510&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;amp;lt;/think&amp;amp;gt; (No output)&amp;lt;code&amp;gt;vim`यह अपनी स्थिति को पूरी तरह से बहाल करता है एक`fg&amp;lt;/code&amp;gt;: कर्सर की स्थिति, बफ़र की सामग्री, अनडू इतिहास — सब कुछ संरक्षित है.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिदृश्य_3_opencode_प्रक्रिया_निलंबित&amp;quot;&amp;gt;परिदृश्य 3: opencode प्रक्रिया निलंबित&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह वह परिदृश्य है जिसने इस लेख को प्रेरित किया। आप उपयोग कर रहे हैं`opencode`(CLI टूल आपके कोड पर एक LLM को नियंत्रित करने के लिए), और प्रक्रिया निलंबित है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 7) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif
skinparam componentStyle rectangle

actor Développeur as dev
participant &amp;quot;opencode
^^^^^
 Syntax Error? (Assumed diagram type: sequence)

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif
skinparam componentStyle rectangle

actor Développeur as dev
participant &amp;quot;opencode
(LLM एजेंट)&amp;quot; as agent
participant &amp;quot;शेल&amp;quot; as shell
participant &amp;quot;गिट&amp;quot; as git

dev -&amp;amp;gt; agent : Session active
agent -&amp;amp;gt; agent : Tour de parole\ndu LLM en cours

note over agent
  Ctrl+Z arrive
  en plein milieu
  d&amp;#39;une analyse de code
end note

dev -&amp;amp;gt; agent : Ctrl+Z
agent -&amp;amp;gt; shell : Suspendu (job [1])
dev -&amp;amp;gt; git : git diff
git --&amp;amp;gt; dev : changements visibles
dev -&amp;amp;gt; shell : fg
shell -&amp;amp;gt; agent : Reprend (job [1])
agent --&amp;amp;gt; dev : Reprend exactement\nl&amp;#39;analyse en cours

note right of agent
  Aucune perte de contexte
  Le LLM reprend sa réponse
  exactement où il en était
end note
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ opencode
# ... session en cours, LLM analyse le code ...
^Z
[1]+  Stoppé    opencode

$ git diff HEAD~1
# vérifier les changements récents

$ fg
opencode
# Le LLM reprend là où il s&amp;#39;était arrêté&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फ़ायदा दोगुना है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;कोई संदर्भ हानि नहीं&amp;lt;/strong&amp;gt;LLM सत्र, वार्तालाप का इतिहास, खुले फ़ाइलें — सब कुछ संरक्षित है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;रीबूट नहीं&amp;lt;/strong&amp;gt;: opencode को पुनः प्रारंभ करने की आवश्यकता नहीं है, संदर्भ को पुनः लोड करने की आवश्यकता नहीं है, LLM को समस्या की पुनः व्याख्या करने की आवश्यकता नहीं है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिदृश्य_4_कई_जॉब्स_को_एक_साथ_प्रबंधित_करें&amp;quot;&amp;gt;परिदृश्य 4: कई जॉब्स को एक साथ प्रबंधित करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;fg&amp;lt;/code&amp;gt; et `bg`वे एक जॉब नंबर स्वीकार करते हैं एक विशेष प्रक्रिया को लक्ष्य करने के लिए जब कई निलंबित हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ vim config.yml
^Z
[1]+  Stoppé    vim config.yml

$ ./gradlew test
^Z
[2]+  Stoppé    ./gradlew test

$ htop
^Z
[3]+  Stoppé    htop

$ jobs
[1]   Stoppé    vim config.yml
[2]-  Stoppé    ./gradlew test
[3]+  Stoppé    htop

$ fg %2
./gradlew test
# Le build reprend en avant-plan

$ bg %3
[3] htop &amp;amp;amp;
# htop reprend en arrière-plan&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/multiple-jobs.svg&amp;quot; alt=&amp;quot;multiple jobs&amp;quot; width=&amp;quot;764&amp;quot; height=&amp;quot;280&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_कार्यों_के_आदेशों_का_सारांश&amp;quot;&amp;gt;कार्यों के आदेशों का सारांश&amp;lt;/h3&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 20%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 40%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 40%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;आदेश&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;प्रभाव&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;उदाहरण&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;Ctrl+Z&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;प्रक्रिया को अग्रभूमि में निलंबित करें&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;भेजने का`SIGTSTP`&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;fg&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;डिफ़ॉल्ट जॉब को फ़ोरग्राउंड में फिर से शुरू करें&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;fg&amp;lt;/code&amp;gt; ou &amp;lt;code&amp;gt;fg %1&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;fg %n&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;जॉब अग्रभूमि में फिर से शुरू करता है&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;fg %2&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;bg&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;डिफ़ॉल्ट जॉब को पृष्ठभूमि में फिर से शुरू करें&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;bg&amp;lt;/code&amp;gt; ou &amp;lt;code&amp;gt;bg %1&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;bg %n&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;न के जॉब को पृष्ठभूमि में फिर से शुरू करें&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;bg %2&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;jobs&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;वर्तमान शेल के कार्यों की सूची बनाएँ&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;jobs -l&amp;lt;/code&amp;gt;(PID के साथ)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;kill %n&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;job completo करो n&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;kill %2&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_fg_bg_ctrlz_ctrlc_और_के_अंतर&amp;quot;&amp;gt;fg, bg, Ctrl+Z, Ctrl+C और &amp;amp;amp; के अंतर&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;बहुत से डेवलपर्स इन तंत्रों को भ्रमित करते हैं। यहाँ एक निर्णायक स्पष्टीकरण दिया गया है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 7) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif

rectangle &amp;quot;**Ctrl+Z**\nSIGTSTP&amp;quot; as ctrlz #LightYellow {
  card &amp;quot;प्रक्रिया को निलंबित करें
(यह अभी भी मेमोरी में है)
^^^^^
 Syntax Error? (Assumed diagram type: activity)

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif

rectangle &amp;quot;**Ctrl+Z**\nSIGTSTP&amp;quot; as ctrlz #LightYellow {
  card &amp;quot;प्रक्रिया को निलंबित करें
(यह अभी भी मेमोरी में है)
fg/bg के साथ उपयोग करने योग्य&amp;quot; as c1
}

rectangle &amp;quot;**Ctrl+C**\nSIGINT&amp;quot; as ctrlc #LightCoral {
  card &amp;quot;प्रक्रिया को मारें
(वापसी संभव नहीं)
सभी स्थिति की हानि&amp;quot; as c2
}

rectangle &amp;quot;**&amp;amp;amp; **\n(पृष्ठभूमि)&amp;quot; as ampersand #LightGreen {
  card &amp;quot;सीधे लॉन्च करें
पृष्ठभूमि में
तुरंत मुक्त टर्मिनल&amp;quot; as c3
}

rectangle &amp;quot;**fg**\n(अग्रभूमि)&amp;quot; as fg_ #SkyBlue {
  card &amp;quot;एक जॉब लाओ
फॉरग्राउंड में सस्पेंडेड
टर्मिनल व्यस्त&amp;quot; as c4
}

rectangle &amp;quot;**bg**\n(पृष्ठभूमि)&amp;quot; as bg_ #Lavender {
  card &amp;quot;एक काम फिर से शुरू
पृष्ठभूमि में निलंबित
मुक्त टर्मिनल&amp;quot; as c5
}

ctrlz -right-&amp;amp;gt; fg_ : fg pour reprendre
ctrlz -right-&amp;amp;gt; bg_ : bg pour continuer\nen arrière-plan
ctrlc -right-&amp;amp;gt; c2 : Pas de retour\nprocessus tué

note bottom of ctrlz
  Le processus est **figé**
  mais **pas tué**
end note

note bottom of ampersand
  Alternative : lancer
  ./gradlew build &amp;amp;amp;
  directement en arrière-plan
end note
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 16.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 16.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3335%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;शॉर्टकट/कमांड&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;सिग्नल&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;प्रभाव&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;वापस लौटना?&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;Ctrl+Z&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;SIGTSTP&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;प्रक्रिया को निलंबित करें (जमा, मेमोरी में)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;हाँ :`fg` ou &amp;lt;code&amp;gt;bg&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;Ctrl+C&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;SIGINT&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;प्रक्रिया को मारें (समाप्त)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;नहीं: नष्ट प्रक्रिया&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;Ctrl+\&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;SIGQUIT&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;प्रक्रिया मारो + core dump&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;नहीं : नष्ट प्रक्रिया&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;commande &amp;amp;amp;&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;(No output)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;बैकग्राउंड में सीधे लॉन्च करें&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;`fg`इसे सामने लाने के लिए&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock tip&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-tip&amp;quot; title=&amp;quot;Tip&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;code&amp;gt;Ctrl+Z`JBake संदर्भ (यह सामग्री JBake टेम्प्लेट और कन्वेंशन का उपयोग करती है): &amp;lt;mark&amp;gt;#&amp;lt;/mark&amp;gt; JBake CLI कमांड ``&amp;lt;/code&amp;gt; # Initialize a new JBake project jbake -i
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;h1 id=&amp;quot;_bake_generate_the_site_jbake_b&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake (generate) the site jbake -b&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_and_serve_locally_jbake_b_s&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake and serve locally jbake -b -s&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_and_watch_for_changes_jbake_b_reset&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake and watch for changes jbake -b --reset&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_specify_source_and_destination_jbake_source_folder_output_folder&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Specify source and destination jbake source_folder output_folder&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_clear_the_output_directory_before_baking_jbake_b_output_resetगैर_विध्वंसक_jbake_cli_commands_initialize_a_new_jbake_project_jbake_i&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Clear the output directory before baking jbake -b . output --reset&amp;lt;strong&amp;gt;गैर-विध्वंसक&amp;lt;/strong&amp;gt;&amp;lt;mark&amp;gt;#&amp;lt;/mark&amp;gt; JBake CLI Commands &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; # Initialize a new JBake project jbake -i&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_generate_the_site_jbake_b_2&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake (generate) the site jbake -b&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_and_serve_locally_jbake_b_s_2&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake and serve locally jbake -b -s&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_and_watch_for_changes_jbake_b_reset_2&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake and watch for changes jbake -b --reset&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_specify_source_and_destination_jbake_source_folder_output_folder_2&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Specify source and destination jbake source_folder output_folder&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_clear_the_output_directory_before_baking_jbake_b_output_reset&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Clear the output directory before baking jbake -b . output --reset &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt;&amp;lt;/h1&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;fr से hi में अनुवाद करें सभी बैकटिक कोड स्पैन (&amp;lt;code&amp;gt;&amp;amp;#8230;&amp;amp;#8203;&amp;lt;/code&amp;gt;) को बिल्कुल वैसा ही रखें — बैकटिक की सामग्री, स्पेसिंग, या स्थिति कभी न बदलें। यह पाठ बड़े वाक्य का एक अंश हो सकता है — अंश का अनुवाद अधिक संदर्भ मांगे बिना करें। केवल अनुवादित पाठ आउटपुट करें — कोई स्पष्टीकरण, कोई टिप्पणी, कोई परिचय, कोई विकल्प, कोई विकल्प नहीं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;प्रक्रिया स्मृति में वैसे ही स्थिर है। आप तुरंत इसे जारी रख सकते हैं`fg`. यह एक &amp;lt;em&amp;gt;pause&amp;lt;/em&amp;gt; है, एक &amp;lt;em&amp;gt;stop&amp;lt;/em&amp;gt; नहीं.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_एक_जॉब_का_पूरा_जीवन_चक्र&amp;quot;&amp;gt;एक जॉब का पूरा जीवन चक्र&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 7) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif

title शेल जॉब का पूर्ण जीवन चक्र
state &amp;quot;अस्तित्वहीन&amp;quot; as none
state &amp;quot;अग्रभूमि
^^^^^
 Syntax Error? (Assumed diagram type: state)

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif

title शेल जॉब का पूर्ण जीवन चक्र
state &amp;quot;अस्तित्वहीन&amp;quot; as none
state &amp;quot;अग्रभूमि
(टर्मिनल को घेरता है)&amp;quot; as foreground #LightCoral
state &amp;quot;निलंबित\n(Ctrl+Z / SIGTSTP)&amp;quot; as suspended #LightYellow
state &amp;quot;पृष्ठभूमि\n(bgまたは &amp;amp;amp;)&amp;quot; as background #LightGreen
state &amp;quot;समाप्त
(exit code 0)&amp;quot; as done #LightGray

[*] --&amp;amp;gt; none
none --&amp;amp;gt; foreground : tape une commande
foreground --&amp;amp;gt; suspended : Ctrl+Z
foreground --&amp;amp;gt; done : fin normale

suspended --&amp;amp;gt; foreground : fg
suspended --&amp;amp;gt; background : bg
suspended --&amp;amp;gt; done : kill %n

background --&amp;amp;gt; foreground : fg
background --&amp;amp;gt; done : fin normale\n(en arrière-plan)
background --&amp;amp;gt; suspended : Ctrl+Z\n(si fg puis Ctrl+Z)

done --&amp;amp;gt; [*]

note right of suspended
  L&amp;#39;état suspendu est
  le pivot de tout le
  système de jobs
end note
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_उन्नत_टिप्स&amp;quot;&amp;gt;उन्नत टिप्स&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_fg_नौकरी_के_साथ_सबसे_नया_और_अल्टरनेन्स&amp;quot;&amp;gt;fg नौकरी के साथ सबसे नया और अल्टरनेन्स&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;fg`कोई तर्क नहीं होने पर चिह्नित काम लौटाता है&amp;lt;/code&amp;gt;+&amp;lt;code&amp;gt;(सबसे हालिया). लेकिन आप भी इसका उपयोग कर सकते हैं&amp;lt;/code&amp;gt;%-`पिछले जॉब को लक्ष्य करने के लिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ vim file1.txt
^Z
[1]+  Stoppé    vim file1.txt

$ vim file2.txt
^Z
[2]+  Stoppé    vim file2.txt

$ fg      # ramène job [2] (le plus récent)
$ fg %-   # ramène job [1] (le précédent)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_काम_को_सही_तरीके_से_पूरा_करना&amp;quot;&amp;gt;काम को सही तरीके से पूरा करना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ jobs
[1]-  Stoppé    vim config.yml
[2]+  Stoppé    ./gradlew test

$ kill %2       # envoie SIGTERM au job 2
$ kill -9 %1    # envoie SIGKILL au job 1 (force)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_désown_शेल_से_अलग_करें&amp;quot;&amp;gt;désown : शेल से अलग करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;disown`शेल की जॉब टेबल से एक जॉब हटाएँ। प्रक्रिया चलती रहती है लेकिन अब इसे वापस नहीं लाया जा सकता`fg&amp;lt;/code&amp;gt;:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ ./gradlew build &amp;amp;amp;
[1] 12345

$ disown %1
# Le processus continue mais n&amp;#39;est plus lié au shell
# Ça survives à la fermeture du terminal&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_nohup_के_साथ_मिलाएँ_लंबी_प्रक्रियाओं_के_लिए&amp;quot;&amp;gt;nohup के साथ मिलाएँ लंबी प्रक्रियाओं के लिए&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक प्रक्रिया टर्मिनल बंद होने के बाद भी जीवित रहने के लिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ nohup ./gradlew build &amp;amp;amp;
[1] 12345
$ disown %1
# Le build continue même si vous fermez le terminal&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 7) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif

rectangle &amp;quot;fg&amp;quot; as fg_ #SkyBlue {
  card &amp;quot;जॉब लाओ
सबसे हाल का (+)&amp;quot; as f1
^^^^^
 Syntax Error? (Assumed diagram type: activity)

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif

rectangle &amp;quot;fg&amp;quot; as fg_ #SkyBlue {
  card &amp;quot;जॉब लाओ
सबसे हाल का (+)&amp;quot; as f1
  card &amp;quot;एक नौकरी को लक्ष्य बनाएँ
विशिष्ट : fg %n&amp;quot; as f2
  card &amp;quot;बदलें : fg %-&amp;quot; as f3
}

rectangle &amp;quot;मारो %n&amp;quot; as kill_ #LightCoral {
  card &amp;quot;SIGTERM (स्वच्छ)&amp;quot; as k1
  card &amp;quot;SIGKILL -9 (बल)&amp;quot; as k2
}

rectangle &amp;quot;इन्कार करना&amp;quot; as disown #Lavender {
  card &amp;quot;शेल से अलग करें\n(डिस्कनेक्शन के दौरान जीवित रहता है)&amp;quot; as d1
}

rectangle &amp;quot;nohup + &amp;amp;amp;&amp;quot; as nohup_ #LightGreen {
  card &amp;quot;इम्यूनाइज़्ड प्रक्रिया
SIGHUP के खिलाफ
(टर्मिनल के बंद होने पर जीवित रहता है)&amp;quot; as n1
}

fg_ -right-&amp;amp;gt; kill_ : si faut\nterminer
kill_ -right-&amp;amp;gt; disown_ : ou détacher
nohup_ -left-&amp;amp;gt; fg_ : fg ramène en\navant-plan

note bottom of disown_
  Après disown, fg ne peut
  plus ramener le job
end note
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_जाल_और_सामान्य_त्रुटियाँ&amp;quot;&amp;gt;जाल और सामान्य त्रुटियाँ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ctrlz_और_ctrlc_को_भ्रमित_करना&amp;quot;&amp;gt;Ctrl+Z और Ctrl+C को भ्रमित करना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह सबसे सामान्य त्रुटि है।`Ctrl+C`प्रक्रिया को मारता है।`Ctrl+Z`वह निलंबित कर देता है। यदि आप दबाते हैं`Ctrl+C`reflex से, पूरी स्थिति खो जाती है — खुले फ़ाइलें, LLM सत्र, चल रहे बिल्ड।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/ctrlz-vs-ctrlc.svg&amp;quot; alt=&amp;quot;ctrlz vs ctrlc&amp;quot; width=&amp;quot;1222&amp;quot; height=&amp;quot;129&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_जॉब्स_शेल_के_लिए_स्थानीय_होते_हैं&amp;quot;&amp;gt;जॉब्स शेल के लिए स्थानीय होते हैं&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;jobs&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;fg&amp;lt;/code&amp;gt; et `bg`वे केवल उसी शेल में काम करते हैं जिसने प्रक्रियाओं को लॉन्च किया। यदि आप एक नया टर्मिनल खोलते हैं, तो आप दूसरे के जॉब्स नहीं देख पाएंगे।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Terminal 1
$ vim file.txt
^Z
[1]+  Stoppé    vim file.txt

# Terminal 2 (nouveau)
$ jobs
# (rien — les jobs sont locaux au shell)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सिस्टम-वाइड प्रक्रियाएँ देखने के लिए, उपयोग करें`ps` ou &amp;lt;code&amp;gt;htop&amp;lt;/code&amp;gt;:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;ps aux | grep vim&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_जॉब्स_शेल_बंद_होने_पर_जीवित_नहीं_रहते&amp;quot;&amp;gt;जॉब्स शेल बंद होने पर जीवित नहीं रहते।&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यदि आप टर्मिनल बंद कर देते हैं, तो सभी निलंबित या बैकग्राउंड जॉब्स नष्ट हो जाते हैं। एक प्रक्रिया को जीवित रखने के लिए, उपयोग करें`nohup`+&amp;lt;code&amp;gt;disown&amp;lt;/code&amp;gt;:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ nohup ./gradlew build &amp;amp;amp;
[1] 12345
$ disown %1
# Fermer le terminal → le build continue&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_इंटरएक्टिव_प्रक्रियाएँ_और_fg&amp;quot;&amp;gt;इंटरएक्टिव प्रक्रियाएँ और fg&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;कुछ इंटरएक्टिव प्रोग्राम एक के बाद अच्छा प्रदर्शन नहीं करते`Ctrl+Z`+&amp;lt;code&amp;gt;fg&amp;lt;/code&amp;gt;. यह दुर्लभ है लेकिन ऐसा होता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कुछ प्रोग्राम जो संकेतों का उपयोग करते हैं (vim, htop, less) अच्छी तरह से काम करते हैं`Ctrl+Z`)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;लंबे नेटवर्क प्रोग्राम (ssh, opencode) सामान्यतः सही ढंग से पुनर्प्राप्त होते हैं&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;टर्मिनल (ncurses) को संशोधित करने वाले कार्यक्रम कभी‑कभी टर्मिनल को अपेक्षित नहीं स्थिति में छोड़ सकते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;भ्रष्ट टर्मिनल के बाद एक`fg`, टाइप करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;reset&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_सारांश_आरेख&amp;quot;&amp;gt;सारांश आरेख&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 10) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif
skinparam ArrowColor #444444

title &amp;quot;fg — टिप्स जो सब कुछ बदल देते हैं&amp;quot;

rectangle &amp;quot;**समस्या**&amp;quot; as problem #LightCoral {
  card &amp;quot;टर्मिनल अवरुद्ध
एक प्रक्रिया द्वारा&amp;quot; as p1
^^^^^
 Syntax Error? (Assumed diagram type: activity)

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif
skinparam ArrowColor #444444

title &amp;quot;fg — टिप्स जो सब कुछ बदल देते हैं&amp;quot;

rectangle &amp;quot;**समस्या**&amp;quot; as problem #LightCoral {
  card &amp;quot;टर्मिनल अवरुद्ध
एक प्रक्रिया द्वारा&amp;quot; as p1
  card &amp;quot;नया\nटर्मिनल खोलना = भारी समाधान&amp;quot; as p2
}

rectangle &amp;quot;समाधान&amp;quot; as solution #LightGreen {
  card &amp;quot;Ctrl+Z → निलंबित&amp;quot; as s1
  card &amp;quot;fg → फिर से शुरू करता है&amp;quot; as s2
  card &amp;quot;bg → पृष्ठभूमि में&amp;quot; as s3
  card &amp;quot;jobs → voir les suspendus&amp;quot; as s4
}

rectangle &amp;quot;**लाभ**&amp;quot; as advantages #SkyBlue {
  card &amp;quot;संदर्भ की हानि नहीं&amp;quot; as a1
  card &amp;quot;रीस्टार्ट नहीं&amp;quot; as a2
  card &amp;quot;एक टर्मिनल पर्याप्त है&amp;quot; as a3
}

problem -right-&amp;amp;gt; solution : &amp;quot;Unix का स्वाभाविक समाधान 40 वर्षों से&amp;quot;
solution -right-&amp;amp;gt; advantages : &amp;quot;परिणाम&amp;quot;

note bottom of advantages
  fg n&amp;#39;est pas un tips obscur
  C&amp;#39;est un mécanisme fondamental
  du shell Unix
end note
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_fg_क्यों_कम_आंका_गया&amp;quot;&amp;gt;fg क्यों कम आंका गया&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अधिकांश आधुनिक डेवलपर्स खोजते हैं`fg`देर से, या कभी नहीं। कुछ कारण :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;IDE टर्मिनल छुपाते हैं&amp;lt;/strong&amp;gt;: VS Code एक इंटीग्रेटेड टर्मिनल प्रदान करता है, लेकिन कई टैब बनाते हैं`fg`दिखने में कम आवश्यक&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;ग्राफ़िकल टूल्स CLI को प्रतिस्थापित करते हैं&amp;lt;/strong&amp;gt;: फ़ाइल प्रबंधक, सिस्टम मॉनिटर, ग्राफ़िकल Git क्लाइंट&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;tmux और स्क्रीन&amp;lt;/strong&amp;gt;: ये मल्टीप्लेक्सर्स एक ही समस्या को अलग तरीके से हल करते हैं, लेकिन`fg`यह अधिक सरल और हमेशा उपलब्ध है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फिर भी,&amp;lt;code&amp;gt;fg&amp;lt;/code&amp;gt;&amp;lt;mark&amp;gt;#&amp;lt;/mark&amp;gt; JBake CLI Commands &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; # Initialize a new JBake project jbake -i&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;h1 id=&amp;quot;_bake_generate_the_site_jbake_b_3&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake (generate) the site jbake -b&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_and_serve_locally_jbake_b_s_3&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake and serve locally jbake -b -s&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_and_watch_for_changes_jbake_b_reset_3&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake and watch for changes jbake -b --reset&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_specify_source_and_destination_jbake_source_folder_output_folder_3&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Specify source and destination jbake source_folder output_folder&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_clear_the_output_directory_before_baking_jbake_b_output_reset_है&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Clear the output directory before baking jbake -b . output --reset &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; है :&amp;lt;/h1&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;सार्वभौमिक&amp;lt;/strong&amp;gt;सभी POSIX शेल्स में मौजूद (bash, zsh, fish&amp;amp;#8230;&amp;amp;#8203;)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;निर्भरता के बिना&amp;lt;/strong&amp;gt;: tmux या स्क्रीन इंस्टॉल करने की ज़रूरत नहीं&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;तत्क्षणिक&amp;lt;/strong&amp;gt;: दो हमले (&amp;lt;code&amp;gt;Ctrl+Z`फिर`fg&amp;lt;/code&amp;gt;) रोकने और फिर से शुरू करने के लिए&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;संदर्भ संरक्षक&amp;lt;/strong&amp;gt; : l&amp;amp;#8217;état du processus est intact&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 6) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif

rectangle &amp;quot;fg है
कम आंका गया ?&amp;quot; as why #LightCoral {
^^^^^
 Syntax Error? (Assumed diagram type: activity)

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif

rectangle &amp;quot;fg है
कम आंका गया ?&amp;quot; as why #LightCoral {
  card &amp;quot;IDE के साथ टर्मिनल\nबहु-टैब&amp;quot; as w1
  card &amp;quot;ग्राफ़िकल उपकरण
जो CLI को बदलते हैं&amp;quot; as w2
  card &amp;quot;tmux/screen समस्या को अन्य तरीके से हल करते हैं&amp;quot; as w3
}

rectangle &amp;quot;क्यों fg है
बेहतर ?&amp;quot; as superior #LightGreen {
  card &amp;quot;सार्वत्रिक : bash,
zsh, fish, sh...&amp;quot; as s1
  card &amp;quot;निर्भरता रहित:\nइंस्टॉलेशन नहीं&amp;quot; as s2
  card &amp;quot;दो हमले:\nCtrl+Z फिर fg&amp;quot; as s3
  card &amp;quot;संरक्षित संदर्भ:
शून्य राज्य हानि&amp;quot; as s4
}

why -right-&amp;amp;gt; superior : &amp;quot;सादगी
हमेशा जीतती है&amp;quot;
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_तकनीकी_ज्ञापन_संकेत&amp;quot;&amp;gt;तकनीकी ज्ञापन : संकेत&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जिज्ञासु लोगों के लिए, यहाँ संलग्न संकेत हैं:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 14.2857%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 28.5714%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 28.5714%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 28.5715%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;सिग्नल&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;नाम&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;भेजा गया&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;प्रभाव&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;2&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;SIGINT&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;Ctrl+C&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;बाधा — प्रक्रिया समाप्त कर देती है&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;3&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;SIGQUIT&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;Ctrl+\&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;कोर डंप के साथ बाहर निकलता&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;18&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;SIGTSTP&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;Ctrl+Z&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;इंटरैक्टिव स्टॉप — प्रक्रिया को निलंबित करता है&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;19&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;SIGCONT&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;fg&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;bg&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;जारी रखें — एक निलंबित प्रक्रिया को फिर से शुरू करता है&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;15&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;SIGTERM&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;kill %n&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;स्वच्छ समापन&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;9&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;SIGKILL&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;kill -9 %n&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;जबरदस्त समाप्ति (इसे अवरोधित नहीं किया जा सकता)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पूर्ण प्रवाह:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/signal-flow.svg&amp;quot; alt=&amp;quot;signal flow&amp;quot; width=&amp;quot;442&amp;quot; height=&amp;quot;525&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;`fg`यह एक अस्पष्ट सुझाव नहीं है — यह यूनिक्स शेल का एक मौलिक तंत्र है, जो 1970 के दशक से उपलब्ध है। अधिकांश डेवलपर्स द्वारा इसे अनदेखा करना हमारे युग का एक लक्षण है: IDE और मल्टीप्लेक्सर्स ने हमें मूल बातों से दूर कर दिया है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;लेकिन जब आप एक SSH सर्वर पर हैं, एक न्यूनतम टर्मिनल में हैं, या बस उपयोग कर रहे हैं`opencode`और LLM पूरी तरह से काम कर रहा है —&amp;lt;code&amp;gt;Ctrl+Z&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;fg&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bg&amp;lt;/code&amp;gt;, `jobs`हैं आपके सबसे अच्छे दोस्तों.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;(No output) Ctrl+Z रोकता है, fg फिर से शुरू करता है। यह टर्मिनल की पॉज़‑प्ले है। (No output)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_संदर्भ&amp;quot;&amp;gt;संदर्भ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;man bash&amp;lt;/code&amp;gt;— खंड JOB CONTROL&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;man signal&amp;lt;/code&amp;gt;— POSIX संकेतों की सूची&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://www.gnu.org/software/bash/manual/bash.html#Job-Control&amp;quot;&amp;gt;Bash रेफ़रेंस मैनुअल — जॉब कंट्रोल&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://man7.org/linux/man-pages/man7/signal.7.html&amp;quot;&amp;gt;man 7 signal — लिनक्स सिग्नल&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://tldp.org/LDP/abs/html/x312743.htm&amp;quot;&amp;gt;उन्नत बैश-स्क्रिप्टिंग गाइड — कार्य नियंत्रण&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>VS Code होम में : स्थानीय स्थापना और फ़ॉन्ट कस्टमाइज़ेशन sudo के बिना</title>
            <link >https://cheroliv.com/blog/2026/0103_vscode_local_install_custom_fonts_post.html</link>
            <pubDate>Fri, 17 Apr 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0103_vscode_local_install_custom_fonts_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पथ_का_अवलोकन&amp;quot;&amp;gt;पथ का अवलोकन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_क्यों_vs_code_घर_में&amp;quot;&amp;gt;क्यों : VS Code घर में&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सिस्टम_इंस्टॉलेशन_के_साथ_समस्या&amp;quot;&amp;gt;सिस्टम इंस्टॉलेशन के साथ समस्या&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समाधान_एक_स्थानीय_स्थापना&amp;quot;&amp;gt;समाधान : एक स्थानीय स्थापना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_वास्तविक_लाभ&amp;quot;&amp;gt;वास्तविक लाभ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_मुख्य_मेनू_के_फ़ॉन्ट_को_अनुकूलित_करें&amp;quot;&amp;gt;मुख्य मेनू के फ़ॉन्ट को अनुकूलित करें&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निरीक्षण&amp;quot;&amp;gt;निरीक्षण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_तकनीक_सीधा_सीएसएस_पैच&amp;quot;&amp;gt;तकनीक : सीधा सीएसएस पैच&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सत्यनिष्ठा_चेतावनी_हटाएँ&amp;quot;&amp;gt;सत्यनिष्ठा चेतावनी हटाएँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_एक्सप्लोरर_पैनल_का_फ़ॉन्ट_कस्टमाइज़_करें_लड़ाई&amp;quot;&amp;gt;एक्सप्लोरर पैनल का फ़ॉन्ट कस्टमाइज़ करें — लड़ाई&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_टेंटेटिव1_ऐसा_पैरामीटर_जो_नहीं_मौजूद_है&amp;quot;&amp;gt;टेंटेटिव 1: ऐसा पैरामीटर जो नहीं मौजूद है&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_प्रयास_2_एक्सटेंशन_custom_css_and_js_loader&amp;quot;&amp;gt;प्रयास 2 : एक्सटेंशन Custom CSS and JS Loader&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_जाल_हर_बार_एक्सटेंशन_को_सक्रिय_करना_होगा&amp;quot;&amp;gt;जाल: हर बार एक्सटेंशन को सक्रिय करना होगा&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_प्रयास_3_रेखाएँ_ओवरलैप_होती_हैं&amp;quot;&amp;gt;प्रयास 3: रेखाएँ ओवरलैप होती हैं&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समाधान_zoom_मातृ_कंटेनर_पर&amp;quot;&amp;gt;समाधान : &amp;lt;code&amp;gt;zoom&amp;lt;/code&amp;gt; मातृ कंटेनर पर&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सेलेक्टर्स_का_सारांश_और_क्या_काम_करता_है&amp;quot;&amp;gt;सेलेक्टर्स का सारांश और क्या काम करता है&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ऑटोमैटिक_अपडेट_स्क्रिप्ट&amp;quot;&amp;gt;ऑटोमैटिक अपडेट स्क्रिप्ट&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या&amp;quot;&amp;gt;समस्या&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_स्क्रिप्ट_vscode_update_sh&amp;quot;&amp;gt;स्क्रिप्ट `vscode-update.sh&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संबंधित_फाइलें_अवलोकन&amp;quot;&amp;gt;संबंधित फाइलें — अवलोकन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सीखे_हुए_सबक&amp;quot;&amp;gt;सीखे हुए सबक&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_होम_में_इंस्टॉल_करने_से_सब_कुछ_मुक्त_हो_जाता_है&amp;quot;&amp;gt;होम में इंस्टॉल करने से सब कुछ मुक्त हो जाता है&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_zoom_font_size_सूची_घटकों_के_लिए&amp;quot;&amp;gt;zoom` &amp;amp;gt; &amp;lt;code&amp;gt;font-size&amp;lt;/code&amp;gt; सूची घटकों के लिए&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_custom_css_एक्सटेंशन_को_स्पष्ट_रूप_से_सक्रिय_करने_की_आवश्यकता_है&amp;quot;&amp;gt;Custom CSS एक्सटेंशन को स्पष्ट रूप से सक्रिय करने की आवश्यकता है&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_एक_अपडेट_स्क्रिप्ट_आवश्यक_है&amp;quot;&amp;gt;एक अपडेट स्क्रिप्ट आवश्यक है&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_त्वरित_संदर्भ&amp;quot;&amp;gt;त्वरित संदर्भ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;पढ़ने का समय : 8 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;VS Code को क्यों स्थापित करें में`/opt`या द्वारा`apt`quand हम इसे अपने घर में रख सकते हैं और अपने IDE को कभी टाइप किए बिना एक प्लेग्राउंड में बदल सकते हैं`sudo`यहाँ एक स्थानीय स्थापना की कहानी है, उसके बाद मेनू और फ़ाइल एक्सप्लोरर के फ़ॉन्ट को बढ़ाने के लिए एक कड़ा संघर्ष।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;विषय सूची&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;[]&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_पथ_का_अवलोकन&amp;quot;&amp;gt;पथ का अवलोकन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 10) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

actor Développeur as dev
actor &amp;quot;opencode\n+ LLM&amp;quot; as agent

package &amp;quot;होम उपयोगकर्ता (~)&amp;quot; #LightGreen {
    package &amp;quot;~/apps/&amp;quot; {
        component &amp;quot;VS Code
^^^^^
 Syntax Error? (Assumed diagram type: component)

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

actor Développeur as dev
actor &amp;quot;opencode\n+ LLM&amp;quot; as agent

package &amp;quot;होम उपयोगकर्ता (~)&amp;quot; #LightGreen {
    package &amp;quot;~/apps/&amp;quot; {
        component &amp;quot;VS Code
(टैरबॉल)&amp;quot; as vscode #SkyBlue
        component &amp;quot;vscode-update.sh&amp;quot; as script #LightYellow
    }
    package &amp;quot;~/.config/Code/&amp;quot; {
        component &amp;quot;settings.json&amp;quot; as settings #Lavender
    }
    package &amp;quot;~/.vscode-custom-css/&amp;quot; {
        component &amp;quot;custom.css
(ज़ूम: 1.25)&amp;quot; as customcss #Lavender
    }
}

cloud &amp;quot;code.visualstudio.com&amp;quot; as download

dev --&amp;amp;gt; vscode : Télécharge &amp;amp;amp; installe
dev --&amp;amp;gt; script : Lance mise à jour
script --&amp;amp;gt; download : wget dernière version
script --&amp;amp;gt; vscode : Remplace + re-patch CSS
agent --&amp;amp;gt; settings : Écrit config
agent --&amp;amp;gt; customcss : Écrit zoom CSS
agent --&amp;amp;gt; vscode : Patch workbench CSS

note right of vscode
  Installation dans le home
  = contrôle total sans sudo
end note
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_क्यों_vs_code_घर_में&amp;quot;&amp;gt;क्यों : VS Code घर में&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सिस्टम_इंस्टॉलेशन_के_साथ_समस्या&amp;quot;&amp;gt;सिस्टम इंस्टॉलेशन के साथ समस्या&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;VS Code को इंस्टॉल किया गया के माध्यम से`apt`, &amp;lt;code&amp;gt;dnf`या में&amp;lt;/code&amp;gt;/opt`ऐप्लिकेशन के फ़ाइलों को रूट अधिकारों के पीछे लॉक करता है। नेटिव CSS का कोई भी संशोधन, de`product.json`या इंस्टॉलेशन फ़ोल्डर की आवश्यकता है`sudo`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अब, जब कोई उपयोग करता है&amp;lt;strong&amp;gt;ओपेन्कोड&amp;lt;/strong&amp;gt;(टूल CLI अपने कोड पर एक LLM को नियंत्रित करने के लिए), एजेंट को सक्षम होने की आवश्यकता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कॉन्फ़िगरेशन फ़ाइलों में लिखना (&amp;lt;code&amp;gt;~/.config/Code/User/settings.json&amp;lt;/code&amp;gt;) — यह पहले से ही होमपेज में है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;IDE के एसेट्स को संशोधित करें (वर्कबेंच CSS,&amp;lt;code&amp;gt;product.json&amp;lt;/code&amp;gt;) उन्नत कस्टमाइज़ेशन के लिए — यह sudo के बिना ब्लॉक है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_समाधान_एक_स्थानीय_स्थापना&amp;quot;&amp;gt;समाधान : एक स्थानीय स्थापना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हम आधिकारिक टैरबॉल आर्काइव डाउनलोड करते हैं और उसे सीधे therein में निकालते हैं`~/apps/`:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;mkdir -p ~/apps
cd ~/apps
wget &amp;quot;https://code.visualstudio.com/sha/download?build=stable&amp;amp;amp;os=linux-x64&amp;quot; -O vscode.tar.gz
tar -xzf vscode.tar.gz
rm vscode.tar.gz&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;बाइनरी तब है`~/apps/VSCode-linux-x64/bin/code`. कोई नहीं`sudo`किसी भी फ़ाइल को पढ़ने, संपादित करने या बदलने के लिए आवश्यक नहीं है`~/apps/VSCode-linux-x64/`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_वास्तविक_लाभ&amp;quot;&amp;gt;वास्तविक लाभ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 5) ]

@startuml
skinparam backgroundColor #FEFEFE

rectangle &amp;quot;इंस्टॉलेशन सिस्टम
(/opt, apt, dnf)&amp;quot; #LightCoral {
^^^^^
 Syntax Error? (Assumed diagram type: activity)

@startuml
skinparam backgroundColor #FEFEFE

rectangle &amp;quot;इंस्टॉलेशन सिस्टम
(/opt, apt, dnf)&amp;quot; #LightCoral {
    card &amp;quot;VS Code रूट की संपत्ति&amp;quot; {
        [CSS du workbench : sudo requis]
        [product.json : sudo requis]
        [Dossier d&amp;#39;install : non modifiable]
    }
}

rectangle &amp;quot;स्थापना होम\n(~/apps)&amp;quot; #LightGreen {
    card &amp;quot;VS Code यूज़र की संपत्ति&amp;quot; {
        [CSS du workbench : libre]
        [product.json : libre]
        [Dossier d&amp;#39;install : libre]
        [Script update maison]
    }
}

&amp;quot;इंस्टॉलेशन सिस्टम
(/opt, apt, dnf)&amp;quot; -right-&amp;amp;gt; &amp;quot;स्थापना होम\n(~/apps)&amp;quot; : **Non, merci**\nJe prends le home

note bottom of &amp;quot;स्थापना होम\n(~/apps)&amp;quot;
  L&amp;#39;agent opencode+LLM peut
  modifier les fichiers de l&amp;#39;IDE
  sans aucune élévation de privilèges
end note
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 66.6667%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;लाभ&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;विवरण&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;sudo नहीं&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;IDE के सभी फ़ाइल उपयोगकर्ता के हैं।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;CSS का सीधा संशोधन&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;पैच किया जा सकता है`workbench.desktop.main.css`विशेषाधिकार वृद्धि के बिना&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;घरेलू अपडेट स्क्रिप्ट&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक साधारण शेल स्क्रिप्ट स्वचालित रूप से डाउनलोड, प्रतिस्थापित और पुनः पैच करती है&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;अलगाव&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;सिस्टम इंस्टॉलेशन प्रदूषित नहीं है ; rollback = फ़ोल्डर हटाएँ&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_मुख्य_मेनू_के_फ़ॉन्ट_को_अनुकूलित_करें&amp;quot;&amp;gt;मुख्य मेनू के फ़ॉन्ट को अनुकूलित करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_निरीक्षण&amp;quot;&amp;gt;निरीक्षण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मुख्य मेनू (फ़ाइल, संपादन, दृश्य &amp;amp;#8230;&amp;amp;#8203;) और ड्रॉप‑डाउन का डिफ़ॉल्ट फ़ॉन्ट बहुत छोटा है। VS Code में इसे बदलने के लिए कोई सेटिंग नहीं है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_तकनीक_सीधा_सीएसएस_पैच&amp;quot;&amp;gt;तकनीक : सीधा सीएसएस पैच&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फ़ाइल के अंत में CSS जोड़ें`workbench.desktop.main.css`(No output)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 6) ]

@startuml
skinparam backgroundColor #FEFEFE
autonumber

actor Développeur as dev
participant &amp;quot;workbench.desktop
^^^^^
 Syntax Error? (Assumed diagram type: sequence)

@startuml
skinparam backgroundColor #FEFEFE
autonumber

actor Développeur as dev
participant &amp;quot;workbench.desktop
.main.css&amp;quot; as css
participant &amp;quot;product.json&amp;quot; as product
participant &amp;quot;VS कोड&amp;quot; as vscode

== Patch CSS ==
dev -&amp;amp;gt; css : Ajouter règles font-size\n(.menubar-menu-title, etc.)
dev -&amp;amp;gt; vscode : Redémarrer VS Code
vscode -&amp;amp;gt; vscode : Charge le CSS patché
vscode --&amp;amp;gt; dev : Menus et dropdowns en 23px/22px ✓

== Suppression warning ==
vscode --&amp;amp;gt; dev : ⚠️ &amp;quot;आपकी स्थापना दूषित है&amp;quot;
dev -&amp;amp;gt; product : Supprimer clé &amp;quot;चेकसम&amp;quot;\n(python3 -c ...)
dev -&amp;amp;gt; vscode : Redémarrer VS Code
vscode --&amp;amp;gt; dev : Plus de warning ✓

note over css, product
  Deux fichiers dans ~/apps/
  = modifiables sans sudo
end note
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;CSS_FILE=&amp;quot;$HOME/apps/VSCode-linux-x64/resources/app/out/vs/workbench/workbench.desktop.main.css&amp;quot;

cat &amp;amp;gt;&amp;amp;gt; &amp;quot;$CSS_FILE&amp;quot; &amp;amp;lt;&amp;amp;lt; &amp;#39;EOF&amp;#39;
.menubar-menu-title{font-size:23px!important}
.menubar&amp;amp;gt;.menubar-menu-button{font-size:23px!important}
.monaco-menu-option{font-size:22px!important;line-height:34px!important}
.monaco-menu .action-label:not(.codicon){font-size:22px!important}
.menubar-menu-items-holder .monaco-menu .action-item .action-label{font-size:22px!important}
EOF&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सत्यनिष्ठा_चेतावनी_हटाएँ&amp;quot;&amp;gt;सत्यनिष्ठा चेतावनी हटाएँ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;VS Code अपने फ़ाइलों में हुए परिवर्तनों का पता लगाता है और एक बैनर प्रदर्शित करता है &amp;quot;Your installation is corrupt&amp;quot;। इससे बचने के लिए, हम चेकसम हटा देते हैं`product.json`:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-python hljs&amp;quot; data-lang=&amp;quot;python&amp;quot;&amp;gt;import json
product_json = &amp;quot;$HOME/apps/VSCode-linux-x64/resources/app/product.json&amp;quot;
with open(product_json, &amp;#39;r&amp;#39;) as f:
    data = json.load(f)
data.pop(&amp;#39;checksums&amp;#39;, None)
with open(product_json, &amp;#39;w&amp;#39;) as f:
    json.dump(data, f, indent=2)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;रीस्टार्ट के बाद, कोई चेतावनी नहीं रहती और मेनू अंततः पढ़ने योग्य हो जाते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_एक्सप्लोरर_पैनल_का_फ़ॉन्ट_कस्टमाइज़_करें_लड़ाई&amp;quot;&amp;gt;एक्सप्लोरर पैनल का फ़ॉन्ट कस्टमाइज़ करें — लड़ाई&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_टेंटेटिव1_ऐसा_पैरामीटर_जो_नहीं_मौजूद_है&amp;quot;&amp;gt;टेंटेटिव 1: ऐसा पैरामीटर जो नहीं मौजूद है&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पहले हम स्वाभाविक पैरामीटर का प्रयास करते हैं`workbench.tree.fontSize`में`settings.json`:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-json hljs&amp;quot; data-lang=&amp;quot;json&amp;quot;&amp;gt;{
    &amp;quot;workbench.tree.fontSize&amp;quot;: 20
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;परिणाम :&amp;lt;strong&amp;gt;कोई प्रभाव नहीं&amp;lt;/strong&amp;gt;. यह सेटिंग VS Code में मौजूद नहीं है। इसका सबूत यह है कि अनमान्य सेटिंग्स चुपचाप अनदेखी कर दिए जाते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_प्रयास_2_एक्सटेंशन_custom_css_and_js_loader&amp;quot;&amp;gt;प्रयास 2 : एक्सटेंशन Custom CSS and JS Loader&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हम एक्सटेंशन इंस्टॉल करते हैं`be5invis.vscode-custom-css`:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;~/apps/VSCode-linux-x64/bin/code --install-extension be5invis.vscode-custom-css&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हम एक CSS फ़ाइल बनाते हैं`~/.vscode-custom-css/custom.css`एक्सप्लोरर के तत्वों को लक्षित करने वाले चयनकर्ताओं के साथ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-css hljs&amp;quot; data-lang=&amp;quot;css&amp;quot;&amp;gt;.monaco-tree-rows .monaco-tree-row,
.sidebar .monaco-list-row,
.explorer-viewlet .monaco-list-row,
.monaco-list-row .monaco-icon-label {
    font-size: 22px !important;
    line-height: 36px !important;
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;और हम इस फ़ाइल को सेटिंग्स में संदर्भित करते हैं :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-json hljs&amp;quot; data-lang=&amp;quot;json&amp;quot;&amp;gt;{
    &amp;quot;vscode_custom_css.imports&amp;quot;: [
        &amp;quot;file:///home/user/.vscode-custom-css/custom.css&amp;quot;
    ]
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;परिणाम :&amp;lt;strong&amp;gt;परिवर्तन लागू नहीं होते.&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_जाल_हर_बार_एक्सटेंशन_को_सक्रिय_करना_होगा&amp;quot;&amp;gt;जाल: हर बार एक्सटेंशन को सक्रिय करना होगा&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक्सटेंशन की दस्तावेज़ीकरण इस महत्वपूर्ण बिंदु पर चुप है: प्रत्येक कस्टम CSS संशोधन के बाद, आपको यह करना होगा&amp;lt;strong&amp;gt;अनिवार्य रूप से&amp;lt;/strong&amp;gt;कमांड चलाएँ पैलेट से :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;Ctrl+Shift+P&amp;lt;/code&amp;gt;→ टाइप करना&amp;lt;strong&amp;gt;कस्टम CSS और JS सक्षम करें&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;VS Code को रीस्टार्ट की आवश्यकता है → स्वीकार करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस चरण के बिना, सीएसएस कभी भी IDE में इंजेक्ट नहीं किया जाता।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_प्रयास_3_रेखाएँ_ओवरलैप_होती_हैं&amp;quot;&amp;gt;प्रयास 3: रेखाएँ ओवरलैप होती हैं&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;के साथ भी`font-size: 22px` et &amp;lt;code&amp;gt;line-height: 36px&amp;lt;/code&amp;gt;, जैमबेज वाले अक्षर (g, p, f, b) पड़ोस वाली लाइनों पर फैल जाते हैं. हम जोड़ने की कोशिश कर रहे हैं`height` et &amp;lt;code&amp;gt;min-height&amp;lt;/code&amp;gt;:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-css hljs&amp;quot; data-lang=&amp;quot;css&amp;quot;&amp;gt;.monaco-list-row {
    height: 36px !important;
    min-height: 36px !important;
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;परिणाम :&amp;lt;strong&amp;gt;कोई बदलाव नहीं&amp;lt;/strong&amp;gt;. VS Code JavaScript में लाइनों की ऊँचाइयाँ गणना करता है और CSS मानों को ओवरराइड करता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_समाधान_zoom_मातृ_कंटेनर_पर&amp;quot;&amp;gt;समाधान : &amp;lt;code&amp;gt;zoom&amp;lt;/code&amp;gt; मातृ कंटेनर पर&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 5) ]

@startuml
skinparam backgroundColor #FEFEFE

rectangle &amp;quot;प्रयास 1
पैरामीटर मौजूद नहीं है&amp;quot; #LightCoral {
^^^^^
 Syntax Error? (Assumed diagram type: activity)

@startuml
skinparam backgroundColor #FEFEFE

rectangle &amp;quot;प्रयास 1
पैरामीटर मौजूद नहीं है&amp;quot; #LightCoral {
    card &amp;quot;workbench.tree.fontSize&amp;quot; as t1 {
        [VS Code ignore le paramètre]
    }
}

rectangle &amp;quot;प्रयास 2
कस्टम CSS + फ़ॉन्ट-आकार&amp;quot; #LightYellow {
    card &amp;quot;.monaco-list-row { font-size: 22px }&amp;quot; as t2 {
        [Texte plus grand\nmais lignes superposées]
    }
}

rectangle &amp;quot;अस्थायी 3
font-size + line-height + height&amp;quot; #LightYellow {
    card &amp;quot;height: 36px !important&amp;quot; as t3 {
        [VS Code override\npar JavaScript]
        [Aucun effet]
    }
}

rectangle &amp;quot;समाधान
पैरेंट कंटेनर पर ज़ूम&amp;quot; #LightGreen {
    card &amp;quot;.monaco-list-rows { zoom: 1.25 }&amp;quot; as t4 {
        [Texte + espacement\nproportionnels]
        [Layout JS respecté]
        [✓ Résultat conforme]
    }
}

t1 -down-&amp;amp;gt; t2 : Pas de paramètre ?\nOn essaie le CSS
t2 -down-&amp;amp;gt; t3 : Lignes superposées ?\nOn force la hauteur
t3 -down-&amp;amp;gt; t4 : Override JS ?\nOn utilise zoom

@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;JavaScript लेआउट के खिलाफ लड़ने के बजाय, हम प्रॉपर्टी का उपयोग करते हैं`zoom`लाइनों के कंटेनर पर :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-css hljs&amp;quot; data-lang=&amp;quot;css&amp;quot;&amp;gt;.explorer-viewlet .monaco-list-rows,
.sidebar .monaco-list-rows {
    zoom: 1.25;
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;`zoom`समान रूप से कंटेनर का रेंडर बढ़ाता है — टेक्स्ट और स्पेसिंग — VS Code के JavaScript इंजन द्वारा गणना किए गए लेआउट को तोड़े बिना। 1.25 का कारक लगभग 13px से 16px के परिवर्तन के अनुरूप है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;परिणाम :&amp;lt;strong&amp;gt;फ़ाइल के नाम अंततः पढ़ने योग्य हैं, लाइनें सही अंतराल वाली हैं&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सेलेक्टर्स_का_सारांश_और_क्या_काम_करता_है&amp;quot;&amp;gt;सेलेक्टर्स का सारांश और क्या काम करता है&amp;lt;/h3&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 50%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;पहुँच&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;CSS&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;परिणाम&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;font-size`पर&amp;lt;/code&amp;gt;.monaco-list-row`&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;font-size: 22px !important&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;बड़ा पाठ लेकिन रेखाएँ अ overlap&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;line-height&amp;lt;/code&amp;gt;+&amp;lt;code&amp;gt;height`पर&amp;lt;/code&amp;gt;.monaco-list-row`&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;line-height: 36px; height: 36px&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;कोई प्रभाव नहीं (override JS)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;zoom`पर&amp;lt;/code&amp;gt;.monaco-list-rows`&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;zoom: 1.25&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;सफल — पाठ + अनुपातिक अंतराल&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_ऑटोमैटिक_अपडेट_स्क्रिप्ट&amp;quot;&amp;gt;ऑटोमैटिक अपडेट स्क्रिप्ट&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 5) ]

@startuml
skinparam backgroundColor #FEFEFE
autonumber

actor &amp;quot;डेवलपर
^^^^^
 Syntax Error? (Assumed diagram type: sequence)

@startuml
skinparam backgroundColor #FEFEFE
autonumber

actor &amp;quot;डेवलपर
या cron&amp;quot; as dev
participant &amp;quot;vscode-update.sh&amp;quot; as script
participant &amp;quot;VSCode टैरबॉल\n(code.visualstudio.com)&amp;quot; as remote
participant &amp;quot;~/apps/\nVSCode-linux-x64&amp;quot; as local
participant &amp;quot;~/apps/
vscode-backup&amp;quot; as backup
participant &amp;quot;कार्य बेंच
.desktop.main.css&amp;quot; as css
participant &amp;quot;product.json&amp;quot; as product

dev -&amp;amp;gt; script : ./vscode-update.sh
script -&amp;amp;gt; local : Lire version courante
script -&amp;amp;gt; remote : wget dernière version
script -&amp;amp;gt; script : Comparer versions

alt Version identique
    script --&amp;amp;gt; dev : &amp;quot;पहले से ही अपडेट!&amp;quot;
else Nouvelle version
    script -&amp;amp;gt; backup : Sauvegarder installation courante\n(horodatée)
    script -&amp;amp;gt; local : rm -rf ancienne installation
    script -&amp;amp;gt; local : mv nouvelle installation
    script -&amp;amp;gt; css : Ajouter patch CSS\n(menubar 23px, dropdown 22px)
    script -&amp;amp;gt; product : Supprimer checksums\n(python3)
    script --&amp;amp;gt; dev : &amp;quot;अपडेट पूरा\n1.xx.yy → 1.zz.ww&amp;quot;
end note
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_समस्या&amp;quot;&amp;gt;समस्या&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जब VS Code अपडेट होता है, तो यह इंस्टॉलेशन फ़ोल्डर को बदल देता है और&amp;lt;strong&amp;gt;सभी CSS पैच हटाएँ&amp;lt;/strong&amp;gt;&amp;amp;gt;. इसे हर बार हाथ से फिर से लागू करना आवश्यक है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_स्क्रिप्ट_vscode_update_sh&amp;quot;&amp;gt;स्क्रिप्ट `vscode-update.sh&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हम बनाते हैं`~/apps/vscode-update.sh`:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;#!/bin/bash
set -e

VSCODE_DIR=&amp;quot;$HOME/apps/VSCode-linux-x64&amp;quot;
BACKUP_DIR=&amp;quot;$HOME/apps/vscode-backup&amp;quot;
TEMP_DIR=&amp;quot;/tmp/vscode-update&amp;quot;

MENUBAR_FONT_SIZE=&amp;quot;23px&amp;quot;
DROPDOWN_FONT_SIZE=&amp;quot;22px&amp;quot;

echo &amp;quot;=== VS Code Local Updater ===&amp;quot;

CURRENT_VERSION=$(&amp;quot;$VSCODE_DIR/bin/code&amp;quot; --version 2&amp;amp;gt;/dev/null | head -1)
echo &amp;quot;Current version: $CURRENT_VERSION&amp;quot;

echo &amp;quot;Downloading latest VS Code...&amp;quot;
mkdir -p &amp;quot;$TEMP_DIR&amp;quot;
wget -q &amp;quot;https://code.visualstudio.com/sha/download?build=stable&amp;amp;amp;os=linux-x64&amp;quot; \
    -O &amp;quot;$TEMP_DIR/vscode.tar.gz&amp;quot;

echo &amp;quot;Extracting...&amp;quot;
mkdir -p &amp;quot;$TEMP_DIR/extracted&amp;quot;
tar -xzf &amp;quot;$TEMP_DIR/vscode.tar.gz&amp;quot; -C &amp;quot;$TEMP_DIR/extracted&amp;quot;

NEW_VERSION=$(&amp;quot;$TEMP_DIR/extracted/VSCode-linux-x64/bin/code&amp;quot; \
    --version 2&amp;amp;gt;/dev/null | head -1)
echo &amp;quot;New version: $NEW_VERSION&amp;quot;

if [ &amp;quot;$CURRENT_VERSION&amp;quot; = &amp;quot;$NEW_VERSION&amp;quot; ]; then
    echo &amp;quot;Already up to date!&amp;quot;
    rm -rf &amp;quot;$TEMP_DIR&amp;quot;
    exit 0
fi

echo &amp;quot;Backing up current installation...&amp;quot;
mkdir -p &amp;quot;$BACKUP_DIR&amp;quot;
cp -r &amp;quot;$VSCODE_DIR&amp;quot; &amp;quot;$BACKUP_DIR/VSCode-linux-x64-$(date +%Y%m%d-%H%M%S)&amp;quot;

echo &amp;quot;Updating...&amp;quot;
rm -rf &amp;quot;$VSCODE_DIR&amp;quot;
mv &amp;quot;$TEMP_DIR/extracted/VSCode-linux-x64&amp;quot; &amp;quot;$VSCODE_DIR&amp;quot;
rm -rf &amp;quot;$TEMP_DIR&amp;quot;

CSS_FILE=&amp;quot;$VSCODE_DIR/resources/app/out/vs/workbench/workbench.desktop.main.css&amp;quot;
echo &amp;quot;Re-applying custom CSS patch \
    (menubar=${MENUBAR_FONT_SIZE}, dropdown=${DROPDOWN_FONT_SIZE})...&amp;quot;
cat &amp;amp;gt;&amp;amp;gt; &amp;quot;$CSS_FILE&amp;quot; &amp;amp;lt;&amp;amp;lt; CSSEOF
.menubar-menu-title{font-size:${MENUBAR_FONT_SIZE}!important}\
.menubar&amp;amp;gt;.menubar-menu-button{font-size:${MENUBAR_FONT_SIZE}!important}\
.monaco-menu-option{font-size:${DROPDOWN_FONT_SIZE}!important;\
line-height:34px!important}\
.monaco-menu .action-label:not(.codicon)\
{font-size:${DROPDOWN_FONT_SIZE}!important}\
.menubar-menu-items-holder .monaco-menu .action-item .action-label\
{font-size:${DROPDOWN_FONT_SIZE}!important}
CSSEOF

PRODUCT_JSON=&amp;quot;$VSCODE_DIR/resources/app/product.json&amp;quot;
if [ -f &amp;quot;$PRODUCT_JSON&amp;quot; ]; then
    echo &amp;quot;Removing checksums to prevent integrity warning...&amp;quot;
    python3 -c &amp;quot;
import json
with open(&amp;#39;$PRODUCT_JSON&amp;#39;,&amp;#39;r&amp;#39;) as f: data=json.load(f)
data.pop(&amp;#39;checksums&amp;#39;, None)
with open(&amp;#39;$PRODUCT_JSON&amp;#39;,&amp;#39;w&amp;#39;) as f: json.dump(data,f,indent=2)
print(&amp;#39;Done.&amp;#39;)
&amp;quot;
fi

echo &amp;quot;=== Update complete: $CURRENT_VERSION -&amp;amp;gt; $NEW_VERSION ===&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;स्क्रिप्ट :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;लेटेस्ट स्थिर संस्करण डाउनलोड करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;जाँच करें कि क्या संस्करण वर्तमान से अलग है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;वर्तमान स्थापना (समयांकित) में सहेजें`~/apps/vscode-backup/`&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;इंस्टॉलेशन फ़ोल्डर बदलें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;फिर से लागू करें&amp;lt;/strong&amp;gt;मुख्य मेनू का CSS पैच&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Supprime les checksums&amp;lt;/strong&amp;gt; de `product.json`अखंडता चेतावनी से बचने के लिए&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;Note&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
कस्टमाइज़ेशन एक्सप्लोरर पैन का Custom CSS एक्सटेंशन के माध्यम से और फ़ाइल`~/.vscode-custom-css/custom.css`वे अपडेट के कारण बच जाते हैं क्योंकि वे इंस्टॉलेशन फ़ोल्डर के बाहर रहते हैं।
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_संबंधित_फाइलें_अवलोकन&amp;quot;&amp;gt;संबंधित फाइलें — अवलोकन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 6) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

rectangle &amp;quot;VS Code की स्थापना
(~/apps/VSCode-linux-x64/)&amp;quot; #LightCoral {
^^^^^
 Syntax Error? (Assumed diagram type: activity)

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

rectangle &amp;quot;VS Code की स्थापना
(~/apps/VSCode-linux-x64/)&amp;quot; #LightCoral {
    component &amp;quot;workbench.desktop\n.main.css&amp;quot; as css #LightCoral
    component &amp;quot;product.json&amp;quot; as product #LightCoral
    component &amp;quot;बाइनरी
bin/code&amp;quot; as binary #LightCoral
}

rectangle &amp;quot;उपयोगकर्ता कॉन्फ़िगरेशन
(~/.config/Code/)&amp;quot; #LightGreen {
    component &amp;quot;settings.json&amp;quot; as settings #LightGreen
    component &amp;quot;एक्सटेंशन/&amp;quot; as extensions #LightGreen
}

rectangle &amp;quot;स्थायी अनुकूलन
(~/.vscode-custom-css/)&amp;quot; #SkyBlue {
    component &amp;quot;custom.css\n(zoom: 1.25)&amp;quot; as customcss #SkyBlue
}

rectangle &amp;quot;स्वचालन
(~/apps/)&amp;quot; #LightYellow {
    component &amp;quot;vscode-update.sh&amp;quot; as script #LightYellow
    component &amp;quot;vscode-backup/&amp;quot; as backup #LightYellow
}

script ..&amp;amp;gt; css : Re-patch après MAJ
script ..&amp;amp;gt; product : Supprime checksums\naprès MAJ
settings --&amp;amp;gt; customcss : Référence via\nvscode_custom_css.imports
extensions ..&amp;amp;gt; css : Custom CSS Loader\ninjecte custom.css

note bottom of css
  **Ne survit pas** aux mises à jour
  Re-patché par le script
end note

note bottom of customcss
  **Survit** aux mises à jour
  Vit hors du dossier d&amp;#39;installation
end note

note bottom of settings
  **Survit** aux mises à jour
  Vit dans ~/.config/
end note
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 28.5714%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 42.8571%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 28.5715%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;पथ&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;भूमिका&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;अपडेट्स से जीवित रहता है?&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;~/apps/VSCode-linux-x64/&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;IDE की स्थापना&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;नहीं (बदली गई)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;~/apps/VSCode-linux-x64/resources/app/out/vs/workbench/workbench.desktop.main.css&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;वर्कबेंच CSS (मेन्यू, ड्रॉपडाउन)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;नहीं (स्क्रिप्ट द्वारा पुनः पैच किया गया)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;~/apps/VSCode-linux-x64/resources/app/product.json&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;इंटेग्रिटी चेकसम&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;नहीं (स्क्रिप्ट द्वारा फिर से साफ किया गया)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;~/apps/vscode-update.sh&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;स्वचालित अपडेट स्क्रिप्ट&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;हाँ&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;~/.config/Code/User/settings.json&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;उपयोगकर्ता सेटिंग्ज़ (fontSize, custom CSS)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;हाँ&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;~/.vscode-custom-css/custom.css&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक्सप्लोरर के लिए कस्टम CSS (ज़ूम)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;हाँ&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_सीखे_हुए_सबक&amp;quot;&amp;gt;सीखे हुए सबक&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 8) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif
skinparam ArrowColor #444444

rectangle &amp;quot;**स्थानीय स्थापना**\n घर में&amp;quot; as install #LightGreen {
    card &amp;quot;सुडो नहीं
 CSS/config को संशोधित करने के लिए&amp;quot; as i1
^^^^^
 Syntax Error? (Assumed diagram type: activity)

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif
skinparam ArrowColor #444444

rectangle &amp;quot;**स्थानीय स्थापना**\n घर में&amp;quot; as install #LightGreen {
    card &amp;quot;सुडो नहीं
 CSS/config को संशोधित करने के लिए&amp;quot; as i1
    card &amp;quot;opencode+LLM सब कुछ संशोधित कर सकता है&amp;quot; as i2
    card &amp;quot;Rollback = पुनर्स्थापित
 टाइमस्टैम्प्ड बैकअप&amp;quot; as i3
}

rectangle &amp;quot;**CSS का कस्टमाइज़ेशन**
 ज़ूम बनाम फ़ॉन्ट-आकार&amp;quot; as css #LightYellow {
    card &amp;quot;ज़ूम &amp;amp;gt; फ़ॉन्ट-आकार\n घटकों की सूची के लिए&amp;quot; as c1
    card &amp;quot;ले आउट JS ओवरराइड
ऊँचाई/लाइन-ऊँचाई&amp;quot; as c2
    card &amp;quot;Extension Custom CSS
 आवश्यक सक्रियण
 हस्तचालित (Ctrl+Shift+P)&amp;quot; as c3
}

rectangle &amp;quot;**स्वचालन**\n अपडेट स्क्रिप्ट&amp;quot; as auto #LightCoral {
    card &amp;quot;CSS को री-पैच करने के बाद
 प्रत्येक अपडेट&amp;quot; as a1
    card &amp;quot;चेकसम हटाएँ
 product.json&amp;quot; as a2
    card &amp;quot;समय-चिह्नित बैकअप
 प्रतिस्थापन से पहले&amp;quot; as a3
}

install -right-&amp;amp;gt; css : ensuite
css -right-&amp;amp;gt; auto : enfin

note top of install
  Contrôle total sans élévation
  de privilèges
end note

note top of auto
  Sans script, chaque MAJ
  efface les patches CSS
end note
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_होम_में_इंस्टॉल_करने_से_सब_कुछ_मुक्त_हो_जाता_है&amp;quot;&amp;gt;होम में इंस्टॉल करने से सब कुछ मुक्त हो जाता है&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;स्थानीय स्थापना में`~/apps`VS Code पर पूर्ण नियंत्रण देता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;नहीं`sudo`CSS को संशोधित करने या कॉन्फ़िगरेशन को बदलने के लिए&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;opencode+LLM एजेंट IDE के कॉन्फ़िगरेशन फ़ाइलों और एसेट्स में लिख सकता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;साधारण रोलबैक : टाइमस्टैम्प्ड बैकअप पुनर्स्थापित करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_zoom_font_size_सूची_घटकों_के_लिए&amp;quot;&amp;gt;zoom` &amp;amp;gt; &amp;lt;code&amp;gt;font-size&amp;lt;/code&amp;gt; सूची घटकों के लिए&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;VS Code JavaScript के माध्यम से लाइन की ऊँचाई को नियंत्रित करता है। संशोधित करें`font-size`ले�ेआउट इंजन द्वारा आवंटित ऊँचाई को छू पाने में असमर्थ होने से पाठ ओवरफ़्लो हो जाते हैं। गुण`zoom`माता कंटेनर को बड़ा करने से सब कुछ समानुपातिक रूप से बड़ा हो जाता है और इस समस्या को टाल दिया जाता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_custom_css_एक्सटेंशन_को_स्पष्ट_रूप_से_सक्रिय_करने_की_आवश्यकता_है&amp;quot;&amp;gt;Custom CSS एक्सटेंशन को स्पष्ट रूप से सक्रिय करने की आवश्यकता है&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह &amp;lt;code&amp;gt;set and forget&amp;lt;/code&amp;gt; पैरामीटर नहीं है। प्रत्येक कस्टम CSS फ़ाइल में बदलाव करने के लिए &amp;lt;code&amp;gt;Enable Custom CSS and JS&amp;lt;/code&amp;gt; को कमांड पैलेट से फिर से चलाना आवश्यक है। (&amp;lt;code&amp;gt;Ctrl+Shift+P&amp;lt;/code&amp;gt;).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_एक_अपडेट_स्क्रिप्ट_आवश्यक_है&amp;quot;&amp;gt;एक अपडेट स्क्रिप्ट आवश्यक है&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;स्क्रिप्ट के बिना, VS Code के प्रत्येक अपडेट वर्कबेंच के CSS पैच को मिटा देता है। स्क्रिप्ट`vscode-update.sh`डाउनलोड, प्रतिस्थापन, री-पैच और चेकसम्स की सफ़ाई को स्वचालित करता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_त्वरित_संदर्भ&amp;quot;&amp;gt;त्वरित संदर्भ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;VS Code डाउनलोड : &amp;lt;a href=&amp;quot;https://code.visualstudio.com/Download&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://code.visualstudio.com/Download&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एक्सटेंशन कस्टम CSS और JS लोडर :`be5invis.vscode-custom-css`&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;VS Code के द्वारा एक्सप्लोरर फ़ॉन्ट के लिए एक नेटिव सेटिंग मांगे जाने का मुद्दा:https://github.com/microsoft/vscode/issues/149[github.com/microsoft/vscode#149]&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Asciidoctor RevealJS प्लगिन को buildSrc Kotlin में माइग्रेट करना : Groovy API का रिवर्स इंजीनियरिंग</title>
            <link >https://cheroliv.com/blog/2026/0102_migration_gradle_script_to_plugin_post.html</link>
            <pubDate>Thu, 16 Apr 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0102_migration_gradle_script_to_plugin_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संदर्भ_और_उद्देश्य&amp;quot;&amp;gt;संदर्भ और उद्देश्य&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_शुरुआती_बिंदु&amp;quot;&amp;gt;शुरुआती बिंदु&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_लक्ष्य&amp;quot;&amp;gt;लक्ष्य&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पहली_बाधा_ruby_gems&amp;quot;&amp;gt;पहली बाधा : `ruby { gems() }&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ग्रोवी_शुगर_सिंटैक्स_क्या_छिपाता_है&amp;quot;&amp;gt;ग्रोवी शुगर सिंटैक्स क्या छिपाता है&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_मैकेनिज़म_का_विघटन&amp;quot;&amp;gt;मैकेनिज़म का विघटन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_तीन_भागों_का_समाधान&amp;quot;&amp;gt;तीन भागों का समाधान&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_भाग_1_ivy_रेपॉ_rubygems_के_लिए&amp;quot;&amp;gt;भाग 1 : Ivy रेपॉ rubygems के लिए&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_jbake_cli_commands_initialize_a_new_jbake_project_jbake_i&amp;quot;&amp;gt;JBake CLI Commands &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; # Initialize a new JBake project jbake -i&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_generate_the_site_jbake_b&amp;quot;&amp;gt;Bake (generate) the site jbake -b&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_and_serve_locally_jbake_b_s&amp;quot;&amp;gt;Bake and serve locally jbake -b -s&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_and_watch_for_changes_jbake_b_reset&amp;quot;&amp;gt;Bake and watch for changes jbake -b --reset&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_specify_source_and_destination_jbake_source_folder_output_folder&amp;quot;&amp;gt;Specify source and destination jbake source_folder output_folder&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_clear_the_output_directory_before_baking_jbake_b_output_reset&amp;quot;&amp;gt;Clear the output directory before baking jbake -b . output --reset &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_संदर्भ_और_उद्देश्य&amp;quot;&amp;gt;संदर्भ और उद्देश्य&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_शुरुआती_बिंदु&amp;quot;&amp;gt;शुरुआती बिंदु&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;परियोजना`slider-gradle`Gradle प्लग़िन के माध्यम से AsciiDoc फ़ाइलों से Reveal.js प्रजेंटेशन बनाता है`org.asciidoctor.jvm.revealjs`. मुख्य कार्य की कॉन्फ़िगरेशन`asciidoctorRevealJs`वह रूट buildscript में सीधे रहता था`build.gradle.kts`:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;plugins { id(&amp;quot;org.asciidoctor.jvm.revealjs&amp;quot;) }

apply&amp;amp;lt;slides.SlidesPlugin&amp;amp;gt;()

project.tasks.getByName&amp;amp;lt;AsciidoctorJRevealJSTask&amp;amp;gt;(TASK_ASCIIDOCTOR_REVEALJS) {
    repositories { ruby { gems() } }
    revealjs {
        version = &amp;quot;3.1.0&amp;quot;
        templateGitHub {
            setOrganisation(&amp;quot;hakimel&amp;quot;)
            setRepository(&amp;quot;reveal.js&amp;quot;)
            setTag(&amp;quot;3.9.1&amp;quot;)
        }
    }
    revealjsOptions {
        // ... configuration complète
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_लक्ष्य&amp;quot;&amp;gt;लक्ष्य&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस पूरी कॉन्फ़िगरेशन को`buildSrc/src/main/kotlin/slides/SlidesPlugin.kt`कि बिल्डस्क्रिप्ट उपभोक्ता कम हो जाए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;apply&amp;amp;lt;slides.SlidesPlugin&amp;amp;gt;()&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;प्लगिन को पूरी तरह से स्वायत्त होना चाहिए: यह अपने प्लगिन निर्भरताओं को स्वयं लागू करता है, अपने रिपॉज़िटरीज़ को कॉन्फ़िगर करता है, और अपने रूबी जेम्स को प्रबंधित करता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_पहली_बाधा_ruby_gems&amp;quot;&amp;gt;पहली बाधा : `ruby { gems() }&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ग्रोवी_शुगर_सिंटैक्स_क्या_छिपाता_है&amp;quot;&amp;gt;ग्रोवी शुगर सिंटैक्स क्या छिपाता है&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;लाइन`repositories { ruby { gems() } }`यह एक Groovy DSL एक्सटेंशन है जो केवल buildscript के निष्पादन संदर्भ में उपलब्ध है। यह buildSrc से 접근 가능한 स्थिर Kotlin API के रूप में मौजूद नहीं है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इसको फ़ोन करने की कोशिश करते हुए`SlidesPlugin.kt`, संकलन तुरंत असफल हो जाता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_मैकेनिज़म_का_विघटन&amp;quot;&amp;gt;मैकेनिज़म का विघटन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;ग्रेडल कैश का विश्लेषण करने के बाद (&amp;lt;code&amp;gt;~/.gradle/caches/modules-2/files-2.1/rubygems/&amp;lt;/code&amp;gt;), फ़ाइल में हमें पता चलता है`ivy-3.1.0.xml`: (Note: The output should be exactly &amp;quot; : &amp;quot; with a leading space, colon, and trailing space, as per the instruction to translate the fragment and preserve formatting.)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-xml hljs&amp;quot; data-lang=&amp;quot;xml&amp;quot;&amp;gt;&amp;amp;lt;artifact type=&amp;#39;gem&amp;#39; url=&amp;#39;https://rubygems.org/gems/asciidoctor-revealjs-3.1.0.gem&amp;#39; /&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;`ruby { gems() }`वास्तव में कर रहा था&amp;lt;strong&amp;gt;तीन भिन्न संचालन&amp;lt;/strong&amp;gt;:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Enregistrer un repo Ivy pointant vers &amp;lt;code&amp;gt;&amp;lt;a href=&amp;quot;https://rubygems.org/gems/&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://rubygems.org/gems/&amp;lt;/a&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;समूह को बाहर रखें`rubygems`Maven रिपॉजिटरी टकराव से बचने के लिए&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;जेम को कॉन्फ़िगरेशन में सहेजें`asciidoctorGems`जिससे JRuby इसे रनटाइम पर लोड करे&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इन तीन जिम्मेदारियों को कोटलिन में अलग‑अलग रूप से पुन: उत्पन्न किया जाना चाहिए।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_तीन_भागों_का_समाधान&amp;quot;&amp;gt;तीन भागों का समाधान&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_भाग_1_ivy_रेपॉ_rubygems_के_लिए&amp;quot;&amp;gt;भाग 1 : Ivy रेपॉ rubygems के लिए&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;project.repositories.mavenCentral() {
    content { excludeGroup(&amp;quot;rubygems&amp;quot;) }
}
project.repositories.ivy {
    url = project.uri(&amp;quot;https://rubygems.org/gems/&amp;quot;)
    patternLayout { artifact(&amp;quot;[module]-[revision].gem&amp;quot;) } &amp;lt;i class=&amp;quot;conum&amp;quot; data-value=&amp;quot;1&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;b&amp;gt;(1)&amp;lt;/b&amp;gt;
    metadataSources { artifact() }
    content { includeGroup(&amp;quot;rubygems&amp;quot;) }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;colist arabic&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td&amp;gt;&amp;lt;i class=&amp;quot;conum&amp;quot; data-value=&amp;quot;1&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;b&amp;gt;1&amp;lt;/b&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td&amp;gt;एक्सटेंशन`.gem`इसे हार्डकोड किया जाना चाहिए।&amp;lt;code&amp;gt;[ext]`डिफ़ॉल्ट रूप से में हल करता है&amp;lt;/code&amp;gt;.jar`, जिससे एक त्रुटि होती है`Resource missing`.&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_jbake_cli_commands_initialize_a_new_jbake_project_jbake_i&amp;quot;&amp;gt;JBake CLI Commands &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; # Initialize a new JBake project jbake -i&amp;lt;/h3&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;h1 id=&amp;quot;_bake_generate_the_site_jbake_b&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake (generate) the site jbake -b&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_and_serve_locally_jbake_b_s&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake and serve locally jbake -b -s&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_and_watch_for_changes_jbake_b_reset&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake and watch for changes jbake -b --reset&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_specify_source_and_destination_jbake_source_folder_output_folder&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Specify source and destination jbake source_folder output_folder&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_clear_the_output_directory_before_baking_jbake_b_output_reset&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Clear the output directory before baking jbake -b . output --reset &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt;&amp;lt;/h1&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;नोट: आइवी रेपो सीधे घोषित किया गया है पर`project.repositories`और नहीं एक ब्लॉक में`repositories { }`क्योंकि इस ब्लॉक का रिसीवर नहीं है`RepositoryHandler`Gradle का मानक लेकिन एक grolifant API एक्सटेंशन के साथ अनुकूल नहीं`ivy`&amp;lt;mark&amp;gt;#&amp;lt;/mark&amp;gt; Gradle Integration JBake को Gradle बिल्ड में JBake Gradle प्लगइन का उपयोग करके या JBake CLI को सीधे बुलाकर एकीकृत किया जा सकता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;----
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
}

=== भाग 2: निर्भरता asciidoctorGems

प्लगइन`org.asciidoctor.jvm.gems`इसे पहले लागू किया जाना चाहिए — यह कॉन्फ़िगरेशन बनाता है`asciidoctorGems`और कार्य`asciidoctorGemsPrepare`:

[source,kotlin]
----
project.plugins.apply(&amp;quot;org.asciidoctor.jvm.gems&amp;quot;)
project.plugins.apply(&amp;quot;org.asciidoctor.jvm.revealjs&amp;quot;) &amp;lt;i class=&amp;quot;conum&amp;quot; data-value=&amp;quot;1&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;b&amp;gt;(1)&amp;lt;/b&amp;gt;

project.dependencies {
    add(&amp;quot;asciidoctorGems&amp;quot;, &amp;quot;rubygems:asciidoctor-revealjs:3.1.0@gem&amp;quot;) &amp;lt;i class=&amp;quot;conum&amp;quot; data-value=&amp;quot;2&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;b&amp;gt;(2)&amp;lt;/b&amp;gt;
}
----

&amp;amp;lt;1&amp;amp;gt; लागू करने का क्रम महत्वपूर्ण है :
### JBake CLI कमांड
----

# एक नया JBake प्रोजेक्ट प्रारंभ करें jbake -i

# बेक (जेनरेट) साइट jbake -b

# बेक और स्थानीय रूप से परोसें jbake -b -s

# बेक और बदलावों की निगरानी करें jbake -b --reset

# स्रोत और गंतव्य निर्दिष्ट करें jbake source_folder output_folder

# बेकिंग से पहले आउटपुट निर्देशिका साफ़ करें jbake -b . output --reset`gems`पहले`revealjs`. &amp;amp;lt;2&amp;amp;gt; योग्यकर्ता`@gem`निर्भरता पर सही एक्सटेंशन बल दें।

=== भाग 3 : settings.gradle.kts

`dependencyResolutionManagement`में`settings.gradle.kts`इसे परियोजनाओं को अपने स्वयं के रिपॉज़िटरी की घोषणा करने की अनुमति देनी चाहिए :

[source,kotlin]
----
@Suppress(&amp;quot;UnstableApiUsage&amp;quot;)
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.PREFER_PROJECT)
}
----

इसी पंक्ति के बिना, Gradle प्लगइन में घोषित रिपॉज़िटरी को अनदेखा करता है और gems का समाधान विफल हो जाता है।

== बाइटकोड्स द्वारा API का आत्मनिरीक्षण

=== क्यों `javap` ?

प्लगइन`asciidoctor-gradle-jvm-slides` est en version `4.0.0-alpha.1`. उसका दस्तावेज़ अस्तित्वहीन या अपूर्ण है। एकमात्र विश्वसनीय स्रोत संकलित क्लासेस की प्रत्यक्ष जाँच है।

=== कार्य का पदानुक्रम

[source,bash]
----
javap -p -classpath asciidoctor-gradle-jvm-slides-4.0.0-alpha.1.jar \
  org.asciidoctor.gradle.jvm.slides.AsciidoctorJRevealJSTask
----

परिणाम :

[source]
----
public class AsciidoctorJRevealJSTask
  extends org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask
  implements org.asciidoctor.gradle.base.slides.SlidesToExportAware
----

=== की खोज `forkOptions

निरीक्षण करते हुए.

&amp;amp;lt;/think&amp;amp;gt;

निरीक्षण करते हुए`AbstractAsciidoctorTask`:

[source,bash]
----
javap -p -classpath asciidoctor-gradle-jvm-4.0.0-alpha.1.jar \
  org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask | grep -i &amp;quot;fork\|exec\|jvm&amp;quot;
----

पाया जाता है:

[source]
----
final org.ysb33r.grolifant.api.v4.JavaForkOptions javaForkOptions;
public void forkOptions(org.gradle.api.Action&amp;amp;lt;org.ysb33r.grolifant.api.v4.JavaForkOptions&amp;amp;gt;);
public static final org.asciidoctor.gradle.base.process.ProcessMode JAVA_EXEC;
----

=== JavaForkOptions की एपीआई (grolifant)

`javaLauncher`इस कार्य पर मौजूद नहीं है। वास्तविक API का`org.ysb33r.grolifant.api.v4.JavaForkOptions`दिखाता है :

[source]
----
public void executable(java.lang.Object);  &amp;lt;i class=&amp;quot;conum&amp;quot; data-value=&amp;quot;1&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;b&amp;gt;(1)&amp;lt;/b&amp;gt;
public void setExecutable(java.lang.Object);
----

&amp;amp;lt;1&amp;amp;gt; पद्धति`executable(Object)`असाइनमेंट को बदलता है`executable = ...`जो कंपाइल नहीं होता (`val`पुन: आवंटित नहीं किया जा सकता).

=== RevealJSExtension

`revealjs { }`कार्य की एक विधि नहीं है, लेकिन एक**परियोजना विस्तार**:

[source,bash]
----
javap -p -classpath asciidoctor-gradle-jvm-slides-4.0.0-alpha.1.jar \
  org.asciidoctor.gradle.jvm.slides.RevealJSExtension
----

इस तक पहुँचा जाता है:

[source,kotlin]
----
project.extensions.getByType&amp;amp;lt;RevealJSExtension&amp;amp;gt;().apply {
    version = &amp;quot;3.1.0&amp;quot;
    templateGitHub {
        setOrganisation(&amp;quot;hakimel&amp;quot;)
        setRepository(&amp;quot;reveal.js&amp;quot;)
        setTag(&amp;quot;3.9.1&amp;quot;)
    }
}
----

== जावा टूलचेन कॉन्फ़िगरेशन

=== JavaToolchainService की समस्या

`JavaToolchainService`यह प्रोजेक्ट एक्सटेंशन नहीं है। निम्नलिखित कॉल विफल होता है :

[source,kotlin]
----
// ERREUR : Extension of type &amp;#39;JavaToolchainService&amp;#39; does not exist
project.extensions.getByType&amp;amp;lt;JavaToolchainService&amp;amp;gt;()
----

अच्छी API है`serviceOf`:

[source,kotlin]
----
import org.gradle.kotlin.dsl.support.serviceOf

project.tasks.getByName&amp;amp;lt;AsciidoctorJRevealJSTask&amp;amp;gt;(TASK_ASCIIDOCTOR_REVEALJS) {
    setInProcess(&amp;quot;JAVA_EXEC&amp;quot;)
    forkOptions {
        executable(
            project.serviceOf&amp;amp;lt;JavaToolchainService&amp;amp;gt;()
                .launcherFor {
                    languageVersion.set(JavaLanguageVersion.of(17))
                    vendor.set(JvmVendorSpec.ADOPTIUM)
                }
                .get()
                .executablePath
                .asFile
                .absolutePath
        )
    }
}
----

== स्वचालित डॉकर का पता लगाना

=== संदर्भ

Asciidoctor/JRuby प्लगिन को Java 17 की आवश्यकता है। Kotlin 2.0.x बिल्डSrc में Java 25 का समर्थन नहीं करता (वर्ज़न पार्सर क्रैश हो जाता है पर`&amp;quot;25.0.2&amp;quot;`Gradle डेमन को इसलिए Java 17 पर चलना चाहिए या Docker का उपयोग किया जाना चाहिए।

=== रणनीति

1. Docker उपलब्ध → कंटेनर के माध्यम से निष्पादन`eclipse-temurin:17`(डिफ़ॉल्ट व्यवहार)
2. Docker अनुपस्थित + Java 17 → स्थानीय निष्पादन
3. Docker अनुपस्थित + Java &amp;amp;gt; 17 → स्पष्ट त्रुटि

[source,kotlin]
----
val isDockerAvailable = try {
    Runtime.getRuntime().exec(arrayOf(&amp;quot;docker&amp;quot;, &amp;quot;info&amp;quot;)).waitFor() == 0
} catch (e: Exception) {
    false
}

val javaVersion = JavaVersion.current().majorVersion.toInt()

when {
    isDockerAvailable -&amp;amp;gt; project.tasks.register&amp;amp;lt;Exec&amp;amp;gt;(TASK_ASCIIDOCTOR_REVEALJS) {
        group = GROUP_TASK_SLIDER
        description = &amp;quot;Slider settings and generation (via Docker)&amp;quot;
        dependsOn(TASK_CLEAN_SLIDES_BUILD)
        finalizedBy(TASK_DASHBOARD_SLIDES_BUILD)
        commandLine(
            &amp;quot;docker&amp;quot;, &amp;quot;run&amp;quot;, &amp;quot;--rm&amp;quot;,
            &amp;quot;-v&amp;quot;, &amp;quot;${project.rootDir.absolutePath}:/workspace&amp;quot;,
            &amp;quot;-v&amp;quot;, &amp;quot;${System.getProperty(&amp;quot;user.home&amp;quot;)}/.gradle:/root/.gradle&amp;quot;,
            &amp;quot;-w&amp;quot;, &amp;quot;/workspace&amp;quot;,
            &amp;quot;eclipse-temurin:17&amp;quot;,
            &amp;quot;./gradlew&amp;quot;, TASK_ASCIIDOCTOR_REVEALJS
        )
        workingDir = project.rootDir
    }
    javaVersion == 17 -&amp;amp;gt; {
        project.repositories.mavenCentral() {
            content { excludeGroup(&amp;quot;rubygems&amp;quot;) }
        }
        project.repositories.ivy {
            url = project.uri(&amp;quot;https://rubygems.org/gems/&amp;quot;)
            patternLayout { artifact(&amp;quot;[module]-[revision].gem&amp;quot;) }
            metadataSources { artifact() }
            content { includeGroup(&amp;quot;rubygems&amp;quot;) }
        }
        project.extensions.getByType&amp;amp;lt;RevealJSExtension&amp;amp;gt;().apply {
            version = &amp;quot;3.1.0&amp;quot;
            templateGitHub {
                setOrganisation(&amp;quot;hakimel&amp;quot;)
                setRepository(&amp;quot;reveal.js&amp;quot;)
                setTag(&amp;quot;3.9.1&amp;quot;)
            }
        }
        project.tasks.getByName&amp;amp;lt;AsciidoctorJRevealJSTask&amp;amp;gt;(TASK_ASCIIDOCTOR_REVEALJS) {
            setInProcess(&amp;quot;JAVA_EXEC&amp;quot;)
            forkOptions {
                executable(
                    project.serviceOf&amp;amp;lt;JavaToolchainService&amp;amp;gt;()
                        .launcherFor {
                            languageVersion.set(JavaLanguageVersion.of(17))
                            vendor.set(JvmVendorSpec.ADOPTIUM)
                        }
                        .get()
                        .executablePath
                        .asFile
                        .absolutePath
                )
            }
            // ... reste de la configuration
        }
    }
    else -&amp;amp;gt; error(
        &amp;quot;Docker est requis pour exécuter $TASK_ASCIIDOCTOR_REVEALJS &amp;quot; +
        &amp;quot;avec Java $javaVersion. Installez Docker ou utilisez Java 17.&amp;quot;
    )
}
----

== अंतिम परिणाम

=== भोक्ता बिल्डस्क्रिप्ट

[source,kotlin]
----
apply&amp;amp;lt;slides.SlidesPlugin&amp;amp;gt;()
----

इतना ही। प्लगिन पूरी जिम्मेदारी लेता है।

=== settings.gradle.kts

[source,kotlin]
----
pluginManagement {
    repositories {
        mavenLocal()
        gradlePluginPortal()
    }
}

plugins {
    id(&amp;quot;org.gradle.toolchains.foojay-resolver-convention&amp;quot;) version &amp;quot;0.8.0&amp;quot;
}

@Suppress(&amp;quot;UnstableApiUsage&amp;quot;)
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.PREFER_PROJECT)
}

rootProject.name = &amp;quot;slider-gradle&amp;quot;
----

== जाल और समाधानों का सारांश

[cols=&amp;quot;2,3,3&amp;quot;]
|===
|समस्या |कारण |समाधान

|`ruby { gems() }`Kotlin में उपलब्ध नहीं |केवल Groovy DSL एक्सटेंशन |तीन अलग‑अलग तंत्र : Ivy रेपो + Maven बहिष्करण +`asciidoctorGems` |Gradle एक की खोज कर रहा है`.jar`एक के बजाय`.gem` |`[ext]`हल करता है से`jar`डिफ़फ़ॉल्ट रूप से |Hardcoder`.gem`इवी पैटर्न में + योग्यता`@gem` |`ivy { }`में कंपाइल नहीं होता`repositories { }` |रिसीवर grolifant Kotlin DSL के साथ असंगत |सीधी कॉल`project.repositories.ivy { }` |`javaLauncher`अनसुलझा |अस्तित्वहीन गुणधर्म पर`AsciidoctorJRevealJSTask` |`setInProcess(&amp;quot;JAVA_EXEC&amp;quot;)`+`forkOptions { executable(...) }` |`executable = ...`कंपाइल नहीं होता |संपत्ति`val`में`JavaForkOptions`grolifant |पद्धति`executable(Object)`के स्थान पर |`JavaToolchainService`के माध्यम से नहीं मिला`extensions` |यह Gradle का एक सेवा है, एक एक्सटेंशन नहीं |`project.serviceOf&amp;amp;lt;JavaToolchainService&amp;amp;gt;()` |`revealjs { }`कार्य में हल नहीं |परियोजना विस्तार, कार्य की विधि नहीं |`project.extensions.getByType&amp;amp;lt;RevealJSExtension&amp;amp;gt;()` |बिल्ड Java 25 के साथ क्रैश होती है |Kotlin 2.0.x दो अंकों वाले Java संस्करणों को पार्स नहीं करता |स्वचालित Docker पहचान + Java 17 का फॉलबैक
|===

== जाँच की विधि : अज्ञात API को javap के साथ पढ़ना

=== सिद्धांत

जब दस्तावेज़ अनुपलब्ध या अधूरा हो, तब बाइटकोड सत्य का स्रोत होता है। `javap`यह JDK का मानक टूल है जो फ़ाइलों को डीकंपाइल करता है`.class` en signatures Java lisibles, स्रोत कोड की आवश्यकता नहीं

=== चरण 1: Gradle कैश में jar को खोजें

Gradle सभी अपनी निर्भरताओं को डाउनलोड करता है में`~/.gradle/caches/modules-2/files-2.1/`. पहला कदम वह jar खोजना है जिसमें जाँचने के लिए क्लास मौजूद है:

[source,bash]
----
find ~/.gradle/caches -name &amp;quot;asciidoctor-gradle-jvm-slides*.jar&amp;quot; 2&amp;amp;gt;/dev/null
----

.परिणाम :

[source]
----
/home/user/.gradle/caches/modules-2/files-2.1/org.asciidoctor/
asciidoctor-gradle-jvm-slides/4.0.0-alpha.1/.../
asciidoctor-gradle-jvm-slides-4.0.0-alpha.1.jar
----

=== चरण 2 : jar की कक्षाओं की सूची बनाएं

क्लास का निरीक्षण करने से पहले, हम जाँचते हैं कि यह jar में वास्तव में मौजूद है:

[source,bash]
----
jar tf asciidoctor-gradle-jvm-slides-4.0.0-alpha.1.jar | grep -i &amp;quot;RevealJS\|revealjs&amp;quot;
----

.यह सभी उपलब्ध वर्गों को प्रकट करता है : `AsciidoctorJRevealJSTask`, `RevealJSExtension`, `RevealJSOptions`, etc.

=== चरण 3 : एक कक्षा का निरीक्षण करें

[source,bash]
----
javap -p -classpath asciidoctor-gradle-jvm-slides-4.0.0-alpha.1.jar \
org.asciidoctor.gradle.jvm.slides.AsciidoctorJRevealJSTask
----

विकल्प`-p`सभी सदस्यों को प्रदर्शित करता है, निजी सदस्यों सहित। परिणाम तुरंत मुख्य पंक्ति दिखाता है :

[source]
----
public class AsciidoctorJRevealJSTask
extends org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask
----

=== चरण 4 : पदानुक्रम में ऊपर उठना

कार्य विस्तृत होता है`AbstractAsciidoctorTask`. इसे उसकी बारी पर निरीक्षण किया जाता है पहले उसके जार को खोजते हुए :

[source,bash]
----
find ~/.gradle/caches -name &amp;quot;asciidoctor-gradle-jvm-[0-9]*.jar&amp;quot; 2&amp;amp;gt;/dev/null

javap -p -classpath asciidoctor-gradle-jvm-4.0.0-alpha.1.jar \
org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask | grep -i &amp;quot;fork\|exec\|jvm\|java&amp;quot;
----

वही पता चलता है।`forkOptions`, `JAVA_EXEC`, et `javaForkOptions` de type `org.ysb33r.grolifant.api.v4.JavaForkOptions`.

=== चरण 5: अज्ञात प्रकारों का पालन करें

`JavaForkOptions`एक अज्ञात गrolifant कक्षा है। हम इसके jar को खोजते हैं :

[source,bash]
----
find ~/.gradle/caches -name &amp;quot;grolifant*.jar&amp;quot; 2&amp;amp;gt;/dev/null
----

फिर हम इसकी जाँच करते हैं:

[source,bash]
----
javap -p -classpath grolifant40-legacy-api-2.0.0-alpha.6.jar \
org.ysb33r.grolifant.api.v4.JavaForkOptions
----

वहाँ इसे पाया जाता है`executable(java.lang.Object)`— बुलाने की सही विधि, के विपरीत`executable = ...`जो संकलित नहीं होता क्योंकि यह एक संपत्ति है`val`.

=== चरण 6: परियोजना एक्सटेंशन की जाँच करें

के लिए`revealjs { }`, प्रश्न यह था: क्या यह कार्य की एक विधि है या प्रोजेक्ट का एक विस्तार? निरीक्षण का`AsciidoctorJRevealJSTask` कोई भी तरीका नहीं दिखाता`revealjs`. फिर निरीक्षण किया जाता है`RevealJSExtension`:

[source,bash]
----
javap -p -classpath asciidoctor-gradle-jvm-slides-4.0.0-alpha.1.jar \
org.asciidoctor.gradle.jvm.slides.RevealJSExtension | head -5
----

[source]
----
public class RevealJSExtension implements groovy.lang.GroovyObject {
public static final java.lang.String NAME;
----

की मौजूदगी`NAME`यह पुष्टि करता है कि यह एक पंजीकृत एक्सटेंशन परियोजना पर है, के माध्यम से सुलभ`project.extensions.getByType&amp;amp;lt;RevealJSExtension&amp;amp;gt;()`.

=== विधि का सारांश

[cols=&amp;quot;1,3&amp;quot;]
|===
|चरण |क्रिया

|1 |`find ~/.gradle/caches -name &amp;quot;*.jar&amp;quot;`— जार को खोजें |2 |`jar tf jar.jar \| grep NomClasse`— जाँचना कि कक्षा मौजूद है |3 |`javap -p -classpath jar.jar NomCompletClasse`— कक्षा का निरीक्षण करें |4 |पहचानकर्ता`extends`और हिरार्की में चढ़ना |5 |अज्ञात प्रकारों को अपने जारों में ट्रैक करें |6 |खोजें`NAME`एक प्रोजेक्ट एक्सटेंशन की पहचान करने के लिए
|===

यह विधि किसी भी Gradle प्लगइन पर लागू होती है जिसका API दस्तावेज़ीकृत नहीं है या जिसका अल्फा संस्करण अब मौजूदा दस्तावेज़ से मेल नहीं खाता।

== अगला कदम

यह buildSrc प्लगिन को Gradle Plugin Portal या Maven Local पर प्रकाशित किए गए एक स्वतंत्र प्रोजेक्ट में निकाला जाएगा। उपयोग करने वाला buildscript तब : बन जाएगा।

[source,kotlin]
----
plugins { id(&amp;quot;slides&amp;quot;) version &amp;quot;1.0.0&amp;quot; }
----

Et `settings.gradle.kts`इसे उसके न्यूनतम स्तर तक घटा दिया जाएगा बिना किसी संदर्भ के`foojay-resolver-convention`, JDK का प्रावधान प्लगिन द्वारा स्वयं प्रबंधित किया जाता है या यह एक आवश्यक शर्त के रूप में दस्तावेज़ीकृत किया जाता है।&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>आर्किटेक्चर पोर्टफोलियो JBake - दृष्टि और उपयोग के मामले</title>
            <link >https://cheroliv.com/blog/2026/0101_jbake_portfolio_post.html</link>
            <pubDate>Thu, 15 Jan 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0101_jbake_portfolio_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_आर्किटेक्चरल_विज़न&amp;quot;&amp;gt;आर्किटेक्चरल विज़न&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निर्देशक_सिद्धांत&amp;quot;&amp;gt;निर्देशक सिद्धांत&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_रणनीतिक_विकल्प_पोर्टफोलियो_के_लिए_asciidoc&amp;quot;&amp;gt;रणनीतिक विकल्प: पोर्टफोलियो के लिए AsciiDoc&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_डेटा_मॉडल&amp;quot;&amp;gt;डेटा मॉडल&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_विस्तृत_उपयोग_केस&amp;quot;&amp;gt;विस्तृत उपयोग केस&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_uc1_एक_आइटम_पोर्टफोलियो_में_जोड़ें&amp;quot;&amp;gt;UC1 : एक आइटम पोर्टफोलियो में जोड़ें&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel3&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_नॉमिनल_फ़्लक्स&amp;quot;&amp;gt;नॉमिनल फ़्लक्स&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_बनाने_के_लिए_फ़ाइल_का_टेम्प्लेट&amp;quot;&amp;gt;बनाने के लिए फ़ाइल का टेम्प्लेट&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सत्यापन_अंक&amp;quot;&amp;gt;सत्यापन अंक&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_uc2_पोर्टफ़ोलियो_से_एक_आइटम_हटाएँ&amp;quot;&amp;gt;UC2 : पोर्टफ़ोलियो से एक आइटम हटाएँ&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel3&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_नाममात्र_प्रवाह&amp;quot;&amp;gt;नाममात्र प्रवाह&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_वैकल्पिक_रणनीति_अभिलेखागार&amp;quot;&amp;gt;वैकल्पिक रणनीति : अभिलेखागार&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संसाधनों_की_सफाई&amp;quot;&amp;gt;संसाधनों की सफाई&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_uc3_अप्रकाशित_draft_में_रखें&amp;quot;&amp;gt;UC3 : अप्रकाशित (draft) में रखें&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel3&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सामान्य_फ़्लक्स&amp;quot;&amp;gt;सामान्य फ़्लक्स&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संभावित_स्थितियाँ&amp;quot;&amp;gt;संभावित स्थितियाँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सामान्य_उपयोग_केस&amp;quot;&amp;gt;सामान्य उपयोग केस&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_टेम्प्लेटिंग_वास्तुकला&amp;quot;&amp;gt;टेम्प्लेटिंग वास्तुकला&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पुन_प्रयोज्य_टेम्प्लेट्स_की_रणनीति&amp;quot;&amp;gt;पुन: प्रयोज्य टेम्प्लेट्स की रणनीति&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_डेटा_निष्कर्षण_पैटर्न&amp;quot;&amp;gt;डेटा निष्कर्षण पैटर्न&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_नामकरण_नियम&amp;quot;&amp;gt;नामकरण नियम&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_प्रकाशन_वर्कफ़्लो&amp;quot;&amp;gt;प्रकाशन वर्कफ़्लो&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_विकास_पाइपलाइन&amp;quot;&amp;gt;विकास पाइपलाइन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पर्यावरणों&amp;quot;&amp;gt;पर्यावरणों&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_विस्तारनीयता&amp;quot;&amp;gt;विस्तारनीयता&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_नए_विशेषताओं_का_जोड़&amp;quot;&amp;gt;नए विशेषताओं का जोड़&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_उन्नत_वर्गीकरण&amp;quot;&amp;gt;उन्नत वर्गीकरण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अच्छे_अभ्यास&amp;quot;&amp;gt;अच्छे अभ्यास&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_फ़ाइलों_का_संगठन&amp;quot;&amp;gt;फ़ाइलों का संगठन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सामग्री_प्रबंधन&amp;quot;&amp;gt;सामग्री प्रबंधन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_प्रदर्शन&amp;quot;&amp;gt;प्रदर्शन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_आर्किटेक्चरल_विज़न&amp;quot;&amp;gt;आर्किटेक्चरल विज़न&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_निर्देशक_सिद्धांत&amp;quot;&amp;gt;निर्देशक सिद्धांत&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आर्किटेक्चर &amp;lt;strong&amp;gt;विचारों के पृथक्करण&amp;lt;/strong&amp;gt; के सिद्धांत पर आधारित है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;sagri&amp;lt;/strong&amp;gt; : एससीआईडॉक्स फ़ाइलें संरचित मेटाडेटा के साथ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;प्रस्तुति&amp;lt;/strong&amp;gt; : templates Thymeleaf पुन: उपयोग करने योग्य&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;डेटा&amp;quot; : JBake द्वारा AsciiDoc属性 से स्वचालित रूप से निकाला गया मॉडल&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;शैली&amp;lt;/strong&amp;gt; : Bootstrap 5 को दृश्यात्मक सुसंगतता के लिए&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_रणनीतिक_विकल्प_पोर्टफोलियो_के_लिए_asciidoc&amp;quot;&amp;gt;रणनीतिक विकल्प: पोर्टफोलियो के लिए AsciiDoc&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;क्यों AsciiDoc ?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 33.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 66.6667%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;मापदंड&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;लाभ&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;संगति&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Même format que les articles de blog&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;मेटाडेटा&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;संरचित और विस्तारयोग्य गुण (&amp;lt;code&amp;gt;project-*&amp;lt;/code&amp;gt;)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;रखरखावयोग्यता&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;सरल टेक्स्ट संपादन, Git-संस्करणीय&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;लचीलापन&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;इसमें समृद्ध सामग्री (तालिकाएँ, कोड, छवियाँ) हो सकती है&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;टेम्प्लेटिंग&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;JBake स्वचालित रूप से Thymeleaf के लिए अट्रिब्यूट निकालता है&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_डेटा_मॉडल&amp;quot;&amp;gt;डेटा मॉडल&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हर पोर्टफ़ोलियो प्रोजेक्ट एक AsciiDoc दस्तावेज़ है, जिसके साथ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;शीर्षक मेटाडेटा&amp;lt;/strong&amp;gt; : संरचित जानकारी (ग्राहक, अवधि, प्रौद्योगिकियाँ, आदि)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;दस्तावेज़ का शरीर&amp;lt;/strong&amp;gt; : कथात्मक विवरण, चुनौतियाँ, समाधान, परिणाम&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;वैयक्तिकृत विशेषताएँ: पूर्वसंयोजित`project-*`स्वचालित निष्कर्षण के लिए&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-bea209e9aee378261d4d6be388fee53c.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;386&amp;quot; height=&amp;quot;811&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_विस्तृत_उपयोग_केस&amp;quot;&amp;gt;विस्तृत उपयोग केस&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_uc1_एक_आइटम_पोर्टफोलियो_में_जोड़ें&amp;quot;&amp;gt;UC1 : एक आइटम पोर्टफोलियो में जोड़ें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_नॉमिनल_फ़्लक्स&amp;quot;&amp;gt;नॉमिनल फ़्लक्स&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 5) ]

@startuml
skinparam backgroundColor #FEFEFE
actor Développeur as dev
participant &amp;quot;संपादक\nपाठ&amp;quot; as editor
participant &amp;quot;फ़ाइल
^^^^^
 Syntax Error? (Assumed diagram type: sequence)

@startuml
skinparam backgroundColor #FEFEFE
actor Développeur as dev
participant &amp;quot;संपादक\nपाठ&amp;quot; as editor
participant &amp;quot;फ़ाइल
AsciiDoc&amp;quot; as file
participant &amp;quot;JBake
इंजन&amp;quot; as jbake
participant &amp;quot;साइट\nस्थैतिक&amp;quot; as site

dev -&amp;amp;gt; editor : Créer nouveau fichier
activate editor
editor -&amp;amp;gt; file : portfolio/nouveau-projet.adoc
activate file

dev -&amp;amp;gt; editor : Rédiger en-tête avec métadonnées\n(titre, type=project, status=published,\nattributs project-*)
dev -&amp;amp;gt; editor : Rédiger contenu narratif\n(contexte, défis, solutions)
dev -&amp;amp;gt; editor : Ajouter images dans assets/img/portfolio/

editor -&amp;amp;gt; file : Sauvegarder
deactivate editor

dev -&amp;amp;gt; jbake : Lancer build (jbake -b)
activate jbake
jbake -&amp;amp;gt; file : Lire et parser
jbake -&amp;amp;gt; jbake : Extraire métadonnées
jbake -&amp;amp;gt; jbake : Convertir AsciiDoc → HTML
jbake -&amp;amp;gt; jbake : Appliquer template project.html
jbake -&amp;amp;gt; jbake : Ajouter à la liste portfolio.html
jbake -&amp;amp;gt; site : Générer pages statiques
deactivate jbake

dev -&amp;amp;gt; site : Vérifier résultat
activate site
site --&amp;amp;gt; dev : Afficher projet
deactivate site
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_बनाने_के_लिए_फ़ाइल_का_टेम्प्लेट&amp;quot;&amp;gt;बनाने के लिए फ़ाइल का टेम्प्लेट&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;डेवलपर बनाता है`content/portfolio/nom-projet.adoc`एक मानकीकृत संरचना के साथ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;सभी आवश्यक विशेषताओं के साथ शीर्ष&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;मानकीकृत अनुभाग (संदर्भ, चुनौतियाँ, समाधान, परिणाम)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;छवियों की सुसंगत नामावली&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_सत्यापन_अंक&amp;quot;&amp;gt;सत्यापन अंक&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;अनिवार्य विशेषताएँ मौजूद हैं (&amp;lt;code&amp;gt;jbake-type&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;jbake-status&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;project-thumbnail&amp;lt;/code&amp;gt;)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;संदर्भित छवियाँ हैं`assets/img/portfolio/`&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;JBake बिल्ड त्रुटि के बिना सफलतापूर्वक होता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;प्रोजेक्ट पोर्टफ़ोलियो पृष्ठ पर दिखाई देता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;प्रोजेक्ट का व्यक्तिगत पृष्ठ सही ढंग से प्रदर्शित होता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_uc2_पोर्टफ़ोलियो_से_एक_आइटम_हटाएँ&amp;quot;&amp;gt;UC2 : पोर्टफ़ोलियो से एक आइटम हटाएँ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_नाममात्र_प्रवाह&amp;quot;&amp;gt;नाममात्र प्रवाह&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 4) ]

@startuml
skinparam backgroundColor #FEFEFE
actor Développeur as dev
participant &amp;quot;प्रणाली
^^^^^
 Syntax Error? (Assumed diagram type: sequence)

@startuml
skinparam backgroundColor #FEFEFE
actor Développeur as dev
participant &amp;quot;प्रणाली
फ़ाइलें&amp;quot; as fs
participant &amp;quot;JBake
इंजन&amp;quot; as jbake
participant &amp;quot;साइट\nस्थिर&amp;quot; as site
database &amp;quot;कैश
JBake&amp;quot; as cache

dev -&amp;amp;gt; fs : Supprimer portfolio/projet-ancien.adoc
activate fs
fs --&amp;amp;gt; dev : Fichier supprimé
deactivate fs

dev -&amp;amp;gt; fs : (Optionnel) Supprimer images associées\nassets/img/portfolio/projet-ancien-*
activate fs
fs --&amp;amp;gt; dev : Images supprimées
deactivate fs

dev -&amp;amp;gt; cache : Nettoyer cache JBake
activate cache
cache --&amp;amp;gt; dev : Cache vidé
deactivate cache

dev -&amp;amp;gt; jbake : Rebuild complet (jbake -b)
activate jbake
jbake -&amp;amp;gt; jbake : Scanner content/portfolio/
jbake -&amp;amp;gt; jbake : Projet absent → non généré
jbake -&amp;amp;gt; jbake : Régénérer portfolio.html\n(sans le projet supprimé)
jbake -&amp;amp;gt; site : Déployer nouveau build
deactivate jbake

dev -&amp;amp;gt; site : Vérifier
activate site
site --&amp;amp;gt; dev : Projet absent de la liste
deactivate site
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_वैकल्पिक_रणनीति_अभिलेखागार&amp;quot;&amp;gt;वैकल्पिक रणनीति : अभिलेखागार&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;स्थायी रूप से हटाने के बजाय, एक फ़ोल्डर बनाने की संभावना`content/portfolio/archive/`(No output)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;फ़ाइल को हटाने की बजाय इसे ले जाएँ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आसानी से बहाल करने की अनुमति देता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;गिट का इतिहास अधिक स्पष्ट रखें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_संसाधनों_की_सफाई&amp;quot;&amp;gt;संसाधनों की सफाई&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;जाँच करें अनाथ छवियों में`assets/img/portfolio/`&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;अन्य परियोजनाओं द्वारा संदर्भित नहीं की गई छवियों को हटाएँ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;JBake का कैश साफ़ करें ताकि भूतिया संदर्भों से बचा जा सके&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_uc3_अप्रकाशित_draft_में_रखें&amp;quot;&amp;gt;UC3 : अप्रकाशित (draft) में रखें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_सामान्य_फ़्लक्स&amp;quot;&amp;gt;सामान्य फ़्लक्स&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 5) ]

@startuml
skinparam backgroundColor #FEFEFE
actor Développeur as dev
participant &amp;quot;फ़ाइल\nAsciiDoc&amp;quot; as file
participant &amp;quot;JBake
^^^^^
 Syntax Error? (Assumed diagram type: sequence)

@startuml
skinparam backgroundColor #FEFEFE
actor Développeur as dev
participant &amp;quot;फ़ाइल\nAsciiDoc&amp;quot; as file
participant &amp;quot;JBake
इंजन&amp;quot; as jbake
participant &amp;quot;साइट
स्थैतिक&amp;quot; as site

dev -&amp;amp;gt; file : Ouvrir portfolio/projet.adoc
activate file

dev -&amp;amp;gt; file : Modifier attribut\n:jbake-status: published\n↓\n:jbake-status: draft

file --&amp;amp;gt; dev : Sauvegardé
deactivate file

dev -&amp;amp;gt; jbake : Rebuild (jbake -b)
activate jbake
jbake -&amp;amp;gt; file : Parser le fichier
jbake -&amp;amp;gt; jbake : Détecter status=draft
jbake -&amp;amp;gt; jbake : Exclure de published_projects
jbake -&amp;amp;gt; jbake : Ne pas créer page publique
note right
  Le projet existe toujours
  mais n&amp;#39;est pas publié
end note
jbake -&amp;amp;gt; site : Générer site (sans ce projet)
deactivate jbake

dev -&amp;amp;gt; site : Vérifier portfolio
activate site
site --&amp;amp;gt; dev : Projet absent de la liste publique
deactivate site
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_संभावित_स्थितियाँ&amp;quot;&amp;gt;संभावित स्थितियाँ&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-a4b71e9dbf30083d131223257db47469.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;556&amp;quot; height=&amp;quot;448&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_सामान्य_उपयोग_केस&amp;quot;&amp;gt;सामान्य उपयोग केस&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;लेखनाधीन प्रोजेक्ट&amp;lt;/strong&amp;gt; : ड्राफ्ट बनाएं, जब तैयार हो तब प्रकाशित करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;अस्थायी रूप से गोपनीय परियोजना&amp;lt;/strong&amp;gt; : ग्राहक समझौते के दौरान ड्राफ्ट में रखें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;महत्वपूर्ण अपडेट&amp;lt;/strong&amp;gt; : ड्राफ्ट में जाना, संपादित करना, फिर से प्रकाशित करना&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;A/B testing&amp;lt;/strong&amp;gt; : ड्राफ्ट में डुप्लिकेट करें, परीक्षण करें, सर्वोत्तम संस्करण प्रकाशित करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_टेम्प्लेटिंग_वास्तुकला&amp;quot;&amp;gt;टेम्प्लेटिंग वास्तुकला&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_पुन_प्रयोज्य_टेम्प्लेट्स_की_रणनीति&amp;quot;&amp;gt;पुन: प्रयोज्य टेम्प्लेट्स की रणनीति&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-2b0072f38037276992e0f6d3a0089826.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;881&amp;quot; height=&amp;quot;350&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_डेटा_निष्कर्षण_पैटर्न&amp;quot;&amp;gt;डेटा निष्कर्षण पैटर्न&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;JBake AsciiDoc विशेषताओं को Thymeleaf में सुलभ संपत्तियों में स्वचालित रूप से परिवर्तित करता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-62cbc0bbf0985eda2a7b019697a45309.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;893&amp;quot; height=&amp;quot;346&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_नामकरण_नियम&amp;quot;&amp;gt;नामकरण नियम&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;परियोजना गुण&amp;lt;/strong&amp;gt; : प्रीफ़िक्स`project-*` (ex: &amp;lt;code&amp;gt;project-client&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;project-tech-stack&amp;lt;/code&amp;gt;)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;फ़ाइलें&amp;lt;/strong&amp;gt; : kebab-case (उदाहरण:`ecommerce-platform.adoc`)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;छवियाँ&amp;lt;/strong&amp;gt; : प्रीफ़िक्स परियोजना का नाम (उदाहरण:`ecommerce-platform-thumb.jpg`)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Templates&amp;lt;/strong&amp;gt; : कार्यात्मक नाम (उदाहरण:`project-card.html`, &amp;lt;code&amp;gt;tech-badge.html&amp;lt;/code&amp;gt;)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_प्रकाशन_वर्कफ़्लो&amp;quot;&amp;gt;प्रकाशन वर्कफ़्लो&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_विकास_पाइपलाइन&amp;quot;&amp;gt;विकास पाइपलाइन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-2694c3ad773a745365e7ae3fa7dc2d53.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;386&amp;quot; height=&amp;quot;811&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_पर्यावरणों&amp;quot;&amp;gt;पर्यावरणों&amp;lt;/h3&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 20%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 40%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 40%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;पर्यावरण&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;उपयोग&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;स्वीकृत स्थिति&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Local&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;विकास और पूर्वावलोकन&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;ड्राफ्ट, प्रकाशित&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;स्टेजिंग&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;पूर्व-उत्पादन सत्यापन&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;केवल प्रकाशित&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;उत्पादन&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;सार्वजनिक साइट&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;published केवल&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_विस्तारनीयता&amp;quot;&amp;gt;विस्तारनीयता&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_नए_विशेषताओं_का_जोड़&amp;quot;&amp;gt;नए विशेषताओं का जोड़&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;डेटा मॉडल को समृद्ध करने के लिए, सरलता से नए प्रीफ़िक्स वाले विशेषताएँ जोड़ें`project-*`:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;project-awards&amp;lt;/code&amp;gt;: पुरस्कार और सम्मान&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;`project-testimonial`ग्राहक उद्धरण&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;project-team-size&amp;lt;/code&amp;gt;: टीम का आकार&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;project-budget-range&amp;lt;/code&amp;gt;: बजट सीमा&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;ये विशेषताएँ जेएबेक इंजन को संशोधित किए बिना टेम्प्लेट्स में स्वचालित रूप से उपलब्ध हो जाती हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_उन्नत_वर्गीकरण&amp;quot;&amp;gt;उन्नत वर्गीकरण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/diag-plantuml-md5-8fc4ea39537fbf0b42448938639b42a8.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;582&amp;quot; height=&amp;quot;259&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_अच्छे_अभ्यास&amp;quot;&amp;gt;अच्छे अभ्यास&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_फ़ाइलों_का_संगठन&amp;quot;&amp;gt;फ़ाइलों का संगठन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;एक फ़ाइल = एक परियोजना&amp;lt;/strong&amp;gt; : कई परियोजनाओं को मिलाने से बचें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;विशेष फ़ोल्डर में छवियाँ&amp;lt;/strong&amp;gt; :`assets/img/portfolio/nom-projet/`&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;सुसंगत नामावली : खोज और रखरखाव को आसान बनाता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Versioning Git&amp;lt;/strong&amp;gt; : संपूर्ण परिवर्तन ट्रैकिंग&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सामग्री_प्रबंधन&amp;quot;&amp;gt;सामग्री प्रबंधन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;डिफ़ॉल्ट ड्राफ़्ट स्थिति&amp;lt;/strong&amp;gt; : केवल तभी प्रकाशित करें जब तैयार हों&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;प्रकाशन से पहले समीक्षा&amp;lt;/strong&amp;gt; : गुणवत्ता और गोपनीयता की पुष्टि&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;सम्पूर्ण मेटाडेटा&amp;lt;/strong&amp;gt; : सभी संबंधित फ़ील्ड भरें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;समृद्ध कथा सामग्री&amp;lt;/strong&amp;gt; : मेटाडेटा तक सीमित न रहें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_प्रदर्शन&amp;quot;&amp;gt;प्रदर्शन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;छवियों को अनुकूलित करें&amp;lt;/strong&amp;gt; : कमिट से पहले संपीड़न&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;yदि आवश्यक हो तो पेज़िनेशन&amp;lt;/strong&amp;gt; : यदि &amp;amp;gt;20 परियोजनाएँ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Lazy loading&amp;lt;/strong&amp;gt; : गैलरी की छवियों को आवश्यकतानुसार लोड किया जाता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;ब्राउज़र कैश&amp;lt;/strong&amp;gt; : एसेट्स के लिए उपयुक्त हेडर&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह वास्तुकला अनुमति देती है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;उपयोग में आसानी&amp;lt;/strong&amp;gt; : एक परियोजना जोड़ें = एक टेक्स्ट फ़ाइल बनाएँ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;लचीलापन&amp;lt;/strong&amp;gt; : विस्तारयोग्य नई विशेषताओं के माध्यम से&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;धारणीयता&amp;lt;/strong&amp;gt; : सामग्री/प्रस्तुति का पृथक्करण&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;ट्रेसबिलिटी&amp;lt;/strong&amp;gt; : Git का पूर्ण संस्करणन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;स्वचालन&amp;lt;/strong&amp;gt; : लगातार बनाना और तैनाती संभव&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;AsciiDoc का चयन साइट के बाकी हिस्से के साथ सुसंगतता सुनिश्चित करता है, साथ ही एक पेशेवर पोर्टफ़ोलियो के लिए आवश्यक मेटाडेटा की समृद्धि प्रदान करता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>हाइब्रिड आर्किटेक्चर : दोनों दुनिया का सर्वश्रेष्ठ Supabase और Spring Boot के साथ</title>
            <link >https://cheroliv.com/blog/2026/0100_jbake_supabase_springboot_hybride_post.html</link>
            <pubDate>Wed, 14 Jan 2026 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2026/0100_jbake_supabase_springboot_hybride_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;पढ़ने का समय : 12 minutes&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;सुपाबेस की सरलता और स्प्रिंग बूट की शक्ति के बीच चयन करने के बजाय, दोनों को क्यों नहीं मिलाएँ? एक हाइब्रिड आर्किटेक्ट खोजें जो प्रत्येक तकनीक के सर्वश्रेष्ठ पहलुओं का उपयोग करता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;सामग्री की तालिका&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;(No output)&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_आधुनिक_वास्तुकला_का_झूठा_दुविधा&amp;quot;&amp;gt;आधुनिक वास्तुकला का झूठा दुविधा&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जब कोई आधुनिक एप्लिकेशन एक स्थिर फ्रंटएंड के साथ बनाता है, तो वह अक्सर द्विआधारी विकल्प के सामने आ जाता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;एक बैकएंड-एज़-ए-सेवा समाधान पर सब कुछ दांव लगाना&amp;lt;/strong&amp;gt;(Supabase, Firebase) - सरल लेकिन सीमित&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;एक पूर्ण बैकएंड बनाएँ&amp;lt;/strong&amp;gt;(Spring Boot, Node.js) - शक्तिशाली लेकिन जटिल&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह विकल्प एक गलत द्वंद्व है। हाइब्रिड आर्किटेक्चर एक तीसरा रास्ता प्रस्तुत करता है: &amp;lt;strong&amp;gt;हर तकनीक का उपयोग उस जगह करें जहाँ वह उत्कृष्ट होती है&amp;lt;/strong&amp;gt;।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_वास्तुकल_दृष्टि&amp;quot;&amp;gt;वास्तुकल दृष्टि&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_पारंपरिक_आर्किटेक्चर_मोनोलिथिक&amp;quot;&amp;gt;पारंपरिक आर्किटेक्चर: मोनोलिथिक&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;traditional-architecture.svg&amp;quot; alt=&amp;quot;traditional architecture&amp;quot; width=&amp;quot;1744&amp;quot; height=&amp;quot;5664&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस दृष्टिकोण में, सबसे सरल संचालन (एक लेख पढ़ना, एक टिप्पणी बनाना) भी आपके बैकएंड से गुजरना चाहिए। आप पहले दिन से ही जटिलता की लागत चुकाते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_baas_आर्किटेक्चर_सब_प्रतिनिधि&amp;quot;&amp;gt;BaaS आर्किटेक्चर: सब प्रतिनिधि&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;baas-architecture.svg&amp;quot; alt=&amp;quot;baas architecture&amp;quot; width=&amp;quot;1746&amp;quot; height=&amp;quot;5640&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;दूसरी ओर, BaaS पर सब कुछ बाहर रखना शुरू में आकर्षक लगता है, परंतु जब व्यावसायिक तर्क जटिल होने लगता है, तो यह तेज़ी से अपनी सीमाएँ दिखाने लगता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_हाइब्रिड_आर्किटेक्चर_जिम्मेदारियों_का_विभाजन&amp;quot;&amp;gt;हाइब्रिड आर्किटेक्चर : जिम्मेदारियों का विभाजन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;hybrid-overview.svg&amp;quot; alt=&amp;quot;hybrid overview&amp;quot; width=&amp;quot;1758&amp;quot; height=&amp;quot;5784&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हाइब्रिड आर्किटेक्चर जटिलता और संचालन की प्रकृति के अनुसार स्पष्ट रूप से जिम्मेदारियों को अलग करता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_डिज़ाइन_के_सिद्धांत&amp;quot;&amp;gt;डिज़ाइन के सिद्धांत&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सिद्धांत_1_सरलता_से_शुरू_करें_बुद्धिमानी_से_विकसित_हों&amp;quot;&amp;gt;सिद्धांत 1: सरलता से शुरू करें, बुद्धिमानी से विकसित हों&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;evolution-phases.svg&amp;quot; alt=&amp;quot;evolution phases&amp;quot; width=&amp;quot;1738&amp;quot; height=&amp;quot;5688&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;यदि आपको इसकी आवश्यकता नहीं है, तो Spring Boot का निर्माण न करें।&amp;lt;/strong&amp;gt;Supabase से शुरू करें, जब जटिलता इसकी मांग करे तो Spring Boot जोड़ें.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सिद्धान्त_2_ऑपरेशन_की_प्रकृति_से_पृथक्करण&amp;quot;&amp;gt;सिद्धान्त 2 : ऑपरेशन की प्रकृति से पृथक्करण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;operation-types.svg&amp;quot; alt=&amp;quot;operation types&amp;quot; width=&amp;quot;1266&amp;quot; height=&amp;quot;241&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सिद्धांत_3_एक_ही_सत्य_का_स्रोत&amp;quot;&amp;gt;सिद्धांत 3: एक ही सत्य का स्रोत&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;single-source-truth.svg&amp;quot; alt=&amp;quot;single source truth&amp;quot; width=&amp;quot;1746&amp;quot; height=&amp;quot;5712&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;PostgreSQL की एक ही इंस्टेंस साझा करके, Supabase और Spring Boot एक ही डेटा पर काम करते हैं, बिना जटिल सिंक्रोनाइज़ेशन के।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_फ़्लक्स_की_ऑर्केस्ट्रेशन&amp;quot;&amp;gt;फ़्लक्स की ऑर्केस्ट्रेशन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_फ़्लक्स_1_केंद्रीकृत_प्रमाणीकरण&amp;quot;&amp;gt;फ़्लक्स 1: केंद्रीकृत प्रमाणीकरण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;auth-orchestration.svg&amp;quot; alt=&amp;quot;auth orchestration&amp;quot; width=&amp;quot;1099&amp;quot; height=&amp;quot;950&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;मुख्य बिंदु&amp;lt;/strong&amp;gt;एक ही प्रमाणीकरण प्रक्रिया, एक ही JWT, हर जगह उपयोग करने योग्य.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_flux_2_एक_जटिल_व्यावसायिक_प्रक्रिया_का_ऑर्केस्ट्रेशन&amp;quot;&amp;gt;Flux 2 : एक जटिल व्यावसायिक प्रक्रिया का ऑर्केस्ट्रेशन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;business-orchestration.svg&amp;quot; alt=&amp;quot;business orchestration&amp;quot; width=&amp;quot;1169&amp;quot; height=&amp;quot;990&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Spring Boot क्या लाता है&amp;lt;/strong&amp;gt;लेनदेन गारंटी के साथ कई प्रणालियों को शामिल करते हुए जटिल प्रक्रियाओं की विश्वसनीय आर्केस्ट्रेशन&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_फ़्लक्स_3_नियोजित_कार्य_और_सिंक्रोनाइज़ेशन&amp;quot;&amp;gt;फ़्लक्स 3 : नियोजित कार्य और सिंक्रोनाइज़ेशन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;scheduled-jobs.svg&amp;quot; alt=&amp;quot;scheduled jobs&amp;quot; width=&amp;quot;920&amp;quot; height=&amp;quot;912&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Spring Boot क्या लाता है&amp;lt;/strong&amp;gt;विश्वसनीय निर्धारित जॉब्स के साथ स्थिति प्रबंधन, स्वचालित पुनः प्रयास, और सुनिश्चित निष्पादन.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निर्णय_मेट्रिक्स&amp;quot;&amp;gt;निर्णय मेट्रिक्स&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_supabase_का_उपयोग_कब_करें&amp;quot;&amp;gt;Supabase का उपयोग कब करें ?&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;supabase-decision.svg&amp;quot; alt=&amp;quot;supabase decision&amp;quot; width=&amp;quot;1030&amp;quot; height=&amp;quot;445&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_स्प्रिंग_बूट_का_उपयोग_कब_करें&amp;quot;&amp;gt;स्प्रिंग बूट का उपयोग कब करें?&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;springboot-decision.svg&amp;quot; alt=&amp;quot;springboot decision&amp;quot; width=&amp;quot;1142&amp;quot; height=&amp;quot;485&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परियोजना_प्रकार_के_अनुसार_आर्किटेक्चर_के_उदाहरण&amp;quot;&amp;gt;परियोजना प्रकार के अनुसार आर्किटेक्चर के उदाहरण&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ब्लॉग_पोर्टफ़ोलियो&amp;quot;&amp;gt;ब्लॉग / पोर्टफ़ोलियो&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;blog-architecture.svg&amp;quot; alt=&amp;quot;blog architecture&amp;quot; width=&amp;quot;1773&amp;quot; height=&amp;quot;5700&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;निर्णय&amp;lt;/strong&amp;gt;100% Supabase बहुत पर्याप्त है&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_saas_एप्लिकेशन&amp;quot;&amp;gt;SaaS एप्लिकेशन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;saas-architecture.svg&amp;quot; alt=&amp;quot;saas architecture&amp;quot; width=&amp;quot;1770&amp;quot; height=&amp;quot;5748&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;निर्णय&amp;lt;/strong&amp;gt;हाइब्रिड आर्किटेक्चर आवश्यक है। Supabase मुख्य हिस्से के लिए, Spring Boot महत्वपूर्ण भाग (भुगतान, बिलिंग) के लिए।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_इलेक्ट्रॉनिक_वाणिज्य&amp;quot;&amp;gt;इलेक्ट्रॉनिक वाणिज्य&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;ecommerce-architecture.svg&amp;quot; alt=&amp;quot;ecommerce architecture&amp;quot; width=&amp;quot;1738&amp;quot; height=&amp;quot;5760&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;निर्णय&amp;lt;/strong&amp;gt;: Spring Boot आवश्यक है। Supabase केवल प्रमाणीकरण और कैटालॉग के लिए।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_प्रगतिशील_प्रवास_रणनीति&amp;quot;&amp;gt;प्रगतिशील प्रवास रणनीति&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;migration-strategy.svg&amp;quot; alt=&amp;quot;migration strategy&amp;quot; width=&amp;quot;2050&amp;quot; height=&amp;quot;954&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_लागत_और_परिचालन_विचार&amp;quot;&amp;gt;लागत और परिचालन विचार&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_लागत_संरचना&amp;quot;&amp;gt;लागत संरचना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 7) ]

@startuml
skinparam backgroundColor #FEFEFE

package &amp;quot;अनुमानित मासिक लागत&amp;quot; {

  rectangle &amp;quot;चरण MVP
(0-1000 उपयोगकर्ता)&amp;quot; #LightGreen {
^^^^^
 Syntax Error? (Assumed diagram type: activity)

@startuml
skinparam backgroundColor #FEFEFE

package &amp;quot;अनुमानित मासिक लागत&amp;quot; {

  rectangle &amp;quot;चरण MVP
(0-1000 उपयोगकर्ता)&amp;quot; #LightGreen {
    [JBake (GitHub Pages): 0€]
    [Supabase: 0€]
    [Spring Boot: N/A]
    note bottom: **Total: 0€/mois**
  }

  rectangle &amp;quot;वृद्धि चरण
(1k-10k उपयोगकर्ता)&amp;quot; #LightYellow {
    [JBake (GitHub Pages): 0€]
    [Supabase: 0€]
    [Spring Boot (Cloud Run): 20-50€]
    [PostgreSQL (si séparé): 0-30€]
    note bottom: **Total: 20-80€/mois**
  }

  rectangle &amp;quot;चरण स्केल
(10k-100k उपयोगकर्ता)&amp;quot; #LightCoral {
    [JBake (Netlify Pro): 19€]
    [Supabase Pro: 25€]
    [Spring Boot (instances multiples): 100-300€]
    [Redis Cache: 20-50€]
    [Monitoring: 20€]
    note bottom: **Total: 184-414€/mois**
  }
}

note right of &amp;quot;चरण स्केल
(10k-100k उपयोगकर्ता)&amp;quot;
  À ce stade, les revenus
  justifient largement les coûts
end note
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ऑपरेशनल_जिम्मेदारियाँ&amp;quot;&amp;gt;�ऑपरेशनल जिम्मेदारियाँ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;operational-responsibilities.svg&amp;quot; alt=&amp;quot;operational responsibilities&amp;quot; width=&amp;quot;1742&amp;quot; height=&amp;quot;5700&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष_पूर्ण_संतुलन&amp;quot;&amp;gt;निष्कर्ष: पूर्ण संतुलन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Supabase + Spring Boot की संकर आर्किटेक्चर एक समझौता नहीं है, यह एक&amp;lt;strong&amp;gt;सहयोग&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ध्यान_में_रखने_वाले_सिद्धांत&amp;quot;&amp;gt;ध्यान में रखने वाले सिद्धांत&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;key-principles.svg&amp;quot; alt=&amp;quot;key principles&amp;quot; width=&amp;quot;581&amp;quot; height=&amp;quot;316&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_कब_इस_आर्किटेक्चर_को_चुनें&amp;quot;&amp;gt;कब इस आर्किटेक्चर को चुनें ?&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;�✅ यह आर्किटेक्चर आदर्श है यदि :&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आप जल्दी से शुरू करना चाहते हैं (एमवीपी दिनों में, महीनों में नहीं)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आप व्यावसायिक जटिलता में वृद्धि की आशा रखते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आप प्रारम्भिक लागत को कम करना चाहते हैं&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आप PostgreSQL को पसंद करते हैं और सत्य का एकमात्र स्रोत चाहते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आप कोटलिन और कोरूटीन को व्यावसायिक कोड के लिए सराहते हैं&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आप पूर्ण विक्रेता लॉक-इन से बचना चाहते हैं&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;�❌ यह आर्किटेक्ट उपयुक्त नहीं है यदि :&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आपका प्रोजेक्ट सरल है और ऐसा ही रहेगा (व्यक्तिगत ब्लॉग → 100% Supabase पर्याप्त है)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आपके पास पहले से ही एक स्थापित बैकएंड स्टैक है जिसे आप समझते हैं&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आप पारंपरिक एकल पत्थर को पसंद करते हैं&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आपको .NET, Python, या अन्य बैकएंड भाषा की आवश्यकता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_अंतिम_समग्र_दृष्टिकोण&amp;quot;&amp;gt;अंतिम समग्र दृष्टिकोण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;final-vision.svg&amp;quot; alt=&amp;quot;final vision&amp;quot; width=&amp;quot;1751&amp;quot; height=&amp;quot;5760&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_दोनों_दुनियाओं_का_सर्वश्रेष्ठ&amp;quot;&amp;gt;दोनों दुनियाओं का सर्वश्रेष्ठ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह आर्किटेक्चर आपको देता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;�🚀 Supabase का वेग&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;घंटों में प्रारम्भ, हफ्तों में नहीं&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;OAuth2 प्रमाणीकरण कुछ क्लिक्स में&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;स्वचालित रूप से उत्पन्न REST API&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;ज़ीरो सर्वर कॉन्फ़िगरेशन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;�💪 Spring Boot की शक्ति&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Kotlin और Coroutines के लिए सुंदर असिंक्रोनस कोड&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;जटिल व्यावसायिक प्रक्रियाओं का ऑर्केस्ट्रेशन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;विश्वसनीय निर्धारित कार्य&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;ACID लेनदेन गारंटीकृत&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;पूरा Spring इकोसिस्टम&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;💰 प्रगतिशील अर्थव्यवस्था&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;शुरू करने और पुष्टि करने के लिए 0€&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;विकास के अनुसार लागत&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;प्रीमैच्योर ओवर-इंजीनियरिंग नहीं&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;🎯 आर्किटेक्चरल लचीलापन&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;प्रगतिशील माइग्रेशन बिना पुनः संरचना&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;यदि आवश्यक हो तो केवल Spring Boot जोड़ें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कुल वेंडर लॉक‑इन नहीं&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;विकासशील आर्किटेक्चर&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_और_आगे_जाने_के_लिए&amp;quot;&amp;gt;और आगे जाने के लिए&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_तकनीकी_संसाधन&amp;quot;&amp;gt;तकनीकी संसाधन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;सुपाबेस दस्तावेज़ :&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://supabase.com/docs/guides/auth&amp;quot;&amp;gt;प्रमाणीकरण गाइड&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://supabase.com/docs/guides/database/postgres/row-level-security&amp;quot;&amp;gt;पंक्तियों के स्तर की सुरक्षा&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://supabase.com/docs/guides/api&amp;quot;&amp;gt;स्वचालित रूप से उत्पन्न API&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;स्प्रिंग बूट दस्तावेज़ :&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://spring.io/guides/tutorials/spring-boot-kotlin/&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://spring.io/guides/tutorials/spring-boot-kotlin/&amp;lt;/a&amp;gt;[&amp;lt;mark&amp;gt;#&amp;lt;/mark&amp;gt; ग्रैडल एकीकरण&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;JBake को JBake Gradle प्लगइन का उपयोग करके या JBake CLI को सीधे बुलाकर Gradle बिल्ड में एकीकृत किया जा सकता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;----
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
}]
* https://spring.io/blog/2019/04/12/going-reactive-with-spring-coroutines-and-kotlin-flow[Coroutines और Spring]
* https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/jwt.html[JWT संसाधन सर्वर]

**पूरक अनुच्छेद:**

* JWT के साथ API सुरक्षा
* PostgreSQL प्रदर्शन अनुकूलन
* प्रगतिशील प्रवास के पैटर्न
* वितरित आर्किटेक्चर में त्रुटि प्रबंधन

=== वास्तविक उपयोग के मामले

इस हाइब्रिड आर्किटेक्चर को सफलतापूर्वक उपयोग में लाया जाता है :

* **SaaS B2B**सुपरबेस प्रमाणीकरण, सपिंग बूट बिलिंग
* **बाज़ारें**: कैटलॉग Supabase, लेनदेन Spring Boot
* **सामग्री प्लेटफ़ॉर्म**: लेख Supabase, विश्लेषण Spring Boot
* **आंतरिक उपकरण**CRUD Supabase, कार्यप्रवाह Spring Boot

=== स्टार्टअप चेकलिस्ट

**चरण 1 - नींव (हफ़्ता 1)**

- [ ] सुपाबेस खाता बनाएँ - [ ] PostgreSQL प्रोजेक्ट कॉन्फ़िगर करें - [ ] Auth सक्रिय करें (Google, GitHub) ### JBake CLI कमांड
# एक नया JBake प्रोजेक्ट प्रारंभ करें
jbake -i

# साइट बेक (जेनरेट) करें
jbake -b

# स्थानीय रूप से बेक और परोसें
jbake -b -s

# परिवर्तनों के लिए बेक और देखें
jbake -b --reset

# स्रोत और गंतव्य निर्दिष्ट करें
jbake source_folder output_folder

# बेक करने से पहले आउटपुट डायरेक्टरी साफ़ करें
jbake -b . output --reset
- [ ] प्रारंभिक स्कीमा परिभाषित करें Row Level Security कॉन्फ़िगर करें - [ ] Tester APIs depuis JBake

**चरण 2 - MVP (सप्ताह 2-3)**

- [ ] मुख्य पेज़ लागू करना - [ ] OAuth2 प्रमाणीकरण को एकीकृत करें - [ ] CRUD फ़ॉर्म बनाना - [ ] फाइलों के लिए Storage कॉन्फ़िगर करें - [ ] गिटहब पेज पर तैनात करें - [ ] वास्तविक स्थितियों में परीक्षण करें

**फेज़ 3 - विकास (आवश्यकताओं के अनुसार)**

- [ ] जटिल तर्क आवश्यकताओं की पहचान करें - [ ] यदि आवश्यक हो तो Spring Boot प्रोजेक्ट बनाएँ - [ ] Supabase में JWT सत्यापन कॉन्फ़िगर करें - [ ] PostgreSQL Supabase से कनेक्ट करें - [ ] जटिल सुविधाएँ माइग्रेट करें - [ ] योजित कार्यों को लागू करें - [ ] डिप्लॉय Spring Boot (Cloud Run, etc.)

=== परिहार्य एंटी-पैटर्न्स

**�❌ न करें :**

* Supabase और Spring Boot के बीच डेटा की प्रतिलिपि बनाएँ
* दो अलग PostgreSQL डेटाबेस बनाएँ
* स्वयं प्रमाणीकरण को कोड करें
* सरल CRUD के लिए Spring Boot का उपयोग करना
* शुरू से ही अति आर्किटेक्चर करना
* Supabase की Row Level Security को अनदेखा करें

**बेहतर करें:**

* एक ही PostgreSQL डेटाबेस साझा करें
* Supabase को प्रमाणीकरण प्रबंधित करने दें
* स्प्रिंग बूट का उपयोग केवल जटिलता के लिए करें
* सरलता से शुरू करें, धीरे-धीरे विकसित हों
* प्रौद्योगिकी के प्रत्येक बल का उपयोग करें
* डेटाबेस स्तर पर RLS के साथ सुरक्षित करें

== विकास के परिप्रेक्ष्य

=== नयी क्षमताओं का जोड़

[plantuml,future-capabilities,svg]
----
@startuml
skinparam backgroundColor #FEFEFE

rectangle &amp;quot;वर्तमान वास्तुकला&amp;quot; #SkyBlue {
  [JBake]
  [Supabase]
  [Spring Boot]
}

rectangle &amp;quot;संभावित विकास&amp;quot; #LightYellow {

  package &amp;quot;प्रदर्शन&amp;quot; {
    [Redis Cache]
    [CDN pour Assets]
    [PostgreSQL Replicas]
  }

  package &amp;quot;निरीक्षण&amp;quot; {
    [Grafana]
    [Prometheus]
    [Sentry]
  }

  package &amp;quot;CI/CD&amp;quot; {
    [GitHub Actions]
    [Tests Automatisés]
    [Déploiement Continu]
  }

  package &amp;quot;विशेषताएँ&amp;quot; {
    [Search (ElasticSearch)]
    [Queue (RabbitMQ)]
    [Event Sourcing]
  }
}

[Spring Boot] .down.&amp;amp;gt; [Redis Cache] : Peut ajouter
[Spring Boot] .down.&amp;amp;gt; [Queue (RabbitMQ)] : Peut ajouter
[Spring Boot] .down.&amp;amp;gt; [Search (ElasticSearch)] : Peut ajouter

[Supabase] .down.&amp;amp;gt; [PostgreSQL Replicas] : Peut ajouter

note bottom
  **Architecture extensible**
  Chaque ajout est indépendant
  Pas de refonte globale nécessaire
end note
@enduml
----

=== क्षैतिज स्केलिंग

जैसे आपका एप्लिकेशन बढ़ता है, हाइब्रिड आर्किटेक्चर स्वाभाविक रूप से स्केल होता है :

**सुपाबेस :**

* यह स्वचालित रूप से मिलियन ऑपरेशन तक स्केल होता है
* Read replicas पढ़ने के प्रदर्शन के लिए
* सुरक्षा के लिए Point-in-time recovery

**स्प्रिंग बूट :**

* लोड बैलेंसर के पीछे कई इंस्टेंस
* स्टेटलेस डिज़ाइन क्षैतिज स्केलींग को सुविधाजनक बनाता है
* Kubernetes ऑर्केस्ट्रेशन के लिए यदि आवश्यक हो

**PostgreSQL:**

* बड़ी टेबल के लिए विभाजन
* कनेक्शन पूलिंग (PgBouncer)
* Sharding यदि वास्तव में आवश्यक है (दुर्लभ)

== आर्किटेक्चरल साक्ष्य

=== स्टार्टअप SaaS (50k उपयोगकर्ता)

____ हमने 100% Supabase से शुरुआत की। 5k उपयोगकर्ताओं पर, हमने केवल Stripe बिलिंग और मासिक रिपोर्ट के लिए Spring Boot जोड़ा। एक साल बाद, हमारे 80% संचालन अभी भी Supabase से गुजरते हैं। Spring Boot केवल महत्वपूर्ण हिस्से को प्रबंधित करता है। यह अलगाव हमें बिना redesign के स्केल करने की अनुमति देता है। ____

=== प्लेटफ़ॉर्म इ-लर्निंग (10k उपयोगकर्ता)

[No output - the input contains no French text to translate, only instructions and placeholder &amp;quot;____&amp;quot;. Per strict instructions, no additional context is requested and nothing is added.] Supabase का OAuth2 प्रमाणीकरण ने हमें 3 सप्ताह की विकास समय बचाया। स्वतः-जनरेटेड APIs हमारे पूरे पाठ्यक्रम कैटलॉग को प्रबंधित करती हैं। Spring Boot केवल PDF प्रमाणपत्र और प्रगति ईमेल के लिए उपयोग किया जाता है। साधारण, रखरखाव योग्य, विस्तार योग्य आर्किटेक्चर। &amp;amp;lt;/think&amp;amp;gt;
(No output)

=== B2B मार्केटप्लेस (3k उपयोगकर्ता)

____ Spring Boot खरीदार और विक्रेता के बीच लेन-देन का प्रबंधन करता है (आवश्यक)। Supabase शेष सभी कार्यों को संभालता है: प्रोफ़ाइल, वास्तविक समय संदेश, दस्तावेज़। यह तथ्य कि वे समान PostgreSQL डेटाबेस साझा करते हैं, हमें जटिल सिंक्रनाइज़ेशन से बचाता है। यह हम द्वारा किया गया सबसे अच्छा वास्तुशिल्प निर्णय है। (No output)

== संश्लेषण : एक आधुनिक वास्तुकलिक पैराडिग्म

हाइब्रिड आर्किटेक्चर Supabase + Spring Boot एक नया पैराडाइम दर्शाता है:**आर्किटेक्चर विशेषीकरण**.

[plantuml,paradigm-shift,svg]
----
@startuml
skinparam backgroundColor #FEFEFE

rectangle &amp;quot;पुराना पैराडाइम&amp;quot; #LightCoral {
  card &amp;quot;बैकएंड में सब कुछ&amp;quot; {
    [Auth]
    [CRUD]
    [Logique Métier]
    [Jobs]
    [Storage]
    [Realtime]
  }
  note bottom
    Complexité maximale
    dès le jour 1
  end note
}

rectangle &amp;quot;नया पैराडाइम&amp;quot; #LightGreen {
  card &amp;quot;Supabase
(सुविधा)&amp;quot; {
    [Auth]
    [CRUD Simple]
    [Storage]
    [Realtime]
  }

  card &amp;quot;Spring Boot
(डिफ़रेंशिएशन)&amp;quot; {
    [Logique Métier]
    [Jobs]
    [Intégrations]
  }

  note bottom
    Complexité progressive
    ajoutée seulement si nécessaire
  end note
}

[Ancien Paradigme] -right-&amp;amp;gt; [Nouveau Paradigme] : Évolution

@enduml
----

**मूलभूत सिद्धांत :**वह जो सेवा के रूप में पहले से मौजूद है, उसका निर्माण न करें। अपने एप्लिकेशन को अलग बनाने वाली बात पर ध्यान केंद्रित करें।

=== 80/20 का नियम

अधिकांश अनुप्रयोगों में :

* **80% के ऑपरेशनों**हैं मानक CRUD → Supabase
* **20% ऑपरेशनों का**व्यवसायिक लॉजिक की आवश्यकता होती है → Spring Boot

यह प्राकृतिक नियम हाइब्रिड आर्किटेक्चर को औचित्य देता है।

[plantuml,8020-rule,svg]
----
@startuml
skinparam backgroundColor #FEFEFE

package &amp;quot;ऑपरेशनों का वितरण&amp;quot; {

  rectangle &amp;quot;80% - मानक संचालन&amp;quot; #LightGreen {
    [Lecture de données]
    [Création d&amp;#39;entités]
    [Mise à jour simple]
    [Suppression]
    [Upload fichiers]
    [Authentification]

    note bottom: **Géré par Supabase**
  }

  rectangle &amp;quot;20% - व्यवसाय तर्क&amp;quot; #Coral {
    [Calculs complexes]
    [Workflows multi-étapes]
    [Transactions critiques]
    [Intégrations tierces]
    [Jobs planifiés]

    note bottom: **Géré par Spring Boot**
  }
}

note right
  **Focus optimal :**
  Votre temps de développement
  concentré sur les 20% qui
  différencient votre produit
end note
@enduml
----

== अंतिम निष्कर्ष

हाइब्रिड वास्तुकला तकनीकी समझौता नहीं है, यह एक**रणनीतिक निर्णय**.

**यह आपको करने की अनुमति देता है:**

* �✅ एक कार्यात्मक एमवीपी के साथ जल्दी से शुरू करें
* ✅ अपने बाजार को भारी निवेश किए बिना मान्य करें
* �✅ जटिलता की आवश्यकता पड़ने पर धीरे-धीरे विकसित हों
* ✅ अपनी लागत को हर चरण में नियंत्रित करें
* हर तकनीक के सर्वोत्तम का उपयोग करें
* �✅ अकाल अतिरंजित इंजीनियरिंग से बचें
* ✅ भविष्य के लिए लचीलापन संरक्षित करें

**वह दर्शाती है:**

* (Translation: Since no French text was provided in the input, there is nothing to translate. The output is an empty string.)**प्रागमतिवाद**: हर तकनीक जहाँ वह उत्कृष्ट होती है
* �🚀**गति**: बाजार में उतरने का न्यूनतम समय
* �💰**अर्थव्यवस्था**मूल्य के अनुसार लागत
* �🔮**स्केलेबिलिटी**: आपके साथ बढ़ने वाली आर्किटेक्चर
* �🛡️**मजबूती**परीक्षित और विश्वसनीय सेवाएँ

=== आपका अगला कदम

यदि यह वास्तुकला आपसे बात करती है, तो यहाँ से शुरू करने का तरीका है :

1. **एक Supabase खाता बनाएँ**(मुफ्त)
2. **अपनी न्यूनतम डेटा स्कीमा परिभाषित करें**
3. **OAuth2 प्रमाणीकरण कॉन्फ़िगर करें**
4. **अपनी पहली JBake पृष्ठ बनाएँ जो API का उपयोग करती है**
5. **GitHub Pages पर तैनात करें**

आपके पास एक कार्यात्मक MVP होगा**कु�ुछ दिन**.

Spring Boot स्वाभाविक रूप से आएगा जब आपको इसकी आवश्यकता होगी। उससे पहले नहीं।

---

**हाइब्रिड आर्किटेक्चर, इसका मतलब है ठीक वही बनाना जो ज़रूरत हो, ठीक समय पर।**

शुभ विकास ! 🚀

---

_यदि आप सोचते हैं कि यह लेख अन्य डेवलपर्स को सही वास्तुकला विकल्प चुनने में मदद कर सकता है तो इसे साझा करें._
----&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>प्रीलोड करने की कला: जावास्क्रिप्ट और CSS के साथ थीम का &quot;Flash&quot; हटाएँ</title>
            <link >https://cheroliv.com/blog/2025/0098_preloading_css_variable_post.html</link>
            <pubDate>Sat, 15 Nov 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0098_preloading_css_variable_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_रिज़्यूमे&amp;quot;&amp;gt;रिज़्यूमे&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_इस_अभिशप्त_थीम_का_झिलमिलाना&amp;quot;&amp;gt;समस्या: इस अभिशप्त थीम का झिलमिलाना&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_उपयोगकर्ता_अनुभव_के_लिए_एक_दुःस्वप्न&amp;quot;&amp;gt;उपयोगकर्ता अनुभव के लिए एक दुःस्वप्न&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_फ़ouc_एक_पुराना_वेब_समस्या&amp;quot;&amp;gt;फ़OUC : एक पुराना वेब समस्या&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_गुणवत्ता_की_धारणा_पर_प्रभाव&amp;quot;&amp;gt;गुणवत्ता की धारणा पर प्रभाव&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_का_तकनीकी_विश्लेषण&amp;quot;&amp;gt;समस्या का तकनीकी विश्लेषण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_क्लासिक_स्क्रिप्ट_क्यों_पर्याप्त_नहीं_है&amp;quot;&amp;gt;क्लासिक स्क्रिप्ट क्यों पर्याप्त नहीं है?&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अनुभवी_लेकिन_अप्रभावी_दृष्टिकोण&amp;quot;&amp;gt;अनुभवी लेकिन अप्रभावी दृष्टिकोण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_domcontentloaded_इवेंट_को_समझें&amp;quot;&amp;gt;DOMContentLoaded इवेंट को समझें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_रेंडर_ब्लॉकिंग_की_समस्या&amp;quot;&amp;gt;रेंडर ब्लॉकिंग की समस्या&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_का_दृश्यीकरण&amp;quot;&amp;gt;समस्या का दृश्यीकरण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_असफल_समाधान_प्रयास&amp;quot;&amp;gt;असफल समाधान प्रयास&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_वास्तविक_समाधान_जल्दी_कार्य_करें&amp;quot;&amp;gt;वास्तविक समाधान : जल्दी कार्य करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समाधान_पूर्व_लोडिंग_early_loading&amp;quot;&amp;gt;समाधान : पूर्व लोडिंग (Early Loading)&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_मूल_सिद्धांत&amp;quot;&amp;gt;मूल सिद्धांत&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_क्यों_head_आदर्श_स्थान_है&amp;quot;&amp;gt;क्यों &amp;lt;code&amp;gt;&amp;amp;lt;head&amp;amp;gt;&amp;lt;/code&amp;gt; आदर्श स्थान है&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समाधान_की_तीन_स्तरीय_आर्किटेक्चर&amp;quot;&amp;gt;समाधान की तीन-स्तरीय आर्किटेक्चर&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_1_उपयोगकर्ता_की_पसंद_को_सेव_करना&amp;quot;&amp;gt;चरण 1 : उपयोगकर्ता की पसंद को सेव करना&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_localstorage_आपकी_स्थायी_स्मृति&amp;quot;&amp;gt;localStorage : आपकी स्थायी स्मृति&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_थीम_बैकअप_का_कार्यान्वयन&amp;quot;&amp;gt;थीम बैकअप का कार्यान्वयन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_त्रुटि_मामलों_का_प्रबंधन&amp;quot;&amp;gt;त्रुटि मामलों का प्रबंधन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अधिक_उन्नत_निरंतरता_रणनीतियाँ&amp;quot;&amp;gt;अधिक उन्नत निरंतरता रणनीतियाँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_2_प्री_लोडिंग_स्क्रिप्ट_में_head&amp;quot;&amp;gt;चरण 2 : प्री-लोडिंग स्क्रिप्ट में `&amp;amp;lt;head&amp;amp;gt;&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समाधान_का_दिल&amp;quot;&amp;gt;समाधान का दिल&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_स्क्रिप्ट_की_अनाटॉमी_हर_पंक्ति_मायने_रखती_है&amp;quot;&amp;gt;स्क्रिप्ट की अनाटॉमी : हर पंक्ति मायने रखती है&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सिस्टम_प्राथमिकता_का_पता_लगाना_बोनस&amp;quot;&amp;gt;सिस्टम प्राथमिकता का पता लगाना (बोनस)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_प्रदर्शन_यह_स्क्रिप्ट_तेज़_क्यों_है&amp;quot;&amp;gt;प्रदर्शन : यह स्क्रिप्ट तेज़ क्यों है&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_head_में_इष्टतम_स्थान&amp;quot;&amp;gt;&amp;amp;lt;head&amp;amp;gt;` में इष्टतम स्थान&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_3_css_एट्रिब्यूट_सेलेक्टर्स_की_शक्ति&amp;quot;&amp;gt;चरण 3 : CSS एट्रिब्यूट सेलेक्टर्स की शक्ति&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_बूटस्ट्रैप_5_थीम_सिस्टम&amp;quot;&amp;gt;बूटस्ट्रैप 5 थीम सिस्टम&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_css_संरचना_एक_थीम_सिस्टम_के_लिए&amp;quot;&amp;gt;CSS संरचना एक थीम सिस्टम के लिए&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_रिज़्यूमे&amp;quot;&amp;gt;रिज़्यूमे&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस गहन तकनीकी लेख में, हम देखते हैं कि कैसे पेज लोड होने पर होने वाले कष्टप्रद चमकते प्रभाव के बिना एक थीम (लाइट/डार्क) सेलेक्टर को लागू किया जाए। हम ब्राउज़र रेंडरिंग चक्र का विस्तृत विश्लेषण करते हैं, FOUC (फ़्लैश ऑफ़ 언स्टाइल्ड कंटेंट) के मूल कारणों की पहचान करते हैं, और सिंक्रोनस प्री-लोडिंग पर आधारित एक मज़बूत समाधान प्रस्तुत करते हैं।&amp;lt;code&amp;gt;&amp;amp;lt;head&amp;amp;gt;&amp;lt;/code&amp;gt;। यह तकनीक एक सुचारू और पेशेवर उपयोगकर्ता अनुभव सुनिश्चित करती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या_इस_अभिशप्त_थीम_का_झिलमिलाना&amp;quot;&amp;gt;समस्या: इस अभिशप्त थीम का झिलमिलाना&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_उपयोगकर्ता_अनुभव_के_लिए_एक_दुःस्वप्न&amp;quot;&amp;gt;उपयोगकर्ता अनुभव के लिए एक दुःस्वप्न&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;कल्पना कीजिए कि आपने अपने वेब एप्लिकेशन के लिए एक सुंदर डार्क थीम बनाने में घंटों बिता दिए हैं। रंग पूरी तरह संतुलित हैं, विपरीतता अनुकूल है, और आपके उपयोगकर्ता इस विकल्प से प्यार करते हैं। लेकिन एक शर्मिंदगी भरी समस्या है: हर बार पेज रीलोड होने पर, एक क्षण के लिए डिफ़ॉल्ट लाइट थीम दिखाई देती है, इससे पहले कि डार्क थीम सक्रिय हो।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह &amp;quot;फ़्लैश&amp;quot; दृश्य, यद्यपि संक्षिप्त (कभी‑कभी 100ms से कम), मानव आंख द्वारा तुरंत अनुभव किया जाता है और एक असहज अनुभव उत्पन्न करता है। उन उपयोगकर्ताओं के लिए जो दृष्टि सुविधा या पहुँच के कारण डार्क थीम चुनते हैं, यह झिलमिलाहट दर्दनाक भी हो सकती है, विशेष रूप से कम रोशनी वाले वातावरण में।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_फ़ouc_एक_पुराना_वेब_समस्या&amp;quot;&amp;gt;फ़OUC : एक पुराना वेब समस्या&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह घटना वह चीज की एक विविधता है जिसको &amp;#39;फ़्लैश ऑफ़ अनस्टाइल्ड कंटेंट&amp;#39; (FOUC) कहा जाता है, जो वेब विकास की एक क्लासिक समस्या है जो सीएसएस के प्रारंभिक दिनों तक वापस जाती है। FOUC तब होता है जब ब्राउज़र अस्थायी रूप से CSS शैलियों के बिना HTML सामग्री प्रदर्शित करता है, जिससे अनस्टाइल्ड सामग्री का फ़्लैश बनता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारे विशिष्ट मामले में, हम पूरी तरह से अनस्टाइल्ड सामग्री के बारे में बात नहीं कर रहे हैं, बल्कि एक के बारे में हैं&amp;lt;strong&amp;gt;गलत थीम का फ्लैश&amp;lt;/strong&amp;gt;(FOWT) - सामग्री स्टाइल की गई है, लेकिन गलत थीम के साथ। यह विशेष रूप से निराशाजनक है क्योंकि यह दर्शाता है कि हमारा एप्लिकेशन &amp;quot;भूल&amp;quot; जाती है कि उपयोगकर्ता की प्राथमिकता प्रत्येक पृष्ठ लोड पर।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_गुणवत्ता_की_धारणा_पर_प्रभाव&amp;quot;&amp;gt;गुणवत्ता की धारणा पर प्रभाव&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह समस्या, हालांकि तकनीकी है, आपके अनुप्रयोग की गुणवत्ता की धारणा पर महत्वपूर्ण प्रभाव डालती है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;पॉलिश की कमी&amp;lt;/strong&amp;gt;: झिलमिलाहट से ऐसा प्रतीत होता है कि एप्लिकेशन अपूर्ण है या अनुकूलित नहीं की गई है। उपयोगकर्ता अक्सर इन छोटे दृश्य दोषों को समग्र रूप से पेशेवरता की कमी से जोड़ते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;संगतता का भंग&amp;lt;/strong&amp;gt;: एप्लिकेशन प्रतीत होता है कि वह उपयोगकर्ता की प्राथमिकताओं को &amp;quot;भूल&amp;quot; रही है, जिससे इंटरफ़ेस और अपेक्षाओं के बीच असंतुलन की भावना उत्पन्न होती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;आँखों की थकान&amp;lt;/strong&amp;gt;: रोशनी के प्रति संवेदनशील उपयोगकर्ताओं या माइग्रेन से पीड़ित लोगों के लिए, यह रोशनी भरी फ़्लैश सिर्फ़ एक साधारण सौंदर्य संबंधित असुविधा से अधिक हो सकता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;अनुभूत प्रदर्शन&amp;lt;/strong&amp;gt;: विडंबना यह है कि, भले ही आपकी साइट तेज़ी से लोड हो, इस ब्लिंकिंग से ऐसा प्रतीत हो सकता है कि एप्लिकेशन धीमी या अप्रतिक्रियाशील है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_समस्या_का_तकनीकी_विश्लेषण&amp;quot;&amp;gt;समस्या का तकनीकी विश्लेषण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;समस्या को हल करने के तरीके को समझने के लिए, सबसे पहले यह समझना होगा कि यह क्यों होता है। झिलमिलाहट एक वेब पृष्ठ के जीवन चक्र में तीन महत्वपूर्ण घटनाओं के बीच समय में अंतराल के कारण होती है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;HTML का प्रारम्भिक पर्सिंग&amp;lt;/strong&amp;gt;ब्राउज़र आपके पेज की संरचना को पढ़ता और विश्लेषण करता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;सीएसएस शैलियों का अनुप्रयोग&amp;lt;/strong&amp;gt;ब्राउज़र CSS नियम लागू करता है और दृश्य प्रस्तुति की गणना करता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;जावास्क्रिप्ट का निष्पादन&amp;lt;/strong&amp;gt;: आपका कोड जो थीम बदलता है चल रहा है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;समस्या तब होती है जब घटना क्रमांक 3 (JavaScript का निष्पादन) ब्राउज़र द्वारा पहले से ही शुरू किए गए या समाप्त किए गए घटना क्रमांक 2 (स्टाइलिंग लागू करने की प्रक्रिया) के बाद होती है। उस समय, ब्राउज़र पहले से ही यह निर्णय ले चुका होता है कि कौन सी थीम दिखाएँ, और आपका कोड पहले रेंडर से पहले इसे प्रभावित करने के लिए बहुत देर से आता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_क्लासिक_स्क्रिप्ट_क्यों_पर्याप्त_नहीं_है&amp;quot;&amp;gt;क्लासिक स्क्रिप्ट क्यों पर्याप्त नहीं है?&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_अनुभवी_लेकिन_अप्रभावी_दृष्टिकोण&amp;quot;&amp;gt;अनुभवी लेकिन अप्रभावी दृष्टिकोण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक डेवलपर के लिए सबसे प्राकृतिक दृष्टिकोण यह होगा कि हम हमारे के अंत में एक स्क्रिप्ट रखें`&amp;amp;lt;body&amp;amp;gt;`जो उपयोगकर्ता के पसंदीदा विषय की जाँच करता है और उसे लागू करता है। यह दृष्टिकोण वेब की पारंपरिक सर्वोत्तम प्रथाओं का पालन करता है, जो पेज के अंत में स्क्रिप्ट लोड करने की सिफारिश करते हैं ताकि रेंडरिंग को ब्लॉक न किया जाए।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;// À la fin de &amp;amp;lt;body&amp;amp;gt; - L&amp;#39;APPROCHE INSUFFISANTE
document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;amp;gt; {
  const theme = localStorage.getItem(&amp;#39;preferred-theme&amp;#39;);
  if (theme === &amp;#39;dark&amp;#39;) {
    document.documentElement.setAttribute(&amp;#39;data-bs-theme&amp;#39;, &amp;#39;dark&amp;#39;);
  }
});&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह दृष्टिकोण पहली नज़र में तर्कसंगत लगता है। हम DOM के तैयार होने का इंतज़ार करते हैं, फिर हम थीम लागू करते हैं। सरल, नहीं? दुर्भाग्य से, इस सरलता में ब्राउज़र के रेंडरिंग चक्र के टाइमिंग से संबंधित एक मौलिक दोष छिपा हुआ है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_domcontentloaded_इवेंट_को_समझें&amp;quot;&amp;gt;DOMContentLoaded इवेंट को समझें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;घटना`DOMContentLoaded`यह तब ट्रिगर होता है जब प्रारंभिक HTML दस्तावेज़ पूरी तरह से लोड हो गया हो और ब्राउज़र द्वारा पार्स किया गया हो,&amp;lt;strong&amp;gt;इंतज़ार किए बिना&amp;lt;/strong&amp;gt;स्टाइल शीट्स, इमेज और सब-फ़्रेम्स के लोडिंग का अंत। यह समझने के लिए एक महत्वपूर्ण बिंदु है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ घटनाओं का सामान्य अनुक्रम है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;ब्राउज़र HTML डाउनलोड करना शुरू करता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;यह HTML का विश्लेषण करता है जैसे ही इसे प्राप्त होता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;वह टैग खोजता है`&amp;amp;lt;link&amp;amp;gt;`CSS के लिए और उन्हें डाउनलोड करना शुरू करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;वह टैग खोजता है`&amp;amp;lt;script&amp;amp;gt;`और उन्हें निष्पादित करता है (उनके प्रकार और विशेषताओं के अनुसार)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;वह DOM (Document Object Model) बनाता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;घटना &amp;lt;code&amp;gt;DOMContentLoaded&amp;lt;/code&amp;gt; ट्रिगर होती है&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;वह शैलियों को लागू करना जारी रखता है और लेआउट बनाता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;पहला पेंट (प्रदर्शन) होता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;घटना`load`जब सभी संसाधन लोड हो जाते हैं, तब यह ट्रिगर होता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;समस्या ? के बीच चरण 6 (DOMContentLoaded) और चरण 8 (premier paint), ब्राउज़र ने पहले ही निर्णय ले लिए हैं कि पेज को कैसे दिखाना है। यदि आपके थीम बदलने वाला स्क्रिप्ट चरण 6 पर चलता है, यह पहले ही बहुत देर हो चुकी है डिफ़ॉल्ट स्टाइल के साथ पहले प्रदर्शन से बचने के लिए।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_रेंडर_ब्लॉकिंग_की_समस्या&amp;quot;&amp;gt;रेंडर ब्लॉकिंग की समस्या&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;वास्तव में, टाइमिंग और भी जटिल है। आधुनिक ब्राउज़र अनुभव की गई प्रदर्शन को बेहतर बनाने के लिए परिष्कृत अनुकूलन तकनीकों का उपयोग करते हैं। वे उपयोगकर्ता को स्क्रीन पर कुछ दिखाने के लिए पहले पेंट (First Contentful Paint) को जितना संभव हो सके जल्दी करने की कोशिश करते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;CSS डिफ़ॉल्ट रूप से &amp;quot;render-blocking&amp;quot; होते हैं, जिसका अर्थ है कि ब्राउज़र पहला पेंट करने से पहले स्टाइलशीट डाउनलोड और पार्स करने की प्रतीक्षा करता है। यह तर्कसंगत है: हम असामयिक सामग्री प्रदर्शित नहीं करना चाहते।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;लेकिन यहाँ जाल है : जब ब्राउज़र इन CSS स्टाइल को पहली बार लागू करता है, तो वह वर्तमान DOM स्थिति के आधार पर ऐसा करता है। यदि विशेषता`data-bs-theme`अभी तक टैग पर परिभाषित नहीं है`&amp;amp;lt;html&amp;amp;gt;`, ब्राउज़र डिफ़ॉल्ट स्टाइल लागू करेगा (सामान्यतः हल्का थीम).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फिर, जब आपका स्क्रिप्ट चलता है और इस विशेषता को बदलता है, ब्राउज़र को करना चाहिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;इस बदलाव से प्रभावित सभी शैलियों की गणना फिर से करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;यदि आवश्यक हो तो लेआउट फिर से तैयार करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;प्रभावित तत्वों को फिर से रंगें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह पुनःगणना और फिर से चित्रण की प्रक्रिया है जो दृश्यमान चमक का कारण बनती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_समस्या_का_दृश्यीकरण&amp;quot;&amp;gt;समस्या का दृश्यीकरण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस समस्याग्रस्त अनुक्रम को बेहतर ढंग से समझने के लिए, एक विस्तृत अनुक्रम आरेख की जाँच करते हैं:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;diag-flux-incorrect&amp;quot; class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-deed73a8dfdc5320a576263eb3e8285f.svg&amp;quot; alt=&amp;quot;Diagramme de séquence du chargement incorrect&amp;quot; width=&amp;quot;1595&amp;quot; height=&amp;quot;666&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह आरेख स्पष्ट रूप से समस्या को दर्शाता है: पहला paint तब होता है जब हमारा स्क्रिप्ट सही विषय सेट करने का अवसर प्राप्त नहीं कर पाता। अनुक्रमिक repaint दृश्यमान झिलमिलाहट उत्पन्न करता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_असफल_समाधान_प्रयास&amp;quot;&amp;gt;असफल समाधान प्रयास&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;कई दृष्टिकोण इस समस्या को हल करने के प्रयास में अपनाए गए थे, लेकिन अधिकांश में अपने स्वयं के नुकसान हैं :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;पद्धति 1 : लोड होने तक सामग्री को छिपाएँ&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-css&amp;quot; data-lang=&amp;quot;css&amp;quot;&amp;gt;body {
  opacity: 0;
  transition: opacity 0.3s;
}

body.loaded {
  opacity: 1;
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह दृष्टिकोण तब तक सभी सामग्री को कैश करता है जब तक JavaScript सही विषय सेट नहीं कर देता। समस्या? यह कृत्रिम रूप से सामग्री के प्रदर्शन को देरी देता है, जिससे साइट धीमी लगती है। इसके अलावा, यदि JavaScript अक्षम है, तो उपयोगकर्ता कुछ भी नहीं देखता!&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;दृष्टिकोण 2 : एक लोडर/स्पिनर का उपयोग करें&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;प्रवेश 1 के समान, लेकिन एक लोडिंग स्पिनर के साथ। यह समस्या को छिपाता है लेकिन वास्तविक प्रदर्शन में सुधार नहीं करता और अनावश्यक अनुभवित देरी जोड़ता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;पद्धति 3: डिफ़ॉल्ट रूप से डार्क थीम&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;कुछ डेवलपर्स CSS में डार्क थीम को डिफ़ॉल्ट के रूप में सेट करते हैं। यह डार्क थीम उपयोगकर्ताओं के लिए फ्लिकरिंग को रोकता है, लेकिन हल्की थीम उपयोगकर्ताओं के लिए विपरीत समस्या पैदा करता है !&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इनमें से कोई भी दृष्टिकोण संतोषजनक नहीं है, क्योंकि वे समस्या के लक्षण का इलाज करते हैं, जड़ कारण का नहीं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_वास्तविक_समाधान_जल्दी_कार्य_करें&amp;quot;&amp;gt;वास्तविक समाधान : जल्दी कार्य करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस समस्या को हल करने की कुंजी यह समझना है कि हमें उस एट्रिब्यूट को परिभाषित करना होगा।&amp;lt;code&amp;gt;data-bs-theme&amp;lt;/code&amp;gt; &amp;lt;strong&amp;gt;पहले&amp;lt;/strong&amp;gt;कि ब्राउज़र CSS स्टाइल लगाना शुरू नहीं करता। इसका अर्थ है कि हमारा स्क्रिप्ट पृष्ठ के जीवन चक्र में पहले चलना चाहिए, और यही वह बात है जिसका हम अगले खंड में अन्वेषण करेंगे।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समाधान_पूर्व_लोडिंग_early_loading&amp;quot;&amp;gt;समाधान : पूर्व लोडिंग (Early Loading)&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_मूल_सिद्धांत&amp;quot;&amp;gt;मूल सिद्धांत&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारी झिलमिलाहट समस्या का सुंदर समाधान एक सरल लेकिन शक्तिशाली सिद्धांत पर आधारित है:&amp;lt;strong&amp;gt;ब्राउज़र रेंडरिंग प्रक्रिया के साथ एप्लिकेशन की स्थिति को सिंक्रोनाइज़ करना&amp;lt;/strong&amp;gt;. पेज लोड होने का इंतज़ार करने के बजाय, हमें थीम सेट कर देना चाहिए&amp;lt;strong&amp;gt;के दौरान&amp;lt;/strong&amp;gt;लोड हो रहा है, इससे पहले भी कि CSS शैलियाँ लागू हो जाएँ।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह दृष्टिकोण &amp;quot;Early Loading&amp;quot; या &amp;quot;Synchronous Preloading&amp;quot; वेब विकास के शब्दजाल में कहा जाता है। इस विचार का उद्देश्य हमारे थीम डिटेक्शन लॉजिक को पृष्ठ के जीवन चक्र में हो सकने वाले सबसे पहले चरण में निष्पादित करना है, आदर्श रूप से टैग में।&amp;lt;code&amp;gt;&amp;amp;lt;head&amp;amp;gt;&amp;lt;/code&amp;gt;, भले ही ब्राउज़र CSS फ़ाइलों को डाउनलोड करना शुरू न करे.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_क्यों_head_आदर्श_स्थान_है&amp;quot;&amp;gt;क्यों &amp;lt;code&amp;gt;&amp;amp;lt;head&amp;amp;gt;&amp;lt;/code&amp;gt; आदर्श स्थान है&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le `&amp;amp;lt;head&amp;amp;gt;`एक HTML दस्तावेज़ को ब्राउज़र द्वारा क्रमिक रूप से ऊपर से नीचे तक प्रसंस्कृत किया जाता है। प्रत्येक तत्व उस क्रम में प्रसंस्कृत किया जाता है जिसमें वह दिखाई देता है। यह विशेषता हमारे समाधान के लिए अत्यंत महत्वपूर्ण है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जब ब्राउज़र एक टैग से मिलता है`&amp;amp;lt;script&amp;amp;gt;`में`&amp;amp;lt;head&amp;amp;gt;` sans les attributs &amp;lt;code&amp;gt;async&amp;lt;/code&amp;gt; ou &amp;lt;code&amp;gt;defer&amp;lt;/code&amp;gt;, il :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;HTML का पर्सिंग रोकें&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;स्क्रिप्ट डाउनलोड करें&amp;lt;/strong&amp;gt;(यदि बाह्य) या बिस्तर (यदि इनलाइन)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;स्क्रिप्ट को तुरंत निष्पादित करें&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;HTML का पार्सिंग फिर से शुरू करें&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह व्यवहार, अक्सर प्रदर्शन समस्या माना जाता है (जिस कारण से सामान्य सिफ़ारिश पेज के अंत में स्क्रिप्ट रखने की होती है), इस विशेष स्थिति में हमारा सहयोगी बन जाता है। अपना थीम डिटेक्शन स्क्रिप्ट पृष्ठ के शुरू में रखकर`&amp;amp;lt;head&amp;amp;gt;`, हम गारंटी देते हैं कि यह ब्राउज़र टैग्स से मिलने से पहले चलता है`&amp;amp;lt;link&amp;amp;gt;`हमारे स्टाइल शीट्स के.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_समाधान_की_तीन_स्तरीय_आर्किटेक्चर&amp;quot;&amp;gt;समाधान की तीन-स्तरीय आर्किटेक्चर&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारा पूर्ण समाधान तीन परस्पर निर्भर परतों से बना है, प्रत्येक एक विशिष्ट भूमिका निभाती है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;परत 1 : स्थायित्व (localStorage)&amp;lt;/strong&amp;gt; यह परत उपयोगकर्ता के चयन को सत्रों के बीच संग्रहीत और पुनः प्राप्त करने के लिए जिम्मेदार है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;लेयर 2: प्रारंभिक सिंक्रोनाइज़ेशन (इनलाइन स्क्रिप्ट &amp;lt;code&amp;gt;&amp;amp;lt;head&amp;amp;gt;&amp;lt;/code&amp;gt; में)&amp;lt;/strong&amp;gt; यह लेयर प्रारंभिक रेंडरिंग से पहले एप्लिकेशन की स्थिति को DOM के साथ सिंक्रनाइज़ करती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;लेयर 3: रिएक्टिव स्टाइल (CSS एट्रिब्यूट चयनकर्ता के साथ)&amp;lt;/strong&amp;gt; यह लेयर लेयर 2 द्वारा परिभाषित स्थिति के आधार पर दृश्य शैलियों को परिभाषित करती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अब हम प्रत्येक परत का विस्तृत अन्वेषण करते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_चरण_1_उपयोगकर्ता_की_पसंद_को_सेव_करना&amp;quot;&amp;gt;चरण 1 : उपयोगकर्ता की पसंद को सेव करना&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_localstorage_आपकी_स्थायी_स्मृति&amp;quot;&amp;gt;localStorage : आपकी स्थायी स्मृति&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Le &amp;lt;code&amp;gt;localStorage`यह एक Web Storage API है जो ब्राउज़र में लगातार आधार पर कुंजी‑मूल्य युग्मों को संग्रहीत करने की अनुमति देती है। कुकीज़ के विपरीत, डेटा`localStorage&amp;lt;/code&amp;gt;:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;इन्हें कभी भी सर्वर पर स्वचालित रूप से नहीं भेजा जाता&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;उनके पास अधिक स्टोरेज क्षमता होती है (आमतौर पर 5-10 एमबी)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;उनकी समाप्ति तिथि नहीं होती (स्पष्ट रूप से हटाने तक निरंतर)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;इनका सीमित प्रोटोकॉल और डोमेन (Same-Origin Policy) तक सीमित है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारे उपयोग केस के लिए`localStorage`यह सही है क्योंकि :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;हमें इस जानकारी को सर्वर के साथ साझा करने की आवश्यकता नहीं है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;हम चाहते हैं कि प्राथमिकता अनिश्चितकाल तक बनी रहे&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आवश्यक भंडारण आकार न्यूनतम है (कुछ बाइट्स)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_थीम_बैकअप_का_कार्यान्वयन&amp;quot;&amp;gt;थीम बैकअप का कार्यान्वयन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ बताया गया है कि हम उपयोगकर्ता के विकल्प को कैसे सहेजते हैं जब वह थीम बदलता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;// Fonction complète pour changer le thème
function setTheme(newTheme) {
  // Validation de l&amp;#39;entrée
  if (![&amp;#39;light&amp;#39;, &amp;#39;dark&amp;#39;, &amp;#39;auto&amp;#39;].includes(newTheme)) {
    console.error(&amp;#39;Thème invalide:&amp;#39;, newTheme);
    return;
  }

  try {
    // Sauvegarde dans localStorage
    localStorage.setItem(&amp;#39;preferred-theme&amp;#39;, newTheme);

    // Application immédiate dans le DOM
    document.documentElement.setAttribute(&amp;#39;data-bs-theme&amp;#39;, newTheme);

    // Dispatch d&amp;#39;un événement personnalisé pour notifier d&amp;#39;autres composants
    window.dispatchEvent(new CustomEvent(&amp;#39;theme-changed&amp;#39;, {
      detail: { theme: newTheme }
    }));

    console.log(&amp;#39;Thème changé:&amp;#39;, newTheme);
  } catch (error) {
    console.error(&amp;#39;Erreur lors de la sauvegarde du thème:&amp;#39;, error);
    // Fallback : on applique quand même le thème visuellement
    document.documentElement.setAttribute(&amp;#39;data-bs-theme&amp;#39;, newTheme);
  }
}

// Exemple d&amp;#39;utilisation avec un bouton
document.getElementById(&amp;#39;theme-toggle&amp;#39;).addEventListener(&amp;#39;click&amp;#39;, () =&amp;amp;gt; {
  const currentTheme = document.documentElement.getAttribute(&amp;#39;data-bs-theme&amp;#39;) || &amp;#39;light&amp;#39;;
  const newTheme = currentTheme === &amp;#39;light&amp;#39; ? &amp;#39;dark&amp;#39; : &amp;#39;light&amp;#39;;
  setTheme(newTheme);
});&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_त्रुटि_मामलों_का_प्रबंधन&amp;quot;&amp;gt;त्रुटि मामलों का प्रबंधन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह महत्वपूर्ण है कि मामलों को प्रबंधित किया जाए जहाँ वह`localStorage`उपलब्ध या सुलभ नहीं है। कई परिदृश्य एक्सेस को रोक सकते हैं`localStorage`:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;सख्त निजी नेविगेशन&amp;lt;/strong&amp;gt;सफ़ारी निजी ब्राउज़िंग मोड में एक अपवाद फेंकता है`QuotaExceededError`लिखने के प्रयासों के दौरान में`localStorage`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;गोपनीयता सेटिंग्स&amp;lt;/strong&amp;gt;: कुछ ब्राउज़र या गोपनीयता एक्सटेंशन एक्सेस को ब्लॉक कर सकते हैं`localStorage`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;डोमेन की सीमाएँ&amp;lt;/strong&amp;gt; : Le `localStorage`यह प्रोटोकॉल पर सुलभ नहीं है`file://`कुछ ब्राउज़र में।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;भंडारण स्थान भर गया&amp;lt;/strong&amp;gt;हालांकि दुर्लभ, भंडारण स्थान पूरी तरह से भर सकता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इसलिए हमारा कोड एक ब्लॉक का उपयोग करता है`try&amp;amp;#8230;&amp;amp;#8203;catch`इन स्थितियों को शालीनता से संभालने के लिए, भले ही स्थायित्व उपलब्ध न हो, थीम बदलने की सुविधा प्रदान करना जारी रखें।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_अधिक_उन्नत_निरंतरता_रणनीतियाँ&amp;quot;&amp;gt;अधिक उन्नत निरंतरता रणनीतियाँ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अधिक जटिल अनुप्रयोगों के लिए, आप अतिरिक्त रणनीतियों पर विचार कर सकते हैं :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;सर्वर सिंक्रोनाइज़ेशन (वैकल्पिक)&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;async function setTheme(newTheme) {
  // Sauvegarde locale immédiate
  localStorage.setItem(&amp;#39;preferred-theme&amp;#39;, newTheme);
  document.documentElement.setAttribute(&amp;#39;data-bs-theme&amp;#39;, newTheme);

  // Synchronisation serveur en arrière-plan (si l&amp;#39;utilisateur est connecté)
  if (userIsAuthenticated()) {
    try {
      await fetch(&amp;#39;/api/user/preferences&amp;#39;, {
        method: &amp;#39;POST&amp;#39;,
        headers: { &amp;#39;Content-Type&amp;#39;: &amp;#39;application/json&amp;#39; },
        body: JSON.stringify({ theme: newTheme })
      });
    } catch (error) {
      console.warn(&amp;#39;Échec de la synchronisation serveur:&amp;#39;, error);
      // L&amp;#39;échec n&amp;#39;est pas critique car la préférence est déjà sauvegardée localement
    }
  }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह दृष्टिकोण लॉग इन उपयोगकर्ताओं के लिए उपकरणों के बीच प्राथमिकताओं को सिंक्रनाइज़ करने की अनुमति देता है, जबकि तत्काल स्थानीय प्रतिक्रिया बनाए रखता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_चरण_2_प्री_लोडिंग_स्क्रिप्ट_में_head&amp;quot;&amp;gt;चरण 2 : प्री-लोडिंग स्क्रिप्ट में `&amp;amp;lt;head&amp;amp;gt;&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_समाधान_का_दिल&amp;quot;&amp;gt;समाधान का दिल&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ वास्तव में जादू होता है। हम एक छोटा स्क्रिप्ट लगाएँगे।&amp;lt;strong&amp;gt;इनलाइन&amp;lt;/strong&amp;gt;हमारे में सीधे`&amp;amp;lt;head&amp;amp;gt;`, सभी हमारे टैग से पहले`&amp;amp;lt;link&amp;amp;gt;`शैली शीट्स की. यह स्क्रिप्ट जानबूझकर न्यूनतम, स्वतंत्र, और सबसे तेज़ तरीके से चलाने के लिए डिज़ाइन किया गया है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;!DOCTYPE html&amp;amp;gt;
&amp;amp;lt;html lang=&amp;quot;fr&amp;quot;&amp;amp;gt;
&amp;amp;lt;head&amp;amp;gt;
    &amp;amp;lt;meta charset=&amp;quot;UTF-8&amp;quot;&amp;amp;gt;
    &amp;amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0&amp;quot;&amp;amp;gt;
    &amp;amp;lt;title&amp;amp;gt;Mon Site Incroyable&amp;amp;lt;/title&amp;amp;gt;

    &amp;amp;lt;!-- ==========================================
         NOTRE SCRIPT MAGIQUE DE PRÉ-CHARGEMENT
         Ce script DOIT être le premier élément
         dans le &amp;amp;lt;head&amp;amp;gt; après les meta tags
         ========================================== --&amp;amp;gt;
    &amp;amp;lt;script&amp;amp;gt;
      // IIFE pour ne pas polluer le scope global
      (function() {
        &amp;#39;use strict&amp;#39;;

        try {
          // Lecture de la préférence sauvegardée
          const savedTheme = localStorage.getItem(&amp;#39;preferred-theme&amp;#39;);

          // Si une préférence existe, on l&amp;#39;applique immédiatement
          if (savedTheme) {
            document.documentElement.setAttribute(&amp;#39;data-bs-theme&amp;#39;, savedTheme);
          }
          // Optionnel : Détecter la préférence système si aucune sauvegarde
          else if (window.matchMedia &amp;amp;amp;&amp;amp;amp; window.matchMedia(&amp;#39;(prefers-color-scheme: dark)&amp;#39;).matches) {
            document.documentElement.setAttribute(&amp;#39;data-bs-theme&amp;#39;, &amp;#39;dark&amp;#39;);
          }
          // Sinon, le thème par défaut du CSS sera utilisé (généralement &amp;#39;light&amp;#39;)

        } catch (error) {
          // En cas d&amp;#39;erreur (localStorage bloqué, etc.), on log discrètement
          // et on laisse le thème par défaut s&amp;#39;appliquer
          console.warn(&amp;#39;Impossible de charger la préférence de thème:&amp;#39;, error);
        }
      })();
    &amp;amp;lt;/script&amp;amp;gt;
    &amp;amp;lt;!-- FIN DU SCRIPT MAGIQUE --&amp;amp;gt;

    &amp;amp;lt;!-- Les feuilles de style sont chargées APRÈS le script --&amp;amp;gt;
    &amp;amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;css/bootstrap.min.css&amp;quot;&amp;amp;gt;
    &amp;amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;css/styles.css&amp;quot;&amp;amp;gt;

    &amp;amp;lt;!-- Autres ressources du head --&amp;amp;gt;
    &amp;amp;lt;link rel=&amp;quot;icon&amp;quot; href=&amp;quot;favicon.ico&amp;quot;&amp;amp;gt;
&amp;amp;lt;/head&amp;amp;gt;
&amp;amp;lt;body&amp;amp;gt;
    &amp;amp;lt;!-- Contenu de la page --&amp;amp;gt;
&amp;amp;lt;/body&amp;amp;gt;
&amp;amp;lt;/html&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_स्क्रिप्ट_की_अनाटॉमी_हर_पंक्ति_मायने_रखती_है&amp;quot;&amp;gt;स्क्रिप्ट की अनाटॉमी : हर पंक्ति मायने रखती है&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस स्क्रिप्ट को प्रत्येक पंक्ति में तोड़कर समझते हैं कि प्रत्येक डिज़ाइन निर्णय क्यों लिया गया :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;IIFE (तुरंत बुलाया गया फ़ंक्शन अभिव्यक्ति)&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;(function() {
  // ...
})();&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह संरचना एक फ़ंक्शन बनाती है जो तुरंत निष्पादित होती है। क्यों? ताकि हम अपने चर को एक स्थानीय स्कोप में अलग कर सकें और वैश्विक स्कोप को प्रदूषित होने से बचा सकें। भले ही हम केवल उपयोग करें`const`(जिसका ब्लॉक स्कोप होता है), IIFE एक अच्छी प्रथा है जो हमारे इरादों को स्पष्ट करती है और संभावित नाम संघर्षों से बचाती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;कड़ा मोड&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;&amp;#39;use strict&amp;#39;;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह निर्देश जावास्क्रिप्ट के कड़ाई मोड को सक्रिय करता है, जो : - अघोषित चर के उपयोग को प्रतिबंधित करता है - Génère des erreurs pour les opérations dangereuses कुछ जावास्क्रिप्ट इंजनों में प्रदर्शन में सुधार लाता है&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस तरह के गंभीर स्क्रिप्ट के लिए, हम अधिकतम सुरक्षा चाहते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;ब्लॉक try&amp;amp;#8230;&amp;amp;#8203;catch&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;try {
  // Code principal
} catch (error) {
  console.warn(&amp;#39;Impossible de charger la préférence de thème:&amp;#39;, error);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह ब्लॉक अत्यंत महत्वपूर्ण है। यह सुनिश्चित करता है कि यदि कुछ गलत हो जाता है (localStorage ब्लॉक, असंभाव्य सिंटैक्स त्रुटि, आदि.), तो हमारा स्क्रिप्ट पूरी पृष्ठ लोड को अवरुद्ध नहीं करेगा। का उपयोग`console.warn`इसके बजाय`console.error`इंगित करता है कि यह एक गंभीर समस्या नहीं है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;localStorage की पढ़ाई&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;const savedTheme = localStorage.getItem(&amp;#39;preferred-theme&amp;#39;);&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह पंक्ति कुछ संदर्भों में (सफारी की सख्त निज़ी नेविगेशन) में एक अपवाद उठा सकती है। इसलिए यह एक try&amp;amp;#8230;&amp;amp;#8203;catch ब्लॉक में है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;शर्ती आवेदन&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;if (savedTheme) {
  document.documentElement.setAttribute(&amp;#39;data-bs-theme&amp;#39;, savedTheme);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हम केवल तभी थीम लागू करते हैं जब हमें एक संग्रहीत थीम मिली हो। अन्यथा, हम CSS को अपने डिफ़ॉल्ट थीम का उपयोग करने देते हैं। यह दृष्टिकोण जावास्क्रिप्ट में हार्ड-कोडेड डिफ़ॉल्ट मान की तुलना में अधिक मजबूत है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सिस्टम_प्राथमिकता_का_पता_लगाना_बोनस&amp;quot;&amp;gt;सिस्टम प्राथमिकता का पता लगाना (बोनस)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक वैकल्पिक लेकिन शालीन सुधार यह है कि यदि उपयोगकर्ता आपके एप्लिकेशन में अभी तक स्पष्ट विकल्प नहीं चुना है, तो ऑपरेटिंग सिस्टम की थीम प्राथमिकता का पता लगाया जाता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;else if (window.matchMedia &amp;amp;amp;&amp;amp;amp; window.matchMedia(&amp;#39;(prefers-color-scheme: dark)&amp;#39;).matches) {
  document.documentElement.setAttribute(&amp;#39;data-bs-theme&amp;#39;, &amp;#39;dark&amp;#39;);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह सुविधा मीडिया क्वेरी का उपयोग करती है`prefers-color-scheme`सिस्टम को पूछने के लिए। macOS, Windows 10+, iOS, और आधुनिक Android पर, यह प्रश्न उपयोगकर्ता की सिस्टम प्राथमिकता लौटाता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;फ़ायदे :&amp;lt;/strong&amp;gt; - व्यक्तिगत अनुभव पहली यात्रा से - संगतता के साथ उपयोगकर्ता का प्रणाली पर्यावरण - पहली यात्रा के लिए कोई भंडारण आवश्यक नहीं&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;विचार :&amp;lt;/strong&amp;gt; सभी ब्राउज़र इस सुविधा का समर्थन नहीं करते हैं (लेकिन 2020 से समर्थन उत्कृष्ट रहा है) - सत्यापन`window.matchMedia`संगतता सुनिश्चित करता है - उपयोगकर्ता हमेशा इस विकल्प को ओवरराइड कर सकता है&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_प्रदर्शन_यह_स्क्रिप्ट_तेज़_क्यों_है&amp;quot;&amp;gt;प्रदर्शन : यह स्क्रिप्ट तेज़ क्यों है&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारा प्री-लोड स्क्रिप्ट बेहद तेज़ होने के लिए डिज़ाइन किया गया है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;न्यूनतम आकार&amp;lt;/strong&amp;gt;लगभग 300 बाइट्स अनमिनिफ़ाइड, 200 बाइट्स मिनिफ़ाइड। यह किसी भी इमेज या जावास्क्रिप्ट लाइब्रेरी की तुलना में नगण्य है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;इनलाइन&amp;lt;/strong&amp;gt;को अतिरिक्त HTTP अनुरोध नहीं है। स्क्रिप्ट HTML में है, इसलिए यह तुरंत उपलब्ध है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;सादे समकालिक संचालन&amp;lt;/strong&amp;gt;localStorage में एक कुंजी पढ़ना (अत्यंत तेज़ संचालन) और DOM विशेषता संशोधन (ब्राउज़र का मूल संचालन).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;कोई निर्भरता नहीं&amp;lt;/strong&amp;gt;: कोई फ्रेमवर्क नहीं, कोई लाइब्रेरी नहीं, केवल वैनिला JavaScript। कोई स्टार्टअप समय नहीं, कोई डिपेंडेंसी पार्सिंग नहीं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;एकल निष्पादन&amp;lt;/strong&amp;gt;यह स्क्रिप्ट लोड होने पर केवल एक बार चलती है। कोई इवेंट लिस्नर नहीं, कोई लूप नहीं, कोई जटिल गणना नहीं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;व्यावहारिक रूप से, आधुनिक हार्डवेयर पर, यह स्क्रिप्ट 1 मिलीसेकंड से कम समय में चलती है – एक अवलगनीय समय जो पृष्ठ लोड होने के प्रदर्शन पर कोई प्रभाव नहीं डालता।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_head_में_इष्टतम_स्थान&amp;quot;&amp;gt;&amp;amp;lt;head&amp;amp;gt;` में इष्टतम स्थान&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;तत्वों का क्रम में`&amp;amp;lt;head&amp;amp;gt;`est important. Voici l&amp;amp;#8217;ordre recommandé :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;head&amp;amp;gt;
    &amp;amp;lt;!-- 1. Métadonnées critiques --&amp;amp;gt;
    &amp;amp;lt;meta charset=&amp;quot;UTF-8&amp;quot;&amp;amp;gt;
    &amp;amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0&amp;quot;&amp;amp;gt;

    &amp;amp;lt;!-- 2. Notre script de pré-chargement (IMMÉDIATEMENT après les meta) --&amp;amp;gt;
    &amp;amp;lt;script&amp;amp;gt;
      (function() { /* notre code */ })();
    &amp;amp;lt;/script&amp;amp;gt;

    &amp;amp;lt;!-- 3. Titre de la page --&amp;amp;gt;
    &amp;amp;lt;title&amp;amp;gt;Mon Site&amp;amp;lt;/title&amp;amp;gt;

    &amp;amp;lt;!-- 4. Feuilles de style --&amp;amp;gt;
    &amp;amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;styles.css&amp;quot;&amp;amp;gt;

    &amp;amp;lt;!-- 5. Autres ressources (fonts, favicons, etc.) --&amp;amp;gt;
    &amp;amp;lt;link rel=&amp;quot;preconnect&amp;quot; href=&amp;quot;https://fonts.googleapis.com&amp;quot;&amp;amp;gt;
    &amp;amp;lt;link rel=&amp;quot;icon&amp;quot; href=&amp;quot;favicon.ico&amp;quot;&amp;amp;gt;

    &amp;amp;lt;!-- 6. Autres scripts avec defer ou async --&amp;amp;gt;
    &amp;amp;lt;script src=&amp;quot;app.js&amp;quot; defer&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
&amp;amp;lt;/head&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह आदेश सुनिश्चित करता है कि :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;चारसेट किसी भी पाठ प्रसंस्करण से पहले परिभाषित किया जाता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;हमारा स्क्रिप्ट CSS लोड होने से पहले चलता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;CSS को बाद में लोड किया जाता है और फिर सही विषय को सीधे लागू किया जाता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;अन्य गैर‑महत्वपूर्ण संसाधन अंत में लोड किए जाते हैं&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_चरण_3_css_एट्रिब्यूट_सेलेक्टर्स_की_शक्ति&amp;quot;&amp;gt;चरण 3 : CSS एट्रिब्यूट सेलेक्टर्स की शक्ति&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_बूटस्ट्रैप_5_थीम_सिस्टम&amp;quot;&amp;gt;बूटस्ट्रैप 5 थीम सिस्टम&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Bootstrap 5 ने CSS कस्टम प्रॉपर्टीज़ (CSS चर) और एट्रिब्यूट सेलेक्टर्स पर आधारित थीम प्रबंधन की एक शानदार प्रणाली पेश की। यह प्रणाली एट्रिब्यूट का उपयोग करती है`data-bs-theme`तत्व पर`&amp;amp;lt;html&amp;amp;gt;`निर्धारित करने के लिए कि कौन सा रंग चरों का सेट लागू करना है&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस प्रणाली की सुंदरता इसकी सरलता में निहित है: अलग‑अलग स्टाइलशीट लोड करने या हजारों तत्वों पर क्लासेज को टॉगल करने के बजाय, हम केवल एक तत्व पर एक विशेषता बदलते हैं, और CSS कैस्केड के माध्यम से बाक़ी काम कर देता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_css_संरचना_एक_थीम_सिस्टम_के_लिए&amp;quot;&amp;gt;CSS संरचना एक थीम सिस्टम के लिए&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ एक पूर्ण CSS संरचना है एक मजबूत थीम प्रणाली लागू करने के लिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-css&amp;quot; data-lang=&amp;quot;css&amp;quot;&amp;gt;/**
 * SYSTÈME DE THÈME COMPLET
 * Utilise les Custom Properties CSS pour une maintenance facile
 */

/* ============================================
   THÈME PAR DÉFAUT (LIGHT)
   Défini sur :root pour être le fallback
   ============================================ */
:root {
  /* Couleurs de base */
  --color-primary: #0d6efd;
  --color-secondary: #6c757d;
  --color-success: #198754;
  --color-danger: #dc3545;
  --color-warning: #ffc107;
  --color-info: #0dcaf0;

  /* Couleurs de fond */
  --bg-primary: #ffffff;
  --bg-secondary: #f8f9fa;
  --bg-tertiary: #e9ecef;

  /* Couleurs de texte */
  --text-primary: #212529;
  --text-secondary: #6c757d;
  --text-tertiary: #adb5bd;

  /* Couleurs de bordure */
  --border-color: #dee2e6;
  --border-color-subtle: #e9ecef;

  /* Couleurs d&amp;#39;ombre */
  --shadow-sm: rgba(0, 0, 0, 0.075);
  --shadow-md: rgba(0, 0, 0, 0.15);
  --shadow-lg: rgba(0, 0, 0, 0.25&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>ग्रैडल प्लगिन के कार्यात्मक परीक्षणों में प्रभावी लॉगिंग</title>
            <link >https://cheroliv.com/blog/2025/0097_gradle_plugin_dev_func_test_logger_post.html</link>
            <pubDate>Fri, 7 Nov 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0097_gradle_plugin_dev_func_test_logger_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table of Contents&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_gradlerunner_पर_निर्भरता&amp;quot;&amp;gt;समस्या : GradleRunner पर निर्भरता&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_प्लगिन_विकास_का_संदर्भ&amp;quot;&amp;gt;प्लगिन विकास का संदर्भ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_लॉगिंग_की_दुविधा&amp;quot;&amp;gt;लॉगिंग की दुविधा&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_les_fausses_bonnes_idées&amp;quot;&amp;gt;Les Fausses Bonnes Idées&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समाधान_स्वतंत्र_लॉगर&amp;quot;&amp;gt;समाधान : स्वतंत्र लॉगर&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अनुशंसित_वास्तुकला&amp;quot;&amp;gt;अनुशंसित वास्तुकला&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्पादन_प्रवाह&amp;quot;&amp;gt;निष्पादन प्रवाह&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पूर्ण_कार्यान्वयन&amp;quot;&amp;gt;पूर्ण कार्यान्वयन&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_gradle_निर्भरताएँ&amp;quot;&amp;gt;Gradle निर्भरताएँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_logback_कॉन्फ़िगरेशन&amp;quot;&amp;gt;Logback कॉन्फ़िगरेशन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पूरी_परीक्षा_वर्ग&amp;quot;&amp;gt;पूरी परीक्षा वर्ग&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_बहु_स्तरीय_लॉगिंग_स्कीमा&amp;quot;&amp;gt;बहु-स्तरीय लॉगिंग स्कीमा&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सर्वोत्तम_प्रथाएँ&amp;quot;&amp;gt;सर्वोत्तम प्रथाएँ&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अनुशंसित_लॉगिंग_संरचना&amp;quot;&amp;gt;अनुशंसित लॉगिंग संरचना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_दृश्य_प्रतीक_पठनीयता_के_लिए&amp;quot;&amp;gt;दृश्य प्रतीक पठनीयता के लिए&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_आउटपुट_से_सूचना_निष्कर्षण&amp;quot;&amp;gt;आउटपुट से सूचना निष्कर्षण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_तुलना_पहलेबाद&amp;quot;&amp;gt;तुलना पहले/बाद&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पहले_समस्यात्मक_पद्धति&amp;quot;&amp;gt;पहले: समस्यात्मक पद्धति&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_बाद_मzboused_दृष्टिकोण&amp;quot;&amp;gt;बाद : मzboused दृष्टिकोण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सारांश_आरेख&amp;quot;&amp;gt;सारांश आरेख&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_से_बचने_के_लिए_जाल&amp;quot;&amp;gt;से बचने के लिए जाल&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पेंज_1_भूलना_forwardoutput&amp;quot;&amp;gt;�❌ पेंज #1 : भूलना `.forwardOutput()&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_जाल_n2_लॉगर_इनिशियलाइज़_नहीं&amp;quot;&amp;gt;❌ जाल n°2 : लॉगर इनिशियलाइज़ नहीं&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_जाल_नंबर_3_अत्यधिक_लॉगिंग&amp;quot;&amp;gt;❌ जाल नंबर 3 : अत्यधिक लॉगिंग&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिणाम_और_मेट्रिक्स&amp;quot;&amp;gt;परिणाम और मेट्रिक्स&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संसाधन&amp;quot;&amp;gt;संसाधन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_और_आगे_बढ़ें&amp;quot;&amp;gt;और आगे बढ़ें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Gradle प्लगिन के विकास के दौरान, फ़ंक्शनल टेस्ट प्लगिन के व्यवहार को वास्तविक Gradle वातावरण में मान्य करने के लिए आवश्यक हैं। हालांकि, एक महत्वपूर्ण प्रश्न जल्दी से उठता है:&amp;lt;strong&amp;gt;कैसे प्रभावी लॉगिंग प्रणाली स्थापित करें बिना &amp;lt;code&amp;gt;GradleRunner&amp;lt;/code&amp;gt; के साथ समस्याग्रस्त निर्भरताएँ बनाए ?&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस लेख में, हम खोजेंगे:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Gradle के फ़ंक्शनल टेस्ट में लॉगिंग की समस्या&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;SLF4J और Logback के साथ एक मजबूत समाधान की आर्किटेक्चर&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;संपूर्ण कार्यान्वयन ठोस उदाहरणों के साथ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;अच्छे अभ्यास और बचने योग्य गलतियाँ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या_gradlerunner_पर_निर्भरता&amp;quot;&amp;gt;समस्या : GradleRunner पर निर्भरता&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_प्लगिन_विकास_का_संदर्भ&amp;quot;&amp;gt;प्लगिन विकास का संदर्भ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जब किसी Gradle प्लगइन विकसित करते हैं, तो इसका सामान्यतया उपयोग किया जाता है।`GradleRunner`&amp;lt;em&amp;gt;Gradle TestKit&amp;lt;/em&amp;gt; का उपयोग करके टेस्ट बिल्ड चलाने के लिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;@Test
fun `test my plugin`() {
    val result = GradleRunner.create()
        .withProjectDir(projectDir)
        .withArguments(&amp;quot;myTask&amp;quot;)
        .build()

    // Comment logger efficacement ici ?
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_लॉगिंग_की_दुविधा&amp;quot;&amp;gt;लॉगिंग की दुविधा&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मुख्य समस्या यह है:&amp;lt;strong&amp;gt;लॉगिंग को इस ऑब्जेक्ट पर निर्भर नहीं होना चाहिए जिसका हमें यकीन नहीं है कि वह प्रारम्भिक किया गया है&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-a74755077d3d3bd2b7c4ee0866b951cd.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;433&amp;quot; height=&amp;quot;262&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_les_fausses_bonnes_idées&amp;quot;&amp;gt;Les Fausses Bonnes Idées&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock warning&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-warning&amp;quot; title=&amp;quot;Warning&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;इसे न करें :&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// ❌ MAUVAIS: Tentative d&amp;#39;obtenir un logger du runner
val runner = GradleRunner.create()
val logger = runner.logger // N&amp;#39;existe pas !
// ❌ MAUVAIS: Logger partagé initialisé tardivement
lateinit var logger: Logger
@BeforeEach
fun setup() {
    logger = LoggerFactory.getLogger(...)
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समाधान_स्वतंत्र_लॉगर&amp;quot;&amp;gt;समाधान : स्वतंत्र लॉगर&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_अनुशंसित_वास्तुकला&amp;quot;&amp;gt;अनुशंसित वास्तुकला&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;समाधान में एक लॉगर का उपयोग करना शामिल है।&amp;lt;strong&amp;gt;पूरी तरह स्वतंत्र&amp;lt;/strong&amp;gt; du &amp;lt;code&amp;gt;GradleRunner&amp;lt;/code&amp;gt;, परीक्षण वर्ग स्तर पर प्रारम्भित&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-30193fb5bd62a7a2638f5f9eacd06201.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;601&amp;quot; height=&amp;quot;448&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_निष्पादन_प्रवाह&amp;quot;&amp;gt;निष्पादन प्रवाह&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-fe98b2bdd6062bd4552e30a837cd9cdc.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;729&amp;quot; height=&amp;quot;686&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_पूर्ण_कार्यान्वयन&amp;quot;&amp;gt;पूर्ण कार्यान्वयन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_gradle_निर्भरताएँ&amp;quot;&amp;gt;Gradle निर्भरताएँ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपने में आवश्यक निर्भरताएँ जोड़ें`build.gradle.kts`:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;dependencies {
    // Pour les tests fonctionnels
    testImplementation(gradleTestKit())
    testImplementation(&amp;quot;org.junit.jupiter:junit-jupiter:5.10.2&amp;quot;)

    // Pour le logging
    testImplementation(&amp;quot;org.slf4j:slf4j-api:2.0.17&amp;quot;)
    testRuntimeOnly(&amp;quot;ch.qos.logback:logback-classic:1.4.14&amp;quot;)

    // Pour les assertions
    testImplementation(&amp;quot;org.assertj:assertj-core:3.27.6&amp;quot;)
}

tasks.test {
    useJUnitPlatform()
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_logback_कॉन्फ़िगरेशन&amp;quot;&amp;gt;Logback कॉन्फ़िगरेशन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फ़ाइल बनाएँ`src/test/resources/logback-test.xml`(No output)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-xml hljs&amp;quot; data-lang=&amp;quot;xml&amp;quot;&amp;gt;&amp;amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;amp;gt;
&amp;amp;lt;configuration&amp;amp;gt;
    &amp;amp;lt;!-- Appender console avec format lisible --&amp;amp;gt;
    &amp;amp;lt;appender name=&amp;quot;STDOUT&amp;quot; class=&amp;quot;ch.qos.logback.core.ConsoleAppender&amp;quot;&amp;amp;gt;
        &amp;amp;lt;encoder&amp;amp;gt;
            &amp;amp;lt;pattern&amp;amp;gt;%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n&amp;amp;lt;/pattern&amp;amp;gt;
        &amp;amp;lt;/encoder&amp;amp;gt;
    &amp;amp;lt;/appender&amp;amp;gt;

    &amp;amp;lt;!-- Appender fichier pour conservation --&amp;amp;gt;
    &amp;amp;lt;appender name=&amp;quot;FILE&amp;quot; class=&amp;quot;ch.qos.logback.core.FileAppender&amp;quot;&amp;amp;gt;
        &amp;amp;lt;file&amp;amp;gt;build/test-results/functional-tests.log&amp;amp;lt;/file&amp;amp;gt;
        &amp;amp;lt;encoder&amp;amp;gt;
            &amp;amp;lt;pattern&amp;amp;gt;%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n&amp;amp;lt;/pattern&amp;amp;gt;
        &amp;amp;lt;/encoder&amp;amp;gt;
    &amp;amp;lt;/appender&amp;amp;gt;

    &amp;amp;lt;!-- Logger pour vos tests --&amp;amp;gt;
    &amp;amp;lt;logger name=&amp;quot;com.cheroliv.bakery&amp;quot; level=&amp;quot;DEBUG&amp;quot;/&amp;amp;gt;

    &amp;amp;lt;!-- Réduire le bruit de Gradle --&amp;amp;gt;
    &amp;amp;lt;logger name=&amp;quot;org.gradle&amp;quot; level=&amp;quot;WARN&amp;quot;/&amp;amp;gt;

    &amp;amp;lt;!-- Configuration racine --&amp;amp;gt;
    &amp;amp;lt;root level=&amp;quot;INFO&amp;quot;&amp;amp;gt;
        &amp;amp;lt;appender-ref ref=&amp;quot;STDOUT&amp;quot;/&amp;amp;gt;
        &amp;amp;lt;appender-ref ref=&amp;quot;FILE&amp;quot;/&amp;amp;gt;
    &amp;amp;lt;/root&amp;amp;gt;
&amp;amp;lt;/configuration&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_पूरी_परीक्षा_वर्ग&amp;quot;&amp;gt;पूरी परीक्षा वर्ग&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;package com.cheroliv.bakery

import org.gradle.testkit.runner.GradleRunner
import org.gradle.testkit.runner.TaskOutcome
import org.junit.jupiter.api.*
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
import org.junit.jupiter.api.io.TempDir
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.File
import kotlin.test.assertEquals
import kotlin.test.assertTrue

@TestInstance(PER_CLASS)
class BakeryPluginFunctionalTest {

    @field:TempDir
    lateinit var projectDir: File

    private val buildFile by lazy { projectDir.resolve(&amp;quot;build.gradle.kts&amp;quot;) }
    private val settingsFile by lazy { projectDir.resolve(&amp;quot;settings.gradle.kts&amp;quot;) }

    companion object {
        // ✓ Logger indépendant, initialisé au chargement de la classe
        private val logger: Logger = LoggerFactory.getLogger(
            BakeryPluginFunctionalTest::class.java
        )

        @JvmStatic
        @BeforeAll
        fun globalSetup() {
            logger.info(&amp;quot;═&amp;quot;.repeat(60))
            logger.info(&amp;quot;DÉMARRAGE DE LA SUITE DE TESTS FONCTIONNELS&amp;quot;)
            logger.info(&amp;quot;═&amp;quot;.repeat(60))
        }

        @JvmStatic
        @AfterAll
        fun globalTeardown() {
            logger.info(&amp;quot;═&amp;quot;.repeat(60))
            logger.info(&amp;quot;FIN DE LA SUITE DE TESTS&amp;quot;)
            logger.info(&amp;quot;═&amp;quot;.repeat(60))
        }
    }

    @BeforeEach
    fun setup() {
        logger.info(&amp;quot;─&amp;quot;.repeat(60))
        logger.info(&amp;quot;Préparation de l&amp;#39;environnement de test&amp;quot;)
        logger.debug(&amp;quot;Répertoire de test: ${projectDir.absolutePath}&amp;quot;)

        settingsFile.writeText(&amp;quot;&amp;quot;&amp;quot;
            rootProject.name = &amp;quot;test-bakery-project&amp;quot;
        &amp;quot;&amp;quot;&amp;quot;.trimIndent())

        logger.debug(&amp;quot;✓ settings.gradle.kts créé&amp;quot;)
    }

    @AfterEach
    fun teardown(testInfo: TestInfo) {
        logger.info(&amp;quot;✓ Test terminé: ${testInfo.displayName}&amp;quot;)
        logger.info(&amp;quot;─&amp;quot;.repeat(60))
    }

    @Test
    fun `plugin can be applied successfully`() {
        logger.info(&amp;quot;TEST: Application du plugin Bakery&amp;quot;)

        buildFile.writeText(&amp;quot;&amp;quot;&amp;quot;
            plugins {
                id(&amp;quot;com.cheroliv.bakery&amp;quot;)
            }
        &amp;quot;&amp;quot;&amp;quot;.trimIndent())

        logger.debug(&amp;quot;Fichier build.gradle.kts créé&amp;quot;)
        logger.debug(&amp;quot;Lancement du build Gradle...&amp;quot;)

        val startTime = System.currentTimeMillis()

        val result = GradleRunner.create()
            .forwardOutput() // ← Important : capture la sortie
            .withPluginClasspath()
            .withArguments(&amp;quot;tasks&amp;quot;, &amp;quot;--group=bakery&amp;quot;, &amp;quot;--stacktrace&amp;quot;)
            .withProjectDir(projectDir)
            .build()

        val duration = System.currentTimeMillis() - startTime
        logger.info(&amp;quot;Build terminé en ${duration}ms&amp;quot;)

        // Analyse de la sortie
        logger.debug(&amp;quot;Analyse de la sortie Gradle...&amp;quot;)
        val outputLines = result.output.lines()
        logger.debug(&amp;quot;Nombre de lignes capturées: ${outputLines.size}&amp;quot;)

        // Validation
        val expectedTasks = listOf(&amp;quot;bake&amp;quot;, &amp;quot;printConfigPath&amp;quot;, &amp;quot;printJBakeClasspath&amp;quot;)
        logger.info(&amp;quot;Vérification des tâches attendues:&amp;quot;)

        expectedTasks.forEach { task -&amp;amp;gt;
            val found = result.output.contains(task)
            logger.debug(&amp;quot;  ${if (found) &amp;quot;✓&amp;quot; else &amp;quot;✗&amp;quot;} $task&amp;quot;)
            assertTrue(found, &amp;quot;Task &amp;#39;$task&amp;#39; should be available&amp;quot;)
        }

        logger.info(&amp;quot;✓ Plugin appliqué avec succès - ${expectedTasks.size} tâches trouvées&amp;quot;)
    }

    @Test
    fun `bake task executes and prints version`() {
        logger.info(&amp;quot;TEST: Exécution de la tâche &amp;#39;bake&amp;#39;&amp;quot;)

        buildFile.writeText(&amp;quot;&amp;quot;&amp;quot;
            plugins {
                id(&amp;quot;com.cheroliv.bakery&amp;quot;)
            }
        &amp;quot;&amp;quot;&amp;quot;.trimIndent())

        logger.debug(&amp;quot;Exécution de &amp;#39;gradle bake&amp;#39;...&amp;quot;)

        val result = GradleRunner.create()
            .forwardOutput()
            .withPluginClasspath()
            .withArguments(&amp;quot;bake&amp;quot;, &amp;quot;--info&amp;quot;) // --info pour plus de détails
            .withProjectDir(projectDir)
            .build()

        // Extraction d&amp;#39;informations depuis la sortie
        logger.debug(&amp;quot;Recherche du message &amp;#39;Baking site&amp;#39;...&amp;quot;)
        val hasBakingMessage = result.output.contains(&amp;quot;Baking site with Bakery Plugin!&amp;quot;)

        logger.debug(&amp;quot;Recherche de la version JBake...&amp;quot;)
        val hasVersionMessage = result.output.contains(&amp;quot;Using JBake version:&amp;quot;)

        // Extraction de la version (si présente)
        val versionRegex = Regex(&amp;quot;Using JBake version: (.+)&amp;quot;)
        val versionMatch = versionRegex.find(result.output)
        if (versionMatch != null) {
            val version = versionMatch.groupValues[1]
            logger.info(&amp;quot;Version JBake détectée: $version&amp;quot;)
        }

        // Validation
        assertTrue(hasBakingMessage, &amp;quot;Message &amp;#39;Baking site&amp;#39; attendu&amp;quot;)
        assertTrue(hasVersionMessage, &amp;quot;Message de version attendu&amp;quot;)
        assertEquals(TaskOutcome.SUCCESS, result.task(&amp;quot;:bake&amp;quot;)?.outcome)

        logger.info(&amp;quot;✓ Tâche &amp;#39;bake&amp;#39; exécutée avec succès&amp;quot;)
    }

    @Test
    fun `analyze output with structured logging`() {
        logger.info(&amp;quot;TEST: Analyse structurée de la sortie&amp;quot;)

        buildFile.writeText(&amp;quot;&amp;quot;&amp;quot;
            plugins {
                id(&amp;quot;com.cheroliv.bakery&amp;quot;)
            }

            task(&amp;quot;diagnostics&amp;quot;) {
                doLast {
                    println(&amp;quot;[DIAG] Project: ${&amp;#39;$&amp;#39;}{project.name}&amp;quot;)
                    println(&amp;quot;[DIAG] Build dir: ${&amp;#39;$&amp;#39;}{project.buildDir}&amp;quot;)
                    println(&amp;quot;[DIAG] Plugin applied: true&amp;quot;)

                    val config = configurations.findByName(&amp;quot;jbakeRuntime&amp;quot;)
                    println(&amp;quot;[DIAG] JBake config exists: ${&amp;#39;$&amp;#39;}{config != null}&amp;quot;)

                    if (config != null) {
                        println(&amp;quot;[DIAG] Dependencies count: ${&amp;#39;$&amp;#39;}{config.dependencies.size}&amp;quot;)
                    }
                }
            }
        &amp;quot;&amp;quot;&amp;quot;.trimIndent())

        logger.debug(&amp;quot;Exécution de la tâche diagnostics...&amp;quot;)

        val result = GradleRunner.create()
            .forwardOutput()
            .withPluginClasspath()
            .withArguments(&amp;quot;diagnostics&amp;quot;, &amp;quot;--quiet&amp;quot;)
            .withProjectDir(projectDir)
            .build()

        // Analyse structurée
        logger.info(&amp;quot;Extraction des informations de diagnostic:&amp;quot;)

        val diagLines = result.output.lines()
            .filter { it.startsWith(&amp;quot;[DIAG]&amp;quot;) }

        logger.debug(&amp;quot;Nombre de lignes de diagnostic: ${diagLines.size}&amp;quot;)

        diagLines.forEach { line -&amp;amp;gt;
            logger.info(&amp;quot;  $line&amp;quot;)

            // Analyse spécifique par type de ligne
            when {
                line.contains(&amp;quot;Project:&amp;quot;) -&amp;amp;gt; {
                    val projectName = line.substringAfter(&amp;quot;Project:&amp;quot;).trim()
                    logger.debug(&amp;quot;    → Nom du projet extrait: &amp;#39;$projectName&amp;#39;&amp;quot;)
                }
                line.contains(&amp;quot;Dependencies count:&amp;quot;) -&amp;amp;gt; {
                    val count = line.substringAfter(&amp;quot;count:&amp;quot;).trim()
                    logger.debug(&amp;quot;    → Nombre de dépendances: $count&amp;quot;)
                }
            }
        }

        assertTrue(diagLines.isNotEmpty(), &amp;quot;Des lignes de diagnostic devraient être présentes&amp;quot;)
        logger.info(&amp;quot;✓ Analyse structurée terminée - ${diagLines.size} lignes analysées&amp;quot;)
    }

    @Test
    fun `test with error handling`() {
        logger.info(&amp;quot;TEST: Gestion d&amp;#39;erreurs avec logging&amp;quot;)

        buildFile.writeText(&amp;quot;&amp;quot;&amp;quot;
            plugins {
                id(&amp;quot;com.cheroliv.bakery&amp;quot;)
            }
        &amp;quot;&amp;quot;&amp;quot;.trimIndent())

        try {
            logger.debug(&amp;quot;Tentative d&amp;#39;exécution...&amp;quot;)

            val result = GradleRunner.create()
                .forwardOutput()
                .withPluginClasspath()
                .withArguments(&amp;quot;printJBakeClasspath&amp;quot;)
                .withProjectDir(projectDir)
                .build()

            val outcome = result.task(&amp;quot;:printJBakeClasspath&amp;quot;)?.outcome
            logger.info(&amp;quot;Outcome: $outcome&amp;quot;)

            if (outcome == TaskOutcome.SUCCESS) {
                logger.info(&amp;quot;✓ Exécution réussie&amp;quot;)
            } else {
                logger.warn(&amp;quot;⚠ Outcome inattendu: $outcome&amp;quot;)
            }

            assertEquals(TaskOutcome.SUCCESS, outcome)

        } catch (e: Exception) {
            logger.error(&amp;quot;✗ Échec du test&amp;quot;, e)
            logger.error(&amp;quot;Type d&amp;#39;exception: ${e.javaClass.simpleName}&amp;quot;)
            logger.error(&amp;quot;Message: ${e.message}&amp;quot;)

            // Log de la stack trace si nécessaire
            if (logger.isDebugEnabled) {
                logger.debug(&amp;quot;Stack trace complète:&amp;quot;, e)
            }

            throw e
        }
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_बहु_स्तरीय_लॉगिंग_स्कीमा&amp;quot;&amp;gt;बहु-स्तरीय लॉगिंग स्कीमा&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-224cb29d2432d704b4bdcca197dcb548.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;314&amp;quot; height=&amp;quot;911&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_सर्वोत्तम_प्रथाएँ&amp;quot;&amp;gt;सर्वोत्तम प्रथाएँ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_अनुशंसित_लॉगिंग_संरचना&amp;quot;&amp;gt;अनुशंसित लॉगिंग संरचना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;@Test
fun `mon test`() {
    // 1. LOG: Début du test
    logger.info(&amp;quot;TEST: Description du test&amp;quot;)

    // 2. LOG: Préparation
    logger.debug(&amp;quot;Préparation des fichiers...&amp;quot;)
    buildFile.writeText(&amp;quot;...&amp;quot;)
    logger.debug(&amp;quot;✓ Fichiers préparés&amp;quot;)

    // 3. LOG: Exécution
    logger.debug(&amp;quot;Lancement du build...&amp;quot;)
    val startTime = System.currentTimeMillis()

    val result = GradleRunner.create()
        .forwardOutput()
        .withArguments(&amp;quot;task&amp;quot;)
        .build()

    val duration = System.currentTimeMillis() - startTime
    logger.info(&amp;quot;Build terminé en ${duration}ms&amp;quot;)

    // 4. LOG: Analyse
    logger.debug(&amp;quot;Analyse des résultats...&amp;quot;)
    // ... validations ...

    // 5. LOG: Conclusion
    logger.info(&amp;quot;✓ Test réussi&amp;quot;)
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_दृश्य_प्रतीक_पठनीयता_के_लिए&amp;quot;&amp;gt;दृश्य प्रतीक पठनीयता के लिए&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;लॉग की पठनीयता सुधारने के लिए यूनिकोड प्रतीकों का प्रयोग करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;logger.info(&amp;quot;✓ Succès&amp;quot;)
logger.info(&amp;quot;✗ Échec&amp;quot;)
logger.info(&amp;quot;⚠ Attention&amp;quot;)
logger.info(&amp;quot;→ Étape suivante&amp;quot;)
logger.info(&amp;quot;═&amp;quot;.repeat(60)) // Séparateur principal
logger.info(&amp;quot;─&amp;quot;.repeat(60)) // Séparateur secondaire&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_आउटपुट_से_सूचना_निष्कर्षण&amp;quot;&amp;gt;आउटपुट से सूचना निष्कर्षण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// Recherche simple
val hasMessage = result.output.contains(&amp;quot;Expected message&amp;quot;)

// Extraction avec regex
val versionRegex = Regex(&amp;quot;Version: (.+)&amp;quot;)
val version = versionRegex.find(result.output)?.groupValues?.get(1)

// Filtrage de lignes
val errorLines = result.output.lines()
    .filter { it.contains(&amp;quot;ERROR&amp;quot;) }

errorLines.forEach { logger.error(&amp;quot;Gradle error: $it&amp;quot;) }&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_तुलना_पहलेबाद&amp;quot;&amp;gt;तुलना पहले/बाद&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_पहले_समस्यात्मक_पद्धति&amp;quot;&amp;gt;पहले: समस्यात्मक पद्धति&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;class MyTest {
    lateinit var logger: Logger // ❌ Initialisé tardivement

    @BeforeEach
    fun setup() {
        logger = LoggerFactory.getLogger(...) // ❌ Dépendance
    }

    @Test
    fun test() {
        val runner = GradleRunner.create()
        logger.info(&amp;quot;Testing...&amp;quot;) // ⚠ Peut échouer
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_बाद_मzboused_दृष्टिकोण&amp;quot;&amp;gt;बाद : मzboused दृष्टिकोण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;class MyTest {
    companion object {
        private val logger = LoggerFactory.getLogger(...) // ✓ Indépendant
    }

    @Test
    fun test() {
        logger.info(&amp;quot;TEST: Starting...&amp;quot;) // ✓ Toujours disponible

        val result = GradleRunner.create()
            .forwardOutput() // ✓ Capture la sortie
            .build()

        logger.debug(&amp;quot;Output: ${result.output}&amp;quot;) // ✓ Analyse
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_सारांश_आरेख&amp;quot;&amp;gt;सारांश आरेख&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-5ee5b0aec3d2942882fab09e3ee72bd6.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;948&amp;quot; height=&amp;quot;1345&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_से_बचने_के_लिए_जाल&amp;quot;&amp;gt;से बचने के लिए जाल&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_पेंज_1_भूलना_forwardoutput&amp;quot;&amp;gt;�❌ पेंज #1 : भूलना `.forwardOutput()&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// MAUVAIS: La sortie Gradle n&amp;#39;est pas capturée
val result = GradleRunner.create()
    .withArguments(&amp;quot;task&amp;quot;)
    .build()

// result.output sera vide !&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// BON: La sortie est capturée
val result = GradleRunner.create()
    .forwardOutput() // ✓
    .withArguments(&amp;quot;task&amp;quot;)
    .build()&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_जाल_n2_लॉगर_इनिशियलाइज़_नहीं&amp;quot;&amp;gt;❌ जाल n°2 : लॉगर इनिशियलाइज़ नहीं&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// MAUVAIS
class Test {
    lateinit var logger: Logger // Peut ne pas être initialisé
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// BON
class Test {
    companion object {
        private val logger = LoggerFactory.getLogger(...) // Toujours initialisé
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_जाल_नंबर_3_अत्यधिक_लॉगिंग&amp;quot;&amp;gt;❌ जाल नंबर 3 : अत्यधिक लॉगिंग&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// MAUVAIS: Trop de logs DEBUG en production
logger.debug(&amp;quot;Variable a = $a&amp;quot;)
logger.debug(&amp;quot;Variable b = $b&amp;quot;)
logger.debug(&amp;quot;Variable c = $c&amp;quot;)
// ... 100 lignes de logs&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// BON: Logging ciblé
logger.info(&amp;quot;Traitement de ${items.size} éléments&amp;quot;)
logger.debug(&amp;quot;Détails: ${items.take(5)}...&amp;quot;) // Échantillon seulement&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिणाम_और_मेट्रिक्स&amp;quot;&amp;gt;परिणाम और मेट्रिक्स&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस दृष्टिकोण से, आपको मिलता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 28.5714%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 42.8571%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 28.5715%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;मेट्रिक&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;पहले&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;बाद में&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;कोड की पंक्तियाँ&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;~50 लाइनें&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;~80 पंक्तियाँ (+60%)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;डिबग का समय&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;पाया गया त्रुटियाँ&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;बुनियादी&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;विस्तृत&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;रखरखाव&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;कठिन&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;सरल&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;स्वतंत्रता&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;�❌ जोड़ी गई&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;ग्रेडल प्लगइन के कार्यात्मक परीक्षणों में एक मजबूत लॉगिंग प्रणाली स्थापित करने का आधार एक सरल सिद्धांत है :&amp;lt;strong&amp;gt;स्वतंत्रता&amp;lt;/strong&amp;gt;।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;याद रखने वाले मुख्य बिंदु :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;स्वतंत्र लॉगर&amp;lt;/strong&amp;gt;: एक में प्रारम्भित`companion object`&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;SLF4J + Logback&amp;lt;/strong&amp;gt;: परीक्षणित और कॉन्फ़िगरेबल स्टैक&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;.forwardOutput()&amp;lt;/strong&amp;gt;: ग्रैडल आउटपुट की कैप्चर&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;संरचित लॉगिंग&amp;lt;/strong&amp;gt; : INFO pour les étapes, DEBUG pour les détails&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;आउटपुट विश्लेषण&amp;lt;/strong&amp;gt;: जानकारी निकालना`result.output`&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह दृष्टिकोण परीक्षणों की गारंटी देता है&amp;lt;strong&amp;gt;बनाए रखने योग्य&amp;lt;/strong&amp;gt;, &amp;lt;strong&amp;gt;डिबग योग्य&amp;lt;/strong&amp;gt; et &amp;lt;strong&amp;gt;मजबूत&amp;lt;/strong&amp;gt;, ठोस डिज़ाइन सिद्धांतों का पालन करते हुए.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_संसाधन&amp;quot;&amp;gt;संसाधन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://docs.gradle.org/current/userguide/test_kit.html&amp;quot;&amp;gt;ग्रैडल टेस्टकिट दस्तावेज़&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://www.slf4j.org/manual.html&amp;quot;&amp;gt;एसएलएफ4J मैनुअल&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://logback.qos.ch/manual/configuration.html&amp;quot;&amp;gt;Logback कॉन्फ़िगरेशन&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/gradle/gradle/tree/master/subprojects/test-kit&amp;quot;&amp;gt;Gradle TestKit स्रोत कोड&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_और_आगे_बढ़ें&amp;quot;&amp;gt;और आगे बढ़ें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आगामी लेख में, हम का अन्वेषण करेंगे :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;संरचित लॉगिंग के साथ निरंतर एकीकरण&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एचटीएमएल परीक्षण रिपोर्ट्स जिसमें एम्बेडेड लॉग शामिल हैं&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;उन्नत डिबगिंग JVM अटैच के साथ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;लॉगिंग के प्रदर्शन और अनुकूलन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह लेख &amp;quot;Gradle प्लगिन विकास&amp;quot; श्रृंखला का भाग है मेरे तकनीकी ब्लॉग पर।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>AsciiDoc में रंगीन वर्ग दिखाएँ: व्यावहारिक मार्गदर्शिका</title>
            <link >https://cheroliv.com/blog/2025/0096_afficher-couleurs-asciidoc_post.html</link>
            <pubDate>Sat, 1 Nov 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0096_afficher-couleurs-asciidoc_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table of Contents&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या&amp;quot;&amp;gt;समस्या&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_उपयोग_का_संदर्भ&amp;quot;&amp;gt;उपयोग का संदर्भ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संभावित_दृष्टिकोण&amp;quot;&amp;gt;संभावित दृष्टिकोण&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel3&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_विकल्प_1_यूनिकोड_अक्षर&amp;quot;&amp;gt;विकल्प 1 : यूनिकोड अक्षर&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_generate_the_site_jbake_b&amp;quot;&amp;gt;Bake (generate) the site jbake -b&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_and_serve_locally_jbake_b_s&amp;quot;&amp;gt;Bake and serve locally jbake -b -s&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_and_watch_for_changes_jbake_b_reset&amp;quot;&amp;gt;Bake and watch for changes jbake -b --reset&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_specify_source_and_destination_jbake_source_folder_output_folder&amp;quot;&amp;gt;Specify source and destination jbake source_folder output_folder&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_clear_the_output_directory_before_baking_jbake_b_output_reset&amp;quot;&amp;gt;Clear the output directory before baking jbake -b . output --reset &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt;&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel3&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_option_2_बाहरी_चित्र&amp;quot;&amp;gt;Option 2 : बाहरी चित्र&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_विकल्प_3_css_की_कस्टम_भूमिकाएँ&amp;quot;&amp;gt;विकल्प 3 : CSS की कस्टम भूमिकाएँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_विकल्प_4_html_इंजेक्शन_चुनी_गई_समाधान&amp;quot;&amp;gt;विकल्प 4 : HTML इंजेक्शन (चुनी गई समाधान)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समाधान_html_इन्जेक्शन_के_साथ&amp;quot;&amp;gt;समाधान: HTML इन्जेक्शन  के साथ&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_कार्य_करने_का_सिद्धांत&amp;quot;&amp;gt;कार्य करने का सिद्धांत&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_कार्यान्वयन&amp;quot;&amp;gt;कार्यान्वयन&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel3&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_css_गुणों_की_व्याख्या&amp;quot;&amp;gt;CSS गुणों की व्याख्या&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_उदाहरण_पूरा&amp;quot;&amp;gt;उदाहरण पूरा&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अनुकूलन_और_सर्वोत्तम_प्रथाएँ&amp;quot;&amp;gt;अनुकूलन और सर्वोत्तम प्रथाएँ&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_हल्के_रंगों_को_प्रबंधित_करें&amp;quot;&amp;gt;हल्के रंगों को प्रबंधित करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_वर्गों_के_आकार_को_समायोजित_करें&amp;quot;&amp;gt;वर्गों के आकार को समायोजित करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_वैरिएंट_बनाएँ&amp;quot;&amp;gt;वैरिएंट बनाएँ&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel3&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_रंगीन_वृत्त&amp;quot;&amp;gt;रंगीन वृत्त&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_रंगीन_सीमा_वाला_वर्ग&amp;quot;&amp;gt;रंगीन सीमा वाला वर्ग&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समाधान_आर्किटेक्चर&amp;quot;&amp;gt;समाधान आर्किटेक्चर&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_फ़ायदे_और_सीमाएँ&amp;quot;&amp;gt;फ़ायदे और सीमाएँ&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_फ़ायदे&amp;quot;&amp;gt;फ़ायदे&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सीमाएँ&amp;quot;&amp;gt;सीमाएँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सुलभता_में_सुधार&amp;quot;&amp;gt;सुलभता में सुधार&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_वास्तविक_उदाहरण_विषयों_का_दस्तावेज़&amp;quot;&amp;gt;वास्तविक उदाहरण : विषयों का दस्तावेज़&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संसाधन&amp;quot;&amp;gt;संसाधन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;तकनीकी दस्तावेज़ लिखते समय, विशेष रूप से शैली गाइड या उपयोगकर्ता इंटरफ़ेस स्पेसिफिकेशन्स के लिए, अक्सर रंग पैलेट दिखाने की आवश्यकता होती है। AsciiDoc, दस्तावेज़ीकरण के लिए बहुत शक्तिशाली होने के बावजूद, रंग नमूने प्रदर्शित करने के लिए कोई मूल व्याकरण प्रदान नहीं करता है। यह लेख समस्या की पड़ताल करता है और HTML इंजेक्शन पर आधारित एक शालीन समाधान प्रस्तुत करता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या&amp;quot;&amp;gt;समस्या&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_उपयोग_का_संदर्भ&amp;quot;&amp;gt;उपयोग का संदर्भ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;कल्पना कीजिए कि आप एक वेब एप्लिकेशन थीम के CSS चर को दस्तावेज़ कर रहे हैं। आपको चाहिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;हेक्साडेसिमल रंग कोडों को सूचीबद्ध करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;प्रत्येक रंग का दृश्य पूर्वावलोकन दिखाएँ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Maintenir la lisibilité du document source&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;JBake जैसे स्थिर साइट जेनरेटर्स के साथ संगतता सुनिश्चित करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;use-case-diagram.svg&amp;quot; alt=&amp;quot;use case diagram&amp;quot; width=&amp;quot;906&amp;quot; height=&amp;quot;193&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_संभावित_दृष्टिकोण&amp;quot;&amp;gt;संभावित दृष्टिकोण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक AsciiDoc दस्तावेज़ में रंग दिखाने के कई समाधान पर विचार किया जा सकता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;component-diagram.svg&amp;quot; alt=&amp;quot;component diagram&amp;quot; width=&amp;quot;1783&amp;quot; height=&amp;quot;5795&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_विकल्प_1_यूनिकोड_अक्षर&amp;quot;&amp;gt;विकल्प 1 : यूनिकोड अक्षर&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यूनिकोड अक्षरों के उपयोग के रूप में`&amp;amp;#9632;`&amp;lt;mark&amp;gt;#&amp;lt;/mark&amp;gt; JBake CLI Commands &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; # Initialize a new JBake project jbake -i&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;h1 id=&amp;quot;_bake_generate_the_site_jbake_b&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake (generate) the site jbake -b&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_and_serve_locally_jbake_b_s&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake and serve locally jbake -b -s&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_and_watch_for_changes_jbake_b_reset&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake and watch for changes jbake -b --reset&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_specify_source_and_destination_jbake_source_folder_output_folder&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Specify source and destination jbake source_folder output_folder&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_clear_the_output_directory_before_baking_jbake_b_output_reset&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Clear the output directory before baking jbake -b . output --reset &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt;&amp;lt;/h1&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;(■) सरल लेकिन सीमित है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;* ■ --accent-color: #7952b3 (violet Bootstrap)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Limitations&amp;lt;/strong&amp;gt; : रंग पर कोई नियंत्रण नहीं, सिस्टम फ़ॉन्ट पर निर्भर।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_option_2_बाहरी_चित्र&amp;quot;&amp;gt;Option 2 : बाहरी चित्र&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;प्रत्येक रंग के लिए PNG या SVG छवियाँ बनाएँ:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;* image:colors/violet.svg[width=16] --accent-color: #7952b3&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;सीमाएँ&amp;lt;/strong&amp;gt; : भारी रखरखाव, फ़ाइलों की वृद्धि, स्वचालित समन्वय नहीं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_विकल्प_3_css_की_कस्टम_भूमिकाएँ&amp;quot;&amp;gt;विकल्प 3 : CSS की कस्टम भूमिकाएँ&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;CSS क्लासेस परिभाषित करें और उन्हें AsciiDoc भूमिकाओं के माध्यम से लागू करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;* [.color-violet]##■## --accent-color: #7952b3&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;सीमाएँ&amp;lt;/strong&amp;gt; : बाहरी स्टाइलशीट की आवश्यकता होती है, सभी संभव रंगों की पूर्व परिभाषा।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_विकल्प_4_html_इंजेक्शन_चुनी_गई_समाधान&amp;quot;&amp;gt;विकल्प 4 : HTML इंजेक्शन (चुनी गई समाधान)&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मैक्रो का उपयोग करें``इंलाइन शैली के साथ HTML इंजेक्ट करने के लिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;
background:#7952b3;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;]
--accent-color: #7952b3 (violet Bootstrap)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समाधान_html_इन्जेक्शन_के_साथ&amp;quot;&amp;gt;समाधान: HTML इन्जेक्शन  के साथ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_कार्य_करने_का_सिद्धांत&amp;quot;&amp;gt;कार्य करने का सिद्धांत&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मैक्रो``AsciiDoc कच्ची सामग्री डालने की अनुमति देता है जिसे AsciiDoc प्रोसेसर द्वारा ज्याख्या नहीं की जाएगी। इससे हमें सीधे HTML को इन्लाइन CSS शैलियों के साथ इंजेक्ट करने की अनुमति मिलती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 5) ]

@startuml
participant &amp;quot;दस्तावेज़\nAsciiDoc&amp;quot; as doc
participant &amp;quot;प्रोसेसर\nAsciiDoc&amp;quot; as processor
participant &amp;quot;पास:[] मैक्रो&amp;quot; as pass
participant &amp;quot;HTML
^^^^^
 Syntax Error? (Assumed diagram type: sequence)

@startuml
participant &amp;quot;दस्तावेज़\nAsciiDoc&amp;quot; as doc
participant &amp;quot;प्रोसेसर\nAsciiDoc&amp;quot; as processor
participant &amp;quot;पास:[] मैक्रो&amp;quot; as pass
participant &amp;quot;HTML
अंतिम&amp;quot; as html

doc -&amp;amp;gt; processor : Analyse document
processor -&amp;amp;gt; pass : Détecte pass:[]
pass -&amp;amp;gt; processor : Retourne HTML brut
processor -&amp;amp;gt; html : Insère sans transformation
html -&amp;amp;gt; html : Navigateur applique styles
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_कार्यान्वयन&amp;quot;&amp;gt;कार्यान्वयन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ HTML संरचना डालने के लिए है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html hljs&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;span style=&amp;quot;display:inline-block;
             width:1em;
             height:1em;
             background:#7952b3;
             vertical-align:middle;
             margin-right:0.5em&amp;quot;&amp;amp;gt;
&amp;amp;lt;/span&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_css_गुणों_की_व्याख्या&amp;quot;&amp;gt;CSS गुणों की व्याख्या&amp;lt;/h4&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 75%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;सम्पत्ति&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;फ़ंक्शन&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;display:inline-block&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;इंलाइन प्रवाह में बने रहते हुए width/height सेट करने की अनुमति देता है&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;width:1em; height:1em&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;फ़ॉन्ट के आकार के सापेक्ष वर्ग का आकार (प्रतिक्रियाशील)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;background:#7952b3&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;दिखाने वाला रंग (आपकी आवश्यकतानुसार परिवर्तनीय) (आपकी)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;vertical-align:middle&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;वर्ग को सन्निहित पाठ के साथ संरेखित करें&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;code&amp;gt;margin-right:0.5em&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;वर्ग और टेक्स्ट के बीच की दूरी&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_उदाहरण_पूरा&amp;quot;&amp;gt;उदाहरण पूरा&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ एक उदाहरण है जो एक थीम पैलेट का दस्तावेज़ीकरण करता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;== Thème Clair

* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#f8f9fa;border:1px solid #ccc;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] --bg-primary: `#f8f9fa` (blanc cassé)
* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#212529;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] --text-primary: `#212529` (noir très foncé)
* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#7952b3;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] --accent-color: `#7952b3` (violet Bootstrap)
* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#61428f;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] --accent-hover: `#61428f` (violet plus foncé)
* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#ffffff;border:1px solid #ccc;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] --card-bg: `#ffffff` (blanc)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;निम्नलिखित रेंडर कौन उत्पन्न करता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;लाइट थीम&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#f8f9fa;border:1px solid #ccc;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; --bg-primary:`#f8f9fa`(ऑफ़ व्हाइट)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#212529;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; --text-primary:`#212529`(बहुत गहरा काला)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#7952b3;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; --accent-color:`#7952b3`(Bootstrap बैंगनी)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#61428f;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; --accent-hover:`#61428f`(गहरा बैंगनी)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#ffffff;border:1px solid #ccc;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; --card-bg:`#ffffff`(सफ़ेद)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_अनुकूलन_और_सर्वोत्तम_प्रथाएँ&amp;quot;&amp;gt;अनुकूलन और सर्वोत्तम प्रथाएँ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_हल्के_रंगों_को_प्रबंधित_करें&amp;quot;&amp;gt;हल्के रंगों को प्रबंधित करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;बहुत हल्के रंगों (सफेद, बहुत हल्का ग्रे) के लिए, उन्हें सफेद पृष्ठभूमि पर दृश्यमान बनाने के लिए एक सीमा जोड़ें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html hljs&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;
background:#ffffff;border:1px solid #ccc;
vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;ग्रे बॉर्डर (&amp;lt;code&amp;gt;border:1px solid #ccc&amp;lt;/code&amp;gt;) सफेद पृष्ठभूमि पर सफेद वर्ग को सीमा निर्धारित करने की अनुमति देता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_वर्गों_के_आकार_को_समायोजित_करें&amp;quot;&amp;gt;वर्गों के आकार को समायोजित करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आप अपनी आवश्यकताओं के अनुसार वर्गों के आकार को समायोजित कर सकते हैं :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1.5em;height:1.5em;background:#7952b3;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] Grand carré
* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:0.8em;height:0.8em;background:#7952b3;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] Petit carré&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इकाई का उपयोग`em`यह सुनिश्चित करता है कि वर्ग फ़ॉन्ट के आकार के अनुसार अनुकूलित हो जाते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_वैरिएंट_बनाएँ&amp;quot;&amp;gt;वैरिएंट बनाएँ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;विशिष्ट आवश्यकताओं के लिए, आप विभिन्न प्रकार के प्रारूप बना सकते हैं :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_रंगीन_वृत्त&amp;quot;&amp;gt;रंगीन वृत्त&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#7952b3;border-radius:50%;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] Cercle violet&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_रंगीन_सीमा_वाला_वर्ग&amp;quot;&amp;gt;रंगीन सीमा वाला वर्ग&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#ffffff;border:3px solid #7952b3;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] Bordure violette&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समाधान_आर्किटेक्चर&amp;quot;&amp;gt;समाधान आर्किटेक्चर&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;architecture-diagram.svg&amp;quot; alt=&amp;quot;architecture diagram&amp;quot; width=&amp;quot;1738&amp;quot; height=&amp;quot;5723&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_फ़ायदे_और_सीमाएँ&amp;quot;&amp;gt;फ़ायदे और सीमाएँ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_फ़ायदे&amp;quot;&amp;gt;फ़ायदे&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;✓ &amp;lt;strong&amp;gt;स्वायत्तता&amp;lt;/strong&amp;gt; : बाहरी फ़ाइलों पर कोई निर्भरता नहीं&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;✓ &amp;lt;strong&amp;gt;Portabilité&amp;lt;/strong&amp;gt; : सभी AsciiDoc प्रोसेसर के साथ काम करता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;✓ &amp;lt;strong&amp;gt;सिंक्रोनाइज़ेशन&amp;lt;/strong&amp;gt; : रंग कोड HTML में सीधे है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;�✓ &amp;lt;strong&amp;gt;लचीलापन&amp;lt;/strong&amp;gt; : पूर्ण शैली अनुकूलन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;�✓ &amp;lt;strong&amp;gt;Maintenance&amp;lt;/strong&amp;gt; : हेक्साडेसीमल कोड का सरल संशोधन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;✓ &amp;lt;strong&amp;gt;JBake संगतता&amp;lt;/strong&amp;gt; : पूरी तरह से स्थिर साइट जनरेटरों के साथ काम करता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सीमाएँ&amp;quot;&amp;gt;सीमाएँ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;�✗ &amp;lt;strong&amp;gt;वाचालता&amp;lt;/strong&amp;gt; : पुनरावृत्तिपूर्ण HTML कोड AsciiDoc स्रोत में&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;�✗ &amp;lt;strong&amp;gt;स्रोत की पठनीयता&amp;lt;/strong&amp;gt; : स्रोत दस्तावेज़ कम परिष्कृत है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;एक्सेसिबिलिटी&amp;lt;/strong&amp;gt; : कोई मूल वैकल्पिक पाठ नहीं (हाथ से जोड़ना होगा)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सुलभता_में_सुधार&amp;quot;&amp;gt;सुलभता में सुधार&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;स्क्रीन रीडर्स के लिए वर्गों को सुलभ बनाने के लिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;* pass:[&amp;amp;lt;span role=&amp;quot;img&amp;quot; aria-label=&amp;quot;Couleur violet Bootstrap&amp;quot;
style=&amp;quot;display:inline-block;width:1em;height:1em;background:#7952b3;
vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;]
--accent-color: `#7952b3` (violet Bootstrap)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;विशेषताएँ`role=&amp;quot;img&amp;quot;` et `aria-label`वे सहायक प्रौद्योगिकियों को दृश्य सामग्री को समझने और वर्णित करने की अनुमति देते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_वास्तविक_उदाहरण_विषयों_का_दस्तावेज़&amp;quot;&amp;gt;वास्तविक उदाहरण : विषयों का दस्तावेज़&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ कई विषयों का दस्तावेज़ करने वाला एक पूर्ण उदाहरण है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;= Guide des couleurs de l&amp;#39;application

== Thème Clair (`:root`)

* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#f8f9fa;border:1px solid #ccc;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] --bg-primary: `#f8f9fa` (blanc cassé)
* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#212529;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] --text-primary: `#212529` (noir très foncé)
* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#7952b3;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] --accent-color: `#7952b3` (violet Bootstrap)

== Thème Sombre (`[data-bs-theme=&amp;quot;dark&amp;quot;]`)

* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#212529;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] --bg-primary: `#212529` (noir très foncé)
* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#ffffff;border:1px solid #999;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] --text-primary: `#ffffff` (blanc)
* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#0d6efd;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] --accent-color: `#0d6efd` (bleu Bootstrap)

== Thème Contraste Élevé (`[data-bs-theme=&amp;quot;high-contrast&amp;quot;]`)

* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#000000;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] --bg-primary: `#000000` (noir)
* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#ffffff;border:1px solid #000;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] --text-primary: `#ffffff` (blanc)
* pass:[&amp;amp;lt;span style=&amp;quot;display:inline-block;width:1em;height:1em;background:#00ff00;vertical-align:middle;margin-right:0.5em&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;] --accent-color: `#00ff00` (vert vif)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मैक्रो के माध्यम से HTML इंजेक्शन``AsciiDoc एक सुंदर और व्यावहारिक समाधान प्रदान करता है तकनीकी दस्तावेज़ीकरण में रंग के नमूनों को प्रदर्शित करने के लिए। यद्यपि यह थोड़ा शब्दजालपूर्ण है, इस तरीके से अधिकतम पोर्टेबिलिटी और सरलीकृत रखरखाव की गारंटी मिलती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह तकनीक को किसी बाहरी कॉन्फ़िगरेशन या अतिरिक्त स्टाइल शीट की आवश्यकता नहीं है, और यह JBake और सभी मानक AsciiDoc प्रोसेसर के साथ तुरंत काम करती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक बार जब आप अपना पहला रंगीन वर्ग बना लेते हैं, तो बस HTML कोड कॉपी‑पेस्ट करें और हेक्साडेसिमल कोड बदलकर जल्दी से एक पूर्ण पैलेट बनाएं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह तकनीक अनुकूलित दृश्य रेंडरिंग की आवश्यकता वाले अन्य उपयोग के मामलों में विस्तारित की जा सकती है: आइकन, बैज, साधारण चार्ट, या किसी भी दृश्य तत्व जिसको शैली के सटीक नियंत्रण की आवश्यकता होती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_संसाधन&amp;quot;&amp;gt;संसाधन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://docs.asciidoctor.org/asciidoc/latest/pass/pass-macro/&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noopener&amp;quot;&amp;gt;दस्तावेज़ AsciiDoc : पास मैक्रो&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://jbake.org/docs/2.6.7/&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noopener&amp;quot;&amp;gt;JBake Documentation&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://developer.mozilla.org/fr/docs/Web/CSS/color_value&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noopener&amp;quot;&amp;gt;MDN : CSS रंग के मान&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;लेख प्रकाशित किया गया 2025-11-01&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>थाइमलीफ़ के साथ JBake स्थिर साइट का अंतर्राष्ट्रीयकरण</title>
            <link >https://cheroliv.com/blog/2025/0095_i18n-site-statique-jbake-thymeleaf_post.html</link>
            <pubDate>Mon, 20 Oct 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0095_i18n-site-statique-jbake-thymeleaf_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table of Contents&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_उपयोग_केस_आरेख_use_case&amp;quot;&amp;gt;उपयोग केस आरेख (Use Case)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अंतर्राष्ट्रीयीकरण_की_वास्तुकला&amp;quot;&amp;gt;अंतर्राष्ट्रीयीकरण की वास्तुकला&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संरचना_आरेख_फ़ाइल_संगठन&amp;quot;&amp;gt;संरचना आरेख (फ़ाइल संगठन)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_इस_दृष्टिकोण_क्यों&amp;quot;&amp;gt;इस दृष्टिकोण क्यों?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_घटक_आरेख&amp;quot;&amp;gt;घटक आरेख&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_i18n_thymeleaf_के_साथ_टेम्प्लेटिंग&amp;quot;&amp;gt;I18n Thymeleaf के साथ टेम्प्लेटिंग&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_structure_des_fichiers_de_messages&amp;quot;&amp;gt;Structure des fichiers de messages&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संदेश_फ़ाइलों_की_सामग्री&amp;quot;&amp;gt;संदेश फ़ाइलों की सामग्री&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_टेम्पलेट्स_में_उपयोग&amp;quot;&amp;gt;टेम्पलेट्स में उपयोग&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अनुक्रम_आरेख_i18n_समाधान&amp;quot;&amp;gt;अनुक्रम आरेख - i18n समाधान&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_jbake_में_लोकेल_कॉन्फ़िगरेशन&amp;quot;&amp;gt;JBake में लोकेल कॉन्फ़िगरेशन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_लेखों_का_i18n_फ़ोल्डर_द्वारा_संगठन&amp;quot;&amp;gt;लेखों का I18n: फ़ोल्डर द्वारा संगठन&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_फ़्लो_flow_का_प्रवाह_आरेख_निर्माण&amp;quot;&amp;gt;फ़्लो (Flow) का प्रवाह आरेख - निर्माण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_फ़ोल्डर_संरचना&amp;quot;&amp;gt;फ़ोल्डर संरचना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_इस_दृष्टिकोण_के_फ़ायदे&amp;quot;&amp;gt;इस दृष्टिकोण के फ़ायदे&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_लेखों_के_मेटाडेटा&amp;quot;&amp;gt;लेखों के मेटाडेटा&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_यूआरएल_कॉन्फ़िगरेशन&amp;quot;&amp;gt;यूआरएल कॉन्फ़िगरेशन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_बहुभाषी_प्रदर्शन_के_लिए_टेम्प्लेट&amp;quot;&amp;gt;बहुभाषी प्रदर्शन के लिए टेम्प्लेट&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_भाषा_चयनकर्ता_के_साथ_लेख_टेम्पलेट&amp;quot;&amp;gt;भाषा चयनकर्ता के साथ लेख टेम्पलेट&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_भाषा_द्वारा_फ़िल्टर_किया_गया_सूचकांक&amp;quot;&amp;gt;भाषा द्वारा फ़िल्टर किया गया सूचकांक&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_भाषाओं_के_बीच_नेविगेशन&amp;quot;&amp;gt;भाषाओं के बीच नेविगेशन&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_वैश्विक_भाषा_चयनकर्ता&amp;quot;&amp;gt;वैश्विक भाषा चयनकर्ता&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_फ़्लो_चार्ट_उपयोगकर्ता_पढ़ना&amp;quot;&amp;gt;फ़्लो चार्ट - उपयोगकर्ता पढ़ना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सेलेक्टर_के_लिए_css_शैली&amp;quot;&amp;gt;सेलेक्टर के लिए CSS शैली&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_भाषा_अनुसार_rss_फ़ीड&amp;quot;&amp;gt;भाषा अनुसार RSS फ़ीड&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अच्छी_प्रथाएँ_और_टिप्स&amp;quot;&amp;gt;अच्छी प्रथाएँ और टिप्स&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_1_cohérence_des_identifiants_darticle&amp;quot;&amp;gt;1. Cohérence des identifiants d&amp;amp;#8217;article&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_2_संगत_तारीखें&amp;quot;&amp;gt;2. संगत तारीखें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_3_बहुभाषी_टैग&amp;quot;&amp;gt;3. बहुभाषी टैग&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_4_अनुवाद_न_किए_गए_लेखों_का_प्रबंधन&amp;quot;&amp;gt;4. अनुवाद न किए गए लेखों का प्रबंधन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_5_बहुभाषी_साइटमैप&amp;quot;&amp;gt;5. बहुभाषी साइटमैप&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_डिप्लॉयमेंट_आरेख&amp;quot;&amp;gt;डिप्लॉयमेंट आरेख&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक स्थिर साइट का अंतर्राष्ट्रीयकरण (i18n) पहली नज़र में जटिल लग सकता है, लेकिन JBake के साथ Thymeleaf को मिलाकर बहुभाषी साइट बनाने के लिए सुंदर समाधान प्रदान करता है। इस लेख में, मैं आपको दिखाऊँगा कि मैंने अपने ब्लॉग पर i18n कैसे लागू किया, जिसमें टेम्पलेटिंग और कई भाषाओं में लेख प्रबंधन दोनों शामिल हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_उपयोग_केस_आरेख_use_case&amp;quot;&amp;gt;उपयोग केस आरेख (Use Case)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-a14d3e7d3e4bbf5a4adba93772f5445b.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;651&amp;quot; height=&amp;quot;433&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_अंतर्राष्ट्रीयीकरण_की_वास्तुकला&amp;quot;&amp;gt;अंतर्राष्ट्रीयीकरण की वास्तुकला&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारा दृष्टिकोण दो स्तम्भों पर आधारित है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;टेम्पलेटिंग का i18n&amp;lt;/strong&amp;gt;: Thymeleaf संदेश फाइलों का उपयोग इंटरफ़ेस तत्वों के लिए&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;सामग्री का अंतर्राष्ट्रीयीकरण&amp;lt;/strong&amp;gt;: भाषा के अनुसार आलेखों का संगठन एक समर्पित फ़ोल्डर संरचना में&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_संरचना_आरेख_फ़ाइल_संगठन&amp;quot;&amp;gt;संरचना आरेख (फ़ाइल संगठन)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-2f100fc3ec2ec37f9556818cdc246602.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;188&amp;quot; height=&amp;quot;513&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_इस_दृष्टिकोण_क्यों&amp;quot;&amp;gt;इस दृष्टिकोण क्यों?&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह पृथक्करण करने की अनुमति देता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;भाषा चाहे जैसी भी हो, इंटरफ़ेस में स्थिरता बनाए रखें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;सामग्री और लेख अनुवाद को स्वतंत्र रूप से प्रबंधित करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;बड़े रिफैक्टरिंग किए बिना नयी भाषाएँ जोड़ने को सुगम बनाना&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;केवल कुछ भाषाओं में उपलब्ध लेखों की अनुमति दें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_घटक_आरेख&amp;quot;&amp;gt;घटक आरेख&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-79ece694ee71813801472b3f834432c0.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;1771&amp;quot; height=&amp;quot;477&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_i18n_thymeleaf_के_साथ_टेम्प्लेटिंग&amp;quot;&amp;gt;I18n Thymeleaf के साथ टेम्प्लेटिंग&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_structure_des_fichiers_de_messages&amp;quot;&amp;gt;Structure des fichiers de messages&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पहला चरण समर्थित प्रत्येक भाषा के लिए गुण फ़ाइलें बनाने से शुरू होता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;src/jbake/templates/
├── messages.properties        # Fallback par défaut
├── messages_fr.properties     # Français
├── messages_en.properties     # Anglais
└── messages_de.properties     # Allemand&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_संदेश_फ़ाइलों_की_सामग्री&amp;quot;&amp;gt;संदेश फ़ाइलों की सामग्री&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ एक फ़ाइल का उदाहरण है`messages_fr.properties`(No output - empty string)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-properties hljs&amp;quot; data-lang=&amp;quot;properties&amp;quot;&amp;gt;# Navigation
nav.home=Accueil
nav.blog=Blog
nav.about=À propos
nav.contact=Contact

# Articles
article.readmore=Lire la suite
article.published=Publié le
article.tags=Étiquettes
article.also.available=Également disponible en

# Interface
site.title=Mon Blog Technique
site.description=Partage de connaissances et expériences
footer.copyright=© 2025 Tous droits réservés
search.placeholder=Rechercher un article...&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;और उसका अंग्रेजी समकक्ष`messages_en.properties`(No output)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-properties hljs&amp;quot; data-lang=&amp;quot;properties&amp;quot;&amp;gt;# Navigation
nav.home=Home
nav.blog=Blog
nav.about=About
nav.contact=Contact

# Articles
article.readmore=Read more
article.published=Published on
article.tags=Tags
article.also.available=Also available in

# Interface
site.title=My Tech Blog
site.description=Sharing knowledge and experiences
footer.copyright=© 2025 All rights reserved
search.placeholder=Search articles...&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_टेम्पलेट्स_में_उपयोग&amp;quot;&amp;gt;टेम्पलेट्स में उपयोग&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपने Thymeleaf टेम्पलेट्स में, सिंटैक्स का उपयोग करें`#{}`संदेशों तक पहुँचने के लिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html hljs&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;!DOCTYPE html&amp;amp;gt;
&amp;amp;lt;html xmlns:th=&amp;quot;http://www.thymeleaf.org&amp;quot;&amp;amp;gt;
&amp;amp;lt;head&amp;amp;gt;
    &amp;amp;lt;title th:text=&amp;quot;#{site.title}&amp;quot;&amp;amp;gt;Mon Blog&amp;amp;lt;/title&amp;amp;gt;
    &amp;amp;lt;meta name=&amp;quot;description&amp;quot; th:content=&amp;quot;#{site.description}&amp;quot; /&amp;amp;gt;
&amp;amp;lt;/head&amp;amp;gt;
&amp;amp;lt;body&amp;amp;gt;
    &amp;amp;lt;nav&amp;amp;gt;
        &amp;amp;lt;a th:href=&amp;quot;@{/}&amp;quot; th:text=&amp;quot;#{nav.home}&amp;quot;&amp;amp;gt;Accueil&amp;amp;lt;/a&amp;amp;gt;
        &amp;amp;lt;a th:href=&amp;quot;@{/blog/}&amp;quot; th:text=&amp;quot;#{nav.blog}&amp;quot;&amp;amp;gt;Blog&amp;amp;lt;/a&amp;amp;gt;
        &amp;amp;lt;a th:href=&amp;quot;@{/about.html}&amp;quot; th:text=&amp;quot;#{nav.about}&amp;quot;&amp;amp;gt;À propos&amp;amp;lt;/a&amp;amp;gt;
    &amp;amp;lt;/nav&amp;amp;gt;

    &amp;amp;lt;footer&amp;amp;gt;
        &amp;amp;lt;p th:text=&amp;quot;#{footer.copyright}&amp;quot;&amp;amp;gt;Copyright&amp;amp;lt;/p&amp;amp;gt;
    &amp;amp;lt;/footer&amp;amp;gt;
&amp;amp;lt;/body&amp;amp;gt;
&amp;amp;lt;/html&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_अनुक्रम_आरेख_i18n_समाधान&amp;quot;&amp;gt;अनुक्रम आरेख - i18n समाधान&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 4) ]

@startuml
actor Auteur
participant JBake
participant &amp;quot;AsciiDoc
^^^^^
 Syntax Error? (Assumed diagram type: sequence)

@startuml
actor Auteur
participant JBake
participant &amp;quot;AsciiDoc
पार्सर&amp;quot; as parser
participant &amp;quot;Thymeleaf
इंजन&amp;quot; as thymeleaf
participant &amp;quot;I18n\nसमाधानकर्ता&amp;quot; as i18n
database &amp;quot;messages_*.properties&amp;quot; as messages

Auteur -&amp;amp;gt; JBake: jbake -b
activate JBake

JBake -&amp;amp;gt; parser: Lire article.fr.adoc
activate parser
parser --&amp;amp;gt; JBake: Contenu + métadonnées\n(lang=fr, article-id=xyz)
deactivate parser

JBake -&amp;amp;gt; parser: Lire article.en.adoc
activate parser
parser --&amp;amp;gt; JBake: Contenu + métadonnées\n(lang=en, article-id=xyz)
deactivate parser

JBake -&amp;amp;gt; thymeleaf: Générer page FR
activate thymeleaf

thymeleaf -&amp;amp;gt; i18n: Résoudre #{nav.home}
activate i18n
i18n -&amp;amp;gt; messages: Lire messages_fr.properties
messages --&amp;amp;gt; i18n: &amp;quot;स्वागत&amp;quot;
i18n --&amp;amp;gt; thymeleaf: &amp;quot;स्वागत&amp;quot;
deactivate i18n

thymeleaf -&amp;amp;gt; JBake: Rechercher traductions\n(article-id=xyz, lang!=fr)
JBake --&amp;amp;gt; thymeleaf: article.en.html trouvé

thymeleaf --&amp;amp;gt; JBake: /fr/blog/article.html
deactivate thymeleaf

JBake -&amp;amp;gt; thymeleaf: Générer page EN
activate thymeleaf

thymeleaf -&amp;amp;gt; i18n: Résoudre #{nav.home}
activate i18n
i18n -&amp;amp;gt; messages: Lire messages_en.properties
messages --&amp;amp;gt; i18n: &amp;quot;होम&amp;quot;
i18n --&amp;amp;gt; thymeleaf: &amp;quot;होम&amp;quot;
deactivate i18n

thymeleaf -&amp;amp;gt; JBake: Rechercher traductions\n(article-id=xyz, lang!=en)
JBake --&amp;amp;gt; thymeleaf: article.fr.html trouvé

thymeleaf --&amp;amp;gt; JBake: /en/blog/article.html
deactivate thymeleaf

JBake --&amp;amp;gt; Auteur: Site généré
deactivate JBake
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_jbake_में_लोकेल_कॉन्फ़िगरेशन&amp;quot;&amp;gt;JBake में लोकेल कॉन्फ़िगरेशन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आपकी फ़ाइल में`jbake.properties`, डिफ़ॉल्ट locale सेट करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-properties hljs&amp;quot; data-lang=&amp;quot;properties&amp;quot;&amp;gt;# Locale par défaut
thymeleaf.locale=fr

# Encodage
template.encoding=UTF-8&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_लेखों_का_i18n_फ़ोल्डर_द्वारा_संगठन&amp;quot;&amp;gt;लेखों का I18n: फ़ोल्डर द्वारा संगठन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_फ़्लो_flow_का_प्रवाह_आरेख_निर्माण&amp;quot;&amp;gt;फ़्लो (Flow) का प्रवाह आरेख - निर्माण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-f0b4350346f193bede9cd575ebc2ac32.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;285&amp;quot; height=&amp;quot;1034&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_फ़ोल्डर_संरचना&amp;quot;&amp;gt;फ़ोल्डर संरचना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फ़ाइल नामों में सफ़िक्स का उपयोग करने के बजाय, मैंने स्पष्टता और रखरखाव में सुधार लाने वाले फ़ोल्डर आधारित संगठन को चुना है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;content/blog/
├── 2024/
│   ├── fr/
│   │   ├── introduction-jbake.adoc
│   │   ├── guide-thymeleaf.adoc
│   │   └── astuces-asciidoc.adoc
│   └── en/
│       ├── introduction-jbake.adoc
│       ├── thymeleaf-guide.adoc
│       └── asciidoc-tips.adoc
└── 2025/
    ├── fr/
    │   └── internationalisation-jbake.adoc
    └── en/
        └── jbake-internationalization.adoc&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_इस_दृष्टिकोण_के_फ़ायदे&amp;quot;&amp;gt;इस दृष्टिकोण के फ़ायदे&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस संरचना के कई फायदे हैं:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;स्पष्ट पृथक्करण&amp;lt;/strong&amp;gt;: प्रत्येक भाषा का अपना स्थान है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;लचीला नामकरण&amp;lt;/strong&amp;gt;: फ़ाइलें भाषा के अनुसार विभिन्न नाम रख सकती हैं&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;स्केलेबिलिटी&amp;lt;/strong&amp;gt;: एक नई भाषा जोड़ना आसान है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;प्राकृतिक संगठन&amp;lt;/strong&amp;gt;: JBake के समयबद्ध तर्क का पालन करता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_लेखों_के_मेटाडेटा&amp;quot;&amp;gt;लेखों के मेटाडेटा&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हर लेख में अनुवादों के बीच संबंध स्थापित करने के लिए मेटाडेटा शामिल होना चाहिए। यहाँ एक उदाहरण दिया गया है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;फ़्रेंच संस्करण&amp;lt;/strong&amp;gt;(&amp;lt;code&amp;gt;2025/fr/internationalisation-jbake.adoc&amp;lt;/code&amp;gt;) :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;= Internationalisation d&amp;#39;un site statique JBake
:jbake-type: post
:jbake-status: published
:jbake-date: 2025-10-20
:jbake-lang: fr
:jbake-article-id: jbake-i18n-thymeleaf
:jbake-tags: jbake, thymeleaf, i18n
:jbake-description: Guide pour mettre en place l&amp;#39;i18n avec JBake&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;अंग्रेज़ी संस्करण&amp;lt;/strong&amp;gt;(&amp;lt;code&amp;gt;2025/en/jbake-internationalization.adoc&amp;lt;/code&amp;gt;) :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;= Internationalizing a JBake Static Site
:jbake-type: post
:jbake-status: published
:jbake-date: 2025-10-20
:jbake-lang: en
:jbake-article-id: jbake-i18n-thymeleaf
:jbake-tags: jbake, thymeleaf, i18n
:jbake-description: Guide to implement i18n with JBake&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;Note&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
एट्रिब्यूट`:jbake-article-id:`यह महत्वपूर्ण है: यह एक ही लेख के विभिन्न अनुवादों को जोड़ने की अनुमति देता है।
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_यूआरएल_कॉन्फ़िगरेशन&amp;quot;&amp;gt;यूआरएल कॉन्फ़िगरेशन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;में`jbake.properties`, URL पैटर्न को भाषा शामिल करने के लिए कॉन्फ़िगर करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-properties hljs&amp;quot; data-lang=&amp;quot;properties&amp;quot;&amp;gt;# Pattern d&amp;#39;URL avec langue
post.permalink.pattern=:lang/blog/:year/:name.html

# Langue par défaut
site.default.lang=fr&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इससे इस प्रकार के URL उत्पन्न होंगे :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;/fr/blog/2025/internationalisation-jbake.html&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;/en/blog/2025/jbake-internationalization.html&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_बहुभाषी_प्रदर्शन_के_लिए_टेम्प्लेट&amp;quot;&amp;gt;बहुभाषी प्रदर्शन के लिए टेम्प्लेट&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_भाषा_चयनकर्ता_के_साथ_लेख_टेम्पलेट&amp;quot;&amp;gt;भाषा चयनकर्ता के साथ लेख टेम्पलेट&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक टेम्प्लेट बनाएँ`post.html`disponible अनुवाद दिखाता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html hljs&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;!DOCTYPE html&amp;amp;gt;
&amp;amp;lt;html xmlns:th=&amp;quot;http://www.thymeleaf.org&amp;quot;&amp;amp;gt;
&amp;amp;lt;head&amp;amp;gt;
    &amp;amp;lt;title th:text=&amp;quot;${content.title}&amp;quot;&amp;amp;gt;Article&amp;amp;lt;/title&amp;amp;gt;
&amp;amp;lt;/head&amp;amp;gt;
&amp;amp;lt;body&amp;amp;gt;
    &amp;amp;lt;article&amp;amp;gt;
        &amp;amp;lt;header&amp;amp;gt;
            &amp;amp;lt;h1 th:text=&amp;quot;${content.title}&amp;quot;&amp;amp;gt;Titre&amp;amp;lt;/h1&amp;amp;gt;

            &amp;amp;lt;div class=&amp;quot;article-meta&amp;quot;&amp;amp;gt;
                &amp;amp;lt;time th:text=&amp;quot;${#dates.format(content.date, &amp;#39;dd MMMM yyyy&amp;#39;)}&amp;quot;
                      th:attr=&amp;quot;datetime=${#dates.format(content.date, &amp;#39;yyyy-MM-dd&amp;#39;)}&amp;quot;&amp;amp;gt;
                    Date
                &amp;amp;lt;/time&amp;amp;gt;

                &amp;amp;lt;!-- Sélecteur de traductions --&amp;amp;gt;
                &amp;amp;lt;div class=&amp;quot;translations&amp;quot; th:if=&amp;quot;${content[&amp;#39;article-id&amp;#39;]}&amp;quot;&amp;amp;gt;
                    &amp;amp;lt;span th:text=&amp;quot;#{article.also.available}&amp;quot;&amp;amp;gt;Aussi disponible en :&amp;amp;lt;/span&amp;amp;gt;
                    &amp;amp;lt;ul class=&amp;quot;language-list&amp;quot;&amp;amp;gt;
                        &amp;amp;lt;li th:each=&amp;quot;post : ${published_posts}&amp;quot;
                            th:if=&amp;quot;${post[&amp;#39;article-id&amp;#39;] == content[&amp;#39;article-id&amp;#39;] and post.lang != content.lang}&amp;quot;&amp;amp;gt;
                            &amp;amp;lt;a th:href=&amp;quot;${post.uri}&amp;quot;
                               th:text=&amp;quot;${post.lang.toUpperCase()}&amp;quot;&amp;amp;gt;
                                LANG
                            &amp;amp;lt;/a&amp;amp;gt;
                        &amp;amp;lt;/li&amp;amp;gt;
                    &amp;amp;lt;/ul&amp;amp;gt;
                &amp;amp;lt;/div&amp;amp;gt;
            &amp;amp;lt;/div&amp;amp;gt;
        &amp;amp;lt;/header&amp;amp;gt;

        &amp;amp;lt;div class=&amp;quot;content&amp;quot; th:utext=&amp;quot;${content.body}&amp;quot;&amp;amp;gt;
            Contenu de l&amp;#39;article
        &amp;amp;lt;/div&amp;amp;gt;

        &amp;amp;lt;footer class=&amp;quot;article-footer&amp;quot;&amp;amp;gt;
            &amp;amp;lt;div class=&amp;quot;tags&amp;quot; th:if=&amp;quot;${content.tags}&amp;quot;&amp;amp;gt;
                &amp;amp;lt;span th:text=&amp;quot;#{article.tags}&amp;quot;&amp;amp;gt;Étiquettes :&amp;amp;lt;/span&amp;amp;gt;
                &amp;amp;lt;span th:each=&amp;quot;tag : ${content.tags}&amp;quot;&amp;amp;gt;
                    &amp;amp;lt;a th:href=&amp;quot;@{/tags/{tag}.html(tag=${tag})}&amp;quot;
                       th:text=&amp;quot;${tag}&amp;quot;&amp;amp;gt;tag&amp;amp;lt;/a&amp;amp;gt;
                &amp;amp;lt;/span&amp;amp;gt;
            &amp;amp;lt;/div&amp;amp;gt;
        &amp;amp;lt;/footer&amp;amp;gt;
    &amp;amp;lt;/article&amp;amp;gt;
&amp;amp;lt;/body&amp;amp;gt;
&amp;amp;lt;/html&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_भाषा_द्वारा_फ़िल्टर_किया_गया_सूचकांक&amp;quot;&amp;gt;भाषा द्वारा फ़िल्टर किया गया सूचकांक&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;प्रत्येक भाषा के लिए इंडेक्स टेम्प्लेट बनाएँ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;index.html&amp;lt;/strong&amp;gt;(फ़्रेंच सूचक) :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html hljs&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;!DOCTYPE html&amp;amp;gt;
&amp;amp;lt;html xmlns:th=&amp;quot;http://www.thymeleaf.org&amp;quot;&amp;amp;gt;
&amp;amp;lt;head&amp;amp;gt;
    &amp;amp;lt;title th:text=&amp;quot;#{site.title}&amp;quot;&amp;amp;gt;Mon Blog&amp;amp;lt;/title&amp;amp;gt;
&amp;amp;lt;/head&amp;amp;gt;
&amp;amp;lt;body&amp;amp;gt;
    &amp;amp;lt;main&amp;amp;gt;
        &amp;amp;lt;h1 th:text=&amp;quot;#{nav.blog}&amp;quot;&amp;amp;gt;Blog&amp;amp;lt;/h1&amp;amp;gt;

        &amp;amp;lt;div class=&amp;quot;articles-list&amp;quot;&amp;amp;gt;
            &amp;amp;lt;article th:each=&amp;quot;post : ${published_posts}&amp;quot;
                     th:if=&amp;quot;${post.lang == &amp;#39;fr&amp;#39;}&amp;quot;&amp;amp;gt;
                &amp;amp;lt;h2&amp;amp;gt;
                    &amp;amp;lt;a th:href=&amp;quot;${post.uri}&amp;quot; th:text=&amp;quot;${post.title}&amp;quot;&amp;amp;gt;Titre&amp;amp;lt;/a&amp;amp;gt;
                &amp;amp;lt;/h2&amp;amp;gt;
                &amp;amp;lt;time th:text=&amp;quot;${#dates.format(post.date, &amp;#39;dd MMMM yyyy&amp;#39;)}&amp;quot;&amp;amp;gt;
                    Date
                &amp;amp;lt;/time&amp;amp;gt;
                &amp;amp;lt;p th:text=&amp;quot;${post.description}&amp;quot;&amp;amp;gt;Description&amp;amp;lt;/p&amp;amp;gt;
                &amp;amp;lt;a th:href=&amp;quot;${post.uri}&amp;quot; th:text=&amp;quot;#{article.readmore}&amp;quot;&amp;amp;gt;
                    Lire la suite
                &amp;amp;lt;/a&amp;amp;gt;
            &amp;amp;lt;/article&amp;amp;gt;
        &amp;amp;lt;/div&amp;amp;gt;
    &amp;amp;lt;/main&amp;amp;gt;
&amp;amp;lt;/body&amp;amp;gt;
&amp;amp;lt;/html&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;index_en.html&amp;lt;/strong&amp;gt;(अंग्रेज़ी अनुक्रमणिका) :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html hljs&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;!DOCTYPE html&amp;amp;gt;
&amp;amp;lt;html xmlns:th=&amp;quot;http://www.thymeleaf.org&amp;quot;&amp;amp;gt;
&amp;amp;lt;head&amp;amp;gt;
    &amp;amp;lt;title th:text=&amp;quot;#{site.title}&amp;quot;&amp;amp;gt;My Blog&amp;amp;lt;/title&amp;amp;gt;
&amp;amp;lt;/head&amp;amp;gt;
&amp;amp;lt;body&amp;amp;gt;
    &amp;amp;lt;main&amp;amp;gt;
        &amp;amp;lt;h1 th:text=&amp;quot;#{nav.blog}&amp;quot;&amp;amp;gt;Blog&amp;amp;lt;/h1&amp;amp;gt;

        &amp;amp;lt;div class=&amp;quot;articles-list&amp;quot;&amp;amp;gt;
            &amp;amp;lt;article th:each=&amp;quot;post : ${published_posts}&amp;quot;
                     th:if=&amp;quot;${post.lang == &amp;#39;en&amp;#39;}&amp;quot;&amp;amp;gt;
                &amp;amp;lt;h2&amp;amp;gt;
                    &amp;amp;lt;a th:href=&amp;quot;${post.uri}&amp;quot; th:text=&amp;quot;${post.title}&amp;quot;&amp;amp;gt;Title&amp;amp;lt;/a&amp;amp;gt;
                &amp;amp;lt;/h2&amp;amp;gt;
                &amp;amp;lt;time th:text=&amp;quot;${#dates.format(post.date, &amp;#39;dd MMMM yyyy&amp;#39;)}&amp;quot;&amp;amp;gt;
                    Date
                &amp;amp;lt;/time&amp;amp;gt;
                &amp;amp;lt;p th:text=&amp;quot;${post.description}&amp;quot;&amp;amp;gt;Description&amp;amp;lt;/p&amp;amp;gt;
                &amp;amp;lt;a th:href=&amp;quot;${post.uri}&amp;quot; th:text=&amp;quot;#{article.readmore}&amp;quot;&amp;amp;gt;
                    Read more
                &amp;amp;lt;/a&amp;amp;gt;
            &amp;amp;lt;/article&amp;amp;gt;
        &amp;amp;lt;/div&amp;amp;gt;
    &amp;amp;lt;/main&amp;amp;gt;
&amp;amp;lt;/body&amp;amp;gt;
&amp;amp;lt;/html&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_भाषाओं_के_बीच_नेविगेशन&amp;quot;&amp;gt;भाषाओं के बीच नेविगेशन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_वैश्विक_भाषा_चयनकर्ता&amp;quot;&amp;gt;वैश्विक भाषा चयनकर्ता&amp;lt;/h3&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_फ़्लो_चार्ट_उपयोगकर्ता_पढ़ना&amp;quot;&amp;gt;फ़्लो चार्ट - उपयोगकर्ता पढ़ना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-35c457cfbd1b9be0156f6bbbfb2925d1.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;494&amp;quot; height=&amp;quot;761&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपने मुख्य टेम्पलेट में एक भाषा चयनकर्ता जोड़ें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html hljs&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;nav class=&amp;quot;language-switcher&amp;quot;&amp;amp;gt;
    &amp;amp;lt;a href=&amp;quot;/index.html&amp;quot;
       th:classappend=&amp;quot;${content.lang == &amp;#39;fr&amp;#39;} ? &amp;#39;active&amp;#39;&amp;quot;
       title=&amp;quot;Français&amp;quot;&amp;amp;gt;
        🇫🇷 FR
    &amp;amp;lt;/a&amp;amp;gt;
    &amp;amp;lt;a href=&amp;quot;/en/index.html&amp;quot;
       th:classappend=&amp;quot;${content.lang == &amp;#39;en&amp;#39;} ? &amp;#39;active&amp;#39;&amp;quot;
       title=&amp;quot;English&amp;quot;&amp;amp;gt;
        🇬🇧 EN
    &amp;amp;lt;/a&amp;amp;gt;
&amp;amp;lt;/nav&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सेलेक्टर_के_लिए_css_शैली&amp;quot;&amp;gt;सेलेक्टर के लिए CSS शैली&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-css hljs&amp;quot; data-lang=&amp;quot;css&amp;quot;&amp;gt;.language-switcher {
    display: flex;
    gap: 1rem;
    padding: 0.5rem;
    background: #f5f5f5;
    border-radius: 4px;
}

.language-switcher a {
    padding: 0.5rem 1rem;
    text-decoration: none;
    color: #333;
    border-radius: 4px;
    transition: background 0.2s;
}

.language-switcher a:hover {
    background: #e0e0e0;
}

.language-switcher a.active {
    background: #007bff;
    color: white;
}

.translations {
    margin: 1rem 0;
    padding: 1rem;
    background: #f8f9fa;
    border-left: 4px solid #007bff;
}

.language-list {
    display: inline-flex;
    gap: 0.5rem;
    list-style: none;
    padding: 0;
    margin: 0;
}

.language-list li::after {
    content: &amp;quot;•&amp;quot;;
    margin-left: 0.5rem;
}

.language-list li:last-child::after {
    content: &amp;quot;&amp;quot;;
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_भाषा_अनुसार_rss_फ़ीड&amp;quot;&amp;gt;भाषा अनुसार RSS फ़ीड&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अलग-अलग भाषाओं के लिए अलग-अलग RSS फ़ीड प्राप्त करने के लिए, अलग टेम्प्लेट बनाएँ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;feed.xml&amp;lt;/strong&amp;gt;(फ़्रेंच फ़्लक्स) :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-xml hljs&amp;quot; data-lang=&amp;quot;xml&amp;quot;&amp;gt;&amp;amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;amp;gt;
&amp;amp;lt;rss version=&amp;quot;2.0&amp;quot; xmlns:th=&amp;quot;http://www.thymeleaf.org&amp;quot;&amp;amp;gt;
    &amp;amp;lt;channel&amp;amp;gt;
        &amp;amp;lt;title th:text=&amp;quot;#{site.title}&amp;quot;&amp;amp;gt;Mon Blog&amp;amp;lt;/title&amp;amp;gt;
        &amp;amp;lt;link th:text=&amp;quot;${config.site_host}&amp;quot;&amp;amp;gt;http://example.com&amp;amp;lt;/link&amp;amp;gt;
        &amp;amp;lt;description th:text=&amp;quot;#{site.description}&amp;quot;&amp;amp;gt;Description&amp;amp;lt;/description&amp;amp;gt;
        &amp;amp;lt;language&amp;amp;gt;fr&amp;amp;lt;/language&amp;amp;gt;

        &amp;amp;lt;item th:each=&amp;quot;post : ${published_posts}&amp;quot;
              th:if=&amp;quot;${post.lang == &amp;#39;fr&amp;#39;}&amp;quot;&amp;amp;gt;
            &amp;amp;lt;title th:text=&amp;quot;${post.title}&amp;quot;&amp;amp;gt;Titre&amp;amp;lt;/title&amp;amp;gt;
            &amp;amp;lt;link th:text=&amp;quot;${config.site_host + post.uri}&amp;quot;&amp;amp;gt;Lien&amp;amp;lt;/link&amp;amp;gt;
            &amp;amp;lt;pubDate th:text=&amp;quot;${#dates.format(post.date, &amp;#39;EEE, dd MMM yyyy HH:mm:ss Z&amp;#39;)}&amp;quot;&amp;amp;gt;
                Date
            &amp;amp;lt;/pubDate&amp;amp;gt;
            &amp;amp;lt;description th:text=&amp;quot;${post.description}&amp;quot;&amp;amp;gt;Description&amp;amp;lt;/description&amp;amp;gt;
        &amp;amp;lt;/item&amp;amp;gt;
    &amp;amp;lt;/channel&amp;amp;gt;
&amp;amp;lt;/rss&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_अच्छी_प्रथाएँ_और_टिप्स&amp;quot;&amp;gt;अच्छी प्रथाएँ और टिप्स&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_1_cohérence_des_identifiants_darticle&amp;quot;&amp;gt;1. Cohérence des identifiants d&amp;amp;#8217;article&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह सुनिश्चित करें कि`:jbake-article-id:`सभी लेखों के अनुवादों के लिए समान है। एक सुसंगत प्रारूप का उपयोग करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Préférez les identifiants en anglais pour universalité&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Utilisez des tirets pour séparer les mots&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;विशेष अक्षरों से बचें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_2_संगत_तारीखें&amp;quot;&amp;gt;2. संगत तारीखें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक लेख के सभी अनुवादों की प्रकाशन तिथि समान होनी चाहिए`:jbake-date:`)। यह सॉर्टिंग और कालानुक्रमिक प्रदर्शन को आसान बनाता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_3_बहुभाषी_टैग&amp;quot;&amp;gt;3. बहुभाषी टैग&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;टैग्स के लिए, आपके पास दो विकल्प हैं:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;विकल्प 1: अंग्रेजी में सार्वभौमिक टैग&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;:jbake-tags: java, spring-boot, microservices&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Option 2 : Tags traduits avec mapping&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;# Version française
:jbake-tags: java, spring-boot, microservices

# Version anglaise
:jbake-tags: java, spring-boot, microservices&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_4_अनुवाद_न_किए_गए_लेखों_का_प्रबंधन&amp;quot;&amp;gt;4. अनुवाद न किए गए लेखों का प्रबंधन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सभी लेखों को अनुवाद करना अनिवार्य नहीं है। यदि कोई लेख केवल एक भाषा में उपलब्ध है, तो वह अन्य भाषा की सूची में बस नहीं दिखेगा।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_5_बहुभाषी_साइटमैप&amp;quot;&amp;gt;5. बहुभाषी साइटमैप&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सभी भाषाओं को शामिल करने वाला साइटमैप बनाएँ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-xml hljs&amp;quot; data-lang=&amp;quot;xml&amp;quot;&amp;gt;&amp;amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;amp;gt;
&amp;amp;lt;urlset xmlns=&amp;quot;http://www.sitemaps.org/schemas/sitemap/0.9&amp;quot;
        xmlns:xhtml=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;
        xmlns:th=&amp;quot;http://www.thymeleaf.org&amp;quot;&amp;amp;gt;
    &amp;amp;lt;url th:each=&amp;quot;post : ${published_posts}&amp;quot;&amp;amp;gt;
        &amp;amp;lt;loc th:text=&amp;quot;${config.site_host + post.uri}&amp;quot;&amp;amp;gt;URL&amp;amp;lt;/loc&amp;amp;gt;
        &amp;amp;lt;lastmod th:text=&amp;quot;${#dates.format(post.date, &amp;#39;yyyy-MM-dd&amp;#39;)}&amp;quot;&amp;amp;gt;Date&amp;amp;lt;/lastmod&amp;amp;gt;

        &amp;amp;lt;!-- Liens alternatifs pour les traductions --&amp;amp;gt;
        &amp;amp;lt;xhtml:link th:each=&amp;quot;translation : ${published_posts}&amp;quot;
                    th:if=&amp;quot;${translation[&amp;#39;article-id&amp;#39;] == post[&amp;#39;article-id&amp;#39;] and translation.lang != post.lang}&amp;quot;
                    rel=&amp;quot;alternate&amp;quot;
                    th:attr=&amp;quot;hreflang=${translation.lang},href=${config.site_host + translation.uri}&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;/url&amp;amp;gt;
&amp;amp;lt;/urlset&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;JBake साइट का Thymeleaf के साथ अंतर्राष्ट्रीयकरण एक मजबूत और बनाए रखने योग्य दृष्टिकोण है। टेम्पलेटिंग से i18n (संदेश फ़ाइलों के माध्यम से) और सामग्री से i18n (फ़ोल्डर संगठन के माध्यम से) को अलग करके, आप एक लचीली प्रणाली प्राप्त करते हैं जो आसानी से विकसित हो सकती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मुख्य बिंदु जिन्हें याद रखना चाहिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Thymeleaf संदेश फाइलें&amp;lt;/strong&amp;gt;उपयोगकर्ता इंटरफ़ेस के लिए&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;फ़ोल्डर द्वारा संगठन&amp;lt;/strong&amp;gt;(वर्ष/भाषा) लेखों के लिए&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;आर्टिकल पहचानकर्ता&amp;lt;/strong&amp;gt;अनुवाद लिंक करने के लिए&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;समर्पित टेम्प्लेट्स&amp;lt;/strong&amp;gt;प्रत्येक भाषा के लिए&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;स्पष्ट URLs&amp;lt;/strong&amp;gt;भाषा कोड सहित&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_डिप्लॉयमेंट_आरेख&amp;quot;&amp;gt;डिप्लॉयमेंट आरेख&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 14) ]

@startuml
node &amp;quot;विकास मशीन&amp;quot; {
  artifact &amp;quot;स्रोत&amp;quot; {
    folder &amp;quot;सामग्री/&amp;quot;
    folder &amp;quot;templates/&amp;quot;
    folder &amp;quot;एसेट्स/&amp;quot;
  }

  component &amp;quot;JBake CLI&amp;quot; as jbake

  Sources --&amp;amp;gt; jbake : jbake -b
}

node &amp;quot;बिल्ड सर्वर
^^^^^
 Syntax Error? (Assumed diagram type: component)

@startuml
node &amp;quot;विकास मशीन&amp;quot; {
  artifact &amp;quot;स्रोत&amp;quot; {
    folder &amp;quot;सामग्री/&amp;quot;
    folder &amp;quot;templates/&amp;quot;
    folder &amp;quot;एसेट्स/&amp;quot;
  }

  component &amp;quot;JBake CLI&amp;quot; as jbake

  Sources --&amp;amp;gt; jbake : jbake -b
}

node &amp;quot;बिल्ड सर्वर
(CI/CD)&amp;quot; {
  component &amp;quot;GitHub Actions
या GitLab CI&amp;quot; as ci

  jbake --&amp;amp;gt; ci : push
}

cloud &amp;quot;CDN / होस्टिंग&amp;quot; {
  node &amp;quot;स्थिर वेब सर्वर&amp;quot; {
    artifact &amp;quot;जेनेरेटेड साइट&amp;quot; {
      folder &amp;quot;/fr/ब्लॉग/&amp;quot;
      folder &amp;quot;/en/blog/&amp;quot;
      folder &amp;quot;/assets/&amp;quot;
    }
  }
}

ci --&amp;amp;gt; &amp;quot;जेनेरेटेड साइट&amp;quot; : déploiement

actor &amp;quot;पाठक&amp;quot; as users

users --&amp;amp;gt; &amp;quot;स्थिर वेब सर्वर&amp;quot; : HTTPS
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह आर्किटेक्चर आपको केवल दो भाषाओं के साथ आसानी से शुरू करने और बिना बड़े रीफ़ैक्टरिंग के अन्य भाषाएँ जोड़ने की अनुमति देता है। सब कुछ पूरी तरह स्थैतिक और उच्च प्रदर्शन वाला बना रहता है, JBake के दर्शन के अनुरूप।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;बहुभाषी विकास की शुभकामनाएँ! 🌍&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Ubuntu पर Tor ब्राउज़र स्थापित और सत्यापित करें</title>
            <link >https://cheroliv.com/blog/2025/0094_tor_browser_install_post.html</link>
            <pubDate>Sun, 5 Oct 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0094_tor_browser_install_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table of Contents&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_टॉर_और_इसके_हस्ताक्षर_का_डाउनलोड&amp;quot;&amp;gt;टॉर और इसके हस्ताक्षर का डाउनलोड&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_हस्ताक्षर_का_क्रिप्टोग्राफिक_सत्यापन&amp;quot;&amp;gt;हस्ताक्षर का क्रिप्टोग्राफिक सत्यापन&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_1_टोर_प्रोजेक्ट_की_सार्वजनिक_कुंजी_आयात_करें&amp;quot;&amp;gt;1. टोर प्रोजेक्ट की सार्वजनिक कुंजी आयात करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_2_हस्ताक्षर_की_जाँच_करें&amp;quot;&amp;gt;2. हस्ताक्षर की जाँच करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_व्यावहारिक_मामला_वैध_हस्ताक्षर_लेकिन_प्रमाणित_नहीं_की_गई_कुंजी&amp;quot;&amp;gt;व्यावहारिक मामला: वैध हस्ताक्षर लेकिन प्रमाणित नहीं की गई कुंजी&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_साइन_क्यों_सत्यापित_करें&amp;quot;&amp;gt;साइन क्यों सत्यापित करें ?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_टॉर_ब्राउज़र_की_एक्सट्रैक्शन_और_लॉन्च&amp;quot;&amp;gt;टॉर ब्राउज़र की एक्सट्रैक्शन और लॉन्च&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_उबुन्टू_डेस्कटॉप_एकीकरण&amp;quot;&amp;gt;उबुन्टू डेस्कटॉप एकीकरण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_tor_के_साथ_शैक्षिक_संसाधनों_का_अन्वेषण_करें&amp;quot;&amp;gt;Tor के साथ शैक्षिक संसाधनों का अन्वेषण करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_tor_browser_का_अपडेट&amp;quot;&amp;gt;Tor Browser का अपडेट&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संदर्भ&amp;quot;&amp;gt;संदर्भ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक ऐसी दुनिया में जहाँ डिजिटल गोपनीयता दिन-ब-दिन खतरे में पड़ रही है, &amp;lt;strong&amp;gt;Tor Browser&amp;lt;/strong&amp;gt; एक आवश्यक उपकरण बना रहता है जो अपने अनामिकता और जानकारी की स्वतंत्रता को संरक्षित रखने में मदद करता है। हालाँकि, यह महत्वपूर्ण है कि कभी भी डाउनलोड किया गया सॉफ़्टवेयर न चलाएँ बिना&amp;lt;strong&amp;gt;उसकी प्रामाणिकता सत्यापित की गई&amp;lt;/strong&amp;gt;. यह लेख एक पूरी विधि प्रस्तुत करता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;डाउनलोड &amp;lt;strong&amp;gt;Tor Browser&amp;lt;/strong&amp;gt; और उसका हस्ताक्षर`.asc`&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;डाउनलोड की गई फ़ाइल की वैधता की जाँच करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Ubuntu पर &amp;lt;strong&amp;gt;Tor Browser&amp;lt;/strong&amp;gt; इंस्टॉल करें और लॉन्च करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;इसे डेस्कटॉप मेनús में दैनिक उपयोग के लिए जोड़ें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;टोर के माध्यम से शैक्षिक संसाधनों और नैतिक OSINT का अन्वेषण करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_टॉर_और_इसके_हस्ताक्षर_का_डाउनलोड&amp;quot;&amp;gt;टॉर और इसके हस्ताक्षर का डाउनलोड&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;टोर ब्राउज़र के लिए एक समर्पित फ़ोल्डर बनाएँ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;mkdir -p ~/workspace/tipiak/tor
cd ~/workspace/tipiak/tor&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फिर टॉर ब्राउज़र का आर्काइव और उसकी हस्ताक्षर डाउनलोड करें:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;wget https://www.torproject.org/dist/torbrowser/14.5.7/tor-browser-linux-x86_64-14.5.7.tar.xz
wget https://www.torproject.org/dist/torbrowser/14.5.7/tor-browser-linux-x86_64-14.5.7.tar.xz.asc&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_हस्ताक्षर_का_क्रिप्टोग्राफिक_सत्यापन&amp;quot;&amp;gt;हस्ताक्षर का क्रिप्टोग्राफिक सत्यापन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह चरण है&amp;lt;strong&amp;gt;आवश्यक&amp;lt;/strong&amp;gt;यह सुनिश्चित करने के लिए कि डाउनलोड किया गया फ़ाइल वास्तव में &amp;lt;strong&amp;gt;Tor Project&amp;lt;/strong&amp;gt; से आता है और इसे संशोधित नहीं किया गया है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_1_टोर_प्रोजेक्ट_की_सार्वजनिक_कुंजी_आयात_करें&amp;quot;&amp;gt;1. टोर प्रोजेक्ट की सार्वजनिक कुंजी आयात करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;gpg --auto-key-locate nodefault,wkd --locate-keys torbrowser@torproject.org&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सुनिश्चित करें कि कुंजी सही तरह से आयात की गई है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;gpg --list-keys torbrowser@torproject.org&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_2_हस्ताक्षर_की_जाँच_करें&amp;quot;&amp;gt;2. हस्ताक्षर की जाँच करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;gpg --verify tor-browser-linux-x86_64-14.5.7.tar.xz.asc tor-browser-linux-x86_64-14.5.7.tar.xz&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यदि सब कुछ सही है, तो निम्नलिखित संदेश प्रदर्शित होगा :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;gpg: Good signature from &amp;quot;Tor Browser Developers (signing key)&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अप्रमाणित कुंजी चेतावनी के मामले में, इसका मतलब सिर्फ यह है कि आपने अभी तक टोर प्रोजेक्ट की विश्वसनीय कुंजी पर हस्ताक्षर नहीं किए हैं, लेकिन हस्ताक्षर अभी भी वैध है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_व्यावहारिक_मामला_वैध_हस्ताक्षर_लेकिन_प्रमाणित_नहीं_की_गई_कुंजी&amp;quot;&amp;gt;व्यावहारिक मामला: वैध हस्ताक्षर लेकिन प्रमाणित नहीं की गई कुंजी&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पुष्टि के दौरान इस तरह का संदेश देखना सामान्य है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;gpg --verify tor-browser-linux-x86_64-14.5.7.tar.xz.asc tor-browser-linux-x86_64-14.5.7.tar.xz
gpg: Signature faite le mar. 16 sept. 2025 14:26:26 CEST
gpg:                avec la clef RSA CAAE408AEBE2288E96FC5D5E157432CF78A65729
gpg: Bonne signature de « Tor Browser Developers (signing key) &amp;amp;lt;torbrowser@torproject.org&amp;amp;gt; » [inconnu]
gpg: Attention : cette clef n&amp;#39;est pas certifiée avec une signature de confiance.
gpg:          Rien n&amp;#39;indique que la signature appartient à son propriétaire.
Empreinte de clef principale : EF6E 286D DA85 EA2A 4BA7  DE68 4E2C 6E87 9329 8290
     Empreinte de la sous-clef : CAAE 408A EBE2 288E 96FC  5D5E 1574 32CF 78A6 5729&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह संदेश इंगित करता है कि हस्ताक्षर तकनीकी रूप से &amp;quot;सही&amp;quot; है (फ़ाइल को बदल नहीं गया है), लेकिन आपका GPG सिस्टम स्वयं कुंजी पर &amp;lt;strong&amp;gt;विश्वास को प्रमाणित&amp;lt;/strong&amp;gt; नहीं कर सकता। इस संदेह को दूर करने के लिए, प्राथमिक कुंजी के फिंगरप्रिंट की तुलना करना आवश्यक है (&amp;lt;code&amp;gt;EF6E 286D DA85 EA2A 4BA7 DE68 4E2C 6E87 9329 8290&amp;lt;/code&amp;gt;) उस आधिकारिक टोर प्रोजेक्ट साइट पर प्रकाशित के साथ&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आधिकारिक साइट के अनुसार, अपेक्षित पदचिह्न है :`EF6E286DDA85EA2A4BA7DE684E2C6E8793298290`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;क्योंकि प्रदर्शित छाप द्वारा`gpg`यह आधिकारिक साइट की उस जैसी &amp;lt;strong&amp;gt;पूरी तरह&amp;lt;/strong&amp;gt; मेल खाता है, आप सुनिश्चित हो सकते हैं कि कुंजी वैध है और फ़ाइल सुरक्षित है। &amp;quot;अस증माणित कुंजी&amp;quot; की चेतावनी तब आपकी स्थानीय GPG कॉन्फ़िगरेशन के बारे में जानकारी होती है, और हस्ताक्षर की वैधता या फ़ाइल की प्रामाणिकता के बारे में नहीं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_साइन_क्यों_सत्यापित_करें&amp;quot;&amp;gt;साइन क्यों सत्यापित करें ?&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;GPG हस्ताक्षरों की जांच डिजिटल सुरक्षा का एक मूलभूत कार्य है। यह करने की अनुमति देती है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;गारंटी देना&amp;lt;strong&amp;gt;प्रामाणिकता&amp;lt;/strong&amp;gt;डाउनलोड किया गया सॉफ़्टवेयर का&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एक दुर्भावनापूर्ण अभिनेता द्वारा समझौता किए गए फ़ाइल की स्थापना को रोकें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;भाग लेना&amp;lt;strong&amp;gt;डिजिटल संप्रभुता&amp;lt;/strong&amp;gt;व्यक्तिगत&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एक जिम्मेदार और नैतिक डिजिटल संस्कृति को बढ़ावा दें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;usecase-tor-verification.svg&amp;quot; alt=&amp;quot;usecase tor verification&amp;quot; width=&amp;quot;450&amp;quot; height=&amp;quot;292&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_टॉर_ब्राउज़र_की_एक्सट्रैक्शन_और_लॉन्च&amp;quot;&amp;gt;टॉर ब्राउज़र की एक्सट्रैक्शन और लॉन्च&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;डाउनलोड की गई आर्काइव को निकालें:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;tar -xvf tor-browser-linux-x86_64-14.5.7.tar.xz
cd tor-browser&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फिर ब्राउज़र लॉन्च करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;./start-tor-browser.desktop&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पहले लॉन्च के दौरान, एक कॉन्फ़िगरेशन विंडो खुल जाएगी ताकि टोर नेटवर्क से कनेक्शन स्थापित किया जा सके।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_उबुन्टू_डेस्कटॉप_एकीकरण&amp;quot;&amp;gt;उबुन्टू डेस्कटॉप एकीकरण&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एप्लिकेशन मेन्यू में &amp;lt;strong&amp;gt;Tor Browser&amp;lt;/strong&amp;gt; जोड़ने के लिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;./start-tor-browser.desktop --register-app&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आप फिर से कर सकते हैं:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एप्लिकेशन मेनू से &amp;lt;strong&amp;gt;Tor Browser&amp;lt;/strong&amp;gt; लॉन्च करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;इसे डॉक के पसंदीदा में जोड़ें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;यदि आप चाहें तो कीबोर्ड शॉर्टकट बनाएँ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;activity-tor-installation.svg&amp;quot; alt=&amp;quot;activity tor installation&amp;quot; width=&amp;quot;457&amp;quot; height=&amp;quot;470&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_tor_के_साथ_शैक्षिक_संसाधनों_का_अन्वेषण_करें&amp;quot;&amp;gt;Tor के साथ शैक्षिक संसाधनों का अन्वेषण करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Tor केवल एक अनामिकता उपकरण नहीं है। यह शैक्षिक और अनुसंधान संसाधनों तक पहुँच का एक प्रवेश द्वार है, विशेष रूप से निम्नलिखित क्षेत्रों में :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;ओसिंट (सार्वजनिक स्रोत खुफिया)&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://inteltechniques.com&amp;quot;&amp;gt;https://inteltechniques.com&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://osintframework.com&amp;quot;&amp;gt;https://osintframework.com&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;शैक्षिक साझाकरण और ओपन सोर्स&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://archive.org&amp;quot;&amp;gt;https://archive.org&amp;lt;/a&amp;gt;(Tor के माध्यम से पहुँच के लिए अधिक गोपनीयता)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/&amp;quot;&amp;gt;https://github.com/&amp;lt;/a&amp;gt;(Tor के माध्यम से सुलभ)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://librarygenesis.pro&amp;quot;&amp;gt;https://librarygenesis.pro&amp;lt;/a&amp;gt;(मुक्त वैज्ञानिक साहित्य तक पहुँच)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;ज्ञान का संप्रेषण और मानव की समझ डिजिटल समाज में&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;डिजिटल संस्कृति, अभिव्यक्ति की स्वतंत्रता और ज्ञान तक पहुँच के संसाधन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;तकनीकों की साइबर सुरक्षा और नैतिकता पर मुक्त दस्तावेज़&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_tor_browser_का_अपडेट&amp;quot;&amp;gt;Tor Browser का अपडेट&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अधतम सुरक्षा सुनिश्चित करने के लिए, &amp;lt;strong&amp;gt;Tor Browser&amp;lt;/strong&amp;gt; को अद्यतित रखना अत्यंत महत्वपूर्ण है। ब्राउज़र में एक स्वचालित अपडेट तंत्र बनाया गया है जिसे कमांड लाइन से ट्रिगर किया जा सकता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Tor Browser स्थापना निर्देशिका से, बस स्टार्टअप स्क्रिप्ट को पुनः आरंभ करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;cd ~/workspace/tipiak/tor/tor-browser
./start-tor-browser.desktop&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;लॉन्च पर, &amp;lt;strong&amp;gt;Tor Browser&amp;lt;/strong&amp;gt; स्वचालित रूप से जांचेगा कि क्या एक नया संस्करण उपलब्ध है। यदि ऐसा है, तो यह इसे डाउनलोड और स्थापित करेगा आपके लिए।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह साधारण विधि सुनिश्चित करती है कि आपके पास हमेशा नवीनतम सुरक्षा पैच और सबसे हालिया सुधार हों, जो सुरक्षित ब्राउज़िंग के लिए आवश्यक है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपने डाउनलोड की जाँच करना एक आवश्यक आदत है, जो सुरक्षित डिजिटल वातावरण में प्रगति करने वाले हर व्यक्ति के लिए महत्वपूर्ण है। टॉर को सत्यापित तरीके से स्थापित करना, यह&amp;lt;strong&amp;gt;अपनी डिजिटल अखंडता की रक्षा करें&amp;lt;/strong&amp;gt;, &amp;lt;strong&amp;gt;मुक्त सॉफ़्टवेयर में विश्वास बनाए रखें&amp;lt;/strong&amp;gt;, et &amp;lt;strong&amp;gt;अपनी सूचना स्वायत्तता को मज़बूत करना&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;डिजिटल सुरक्षा एक जागरूकता का कार्य है, न कि पागलपन का।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;summary-diagram.svg&amp;quot; alt=&amp;quot;summary diagram&amp;quot; width=&amp;quot;1594&amp;quot; height=&amp;quot;5396&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_संदर्भ&amp;quot;&amp;gt;संदर्भ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;टोर प्रोजेक्ट की आधिकारिक साइट :https://www.torproject.org/download/[&amp;lt;a href=&amp;quot;https://www.torproject.org/download/&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://www.torproject.org/download/&amp;lt;/a&amp;gt;]&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;हस्ताक्षर सत्यापन दस्तावेज़ :https://support.torproject.org/tbb/how-to-verify-signature/[&amp;lt;a href=&amp;quot;https://support.torproject.org/tbb/how-to-verify-signature/&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://support.torproject.org/tbb/how-to-verify-signature/&amp;lt;/a&amp;gt;]&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Ubuntu दस्तावेज़ :https://ubuntu.com[&amp;lt;a href=&amp;quot;https://ubuntu.com&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://ubuntu.com&amp;lt;/a&amp;gt;]&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;शैक्षिक संग्रह :https://archive.org/details/opensource[&amp;lt;a href=&amp;quot;https://archive.org/details/opensource&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://archive.org/details/opensource&amp;lt;/a&amp;gt;]&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;Note&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह लेख &amp;lt;strong&amp;gt;सुरक्षा और डिजिटल जागरूकता&amp;lt;/strong&amp;gt; श्रृंखला का हिस्सा है। जिम्मेदार और शैक्षिक प्रथाओं को बढ़ावा देने हेतु स्वतंत्र टूल्स के चारों ओर.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>लेख 5 : libs.versions.toml साझा का रोमांच</title>
            <link >https://cheroliv.com/blog/2025/0093_gradle_plugin_toml_composite_build_post.html</link>
            <pubDate>Sat, 27 Sep 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0093_gradle_plugin_toml_composite_build_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;लक्षित दर्शक : Gradle डेवलपर्स जो मल्टी-बिल्ड प्रोजेक्ट्स में निर्भरता प्रबंधन का सामना कर रहे हैं।&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;हमारे प्लग़िन बनाने की खोज में`site-baker`हमने एक स्वच्छ और केंद्रीकृत कोडベース को बनाए रखने का प्रयास किया है। आधुनिक ग्रैडल इकोसिस्टम में एक सर्वोत्तम प्रथा इसका उपयोग करना है।&amp;lt;strong&amp;gt;संस्करणों की सूची&amp;lt;/strong&amp;gt;(&amp;lt;code&amp;gt;libs.versions.toml&amp;lt;/code&amp;gt;) निर्भरताओं को प्रबंधित करने के लिए। लेकिन जब आपका प्रोजेक्ट अधिक जटिल हो जाता है, जैसे एक**&amp;lt;mark&amp;gt;#&amp;lt;/mark&amp;gt; ग्रेडल इंटीग्रेशन JBake को JBake ग्रेडल प्लगइन का उपयोग करके या JBake CLI को सीधे बुलाकर ग्रेडल बिल्ड में एकीकृत किया जा सकता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;----
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
}**कहाँ एक स्वतंत्र बिल्ड (हमारा प्लगिन) को दूसरे में शामिल किया जाना चाहिए ?

यह वही जगह थी जहाँ हमारी यात्रा ने अप्रत्याशित मोड़ ले लिया। हम चाहते थे कि हमारा प्लगइन`site-baker`, जो स्वयं एक Gradle प्रोजेक्ट है, हमारे मुख्य प्रोजेक्ट के समान संस्करण कैटलॉग का उपयोग करता है। यह लेख, हमारी श्रृंखला का पाँचवाँ, बताता है कि हमने इस चुनौती को कैसे हल किया।

== 1. वर्ज़न कैटलॉग (`libs.versions.toml`) : एक अनुस्मरण

फ़ाइल`gradle/libs.versions.toml`यह Gradle की एक सुविधा है जो आपके परियोजना के निर्भरताओं के संस्करण और निर्देशांक को केंद्रीकृत करने की अनुमति देती है। इसकी सामान्य रूप से चार खंडों में संरचना होती है:

*   `[versions]`: परिभाषित करता है संस्करण संख्याओं के लिए एलियास (उदाहरण:`kotlin = &amp;quot;1.9.20&amp;quot;`).
*   `[libraries]`: परिभाषित करता है अलियास पूर्ण निर्भरताओं के लिए, ऊपर परिभाषित संस्करणों का उपयोग करके (ex:`kotlin-stdlib = { module = &amp;quot;org.jetbrains.kotlin:kotlin-stdlib&amp;quot;, version.ref = &amp;quot;kotlin&amp;quot; }`).
*   `[bundles]`कई लाइब्रेरीज़ को एक ही एलियास के तहत समूहित करता (उदाहरण:`jackson = [&amp;quot;jackson-core&amp;quot;, &amp;quot;jackson-databind&amp;quot;]`)
*   `[plugins]`: ग्रैडल प्लगिन के लिए एलियास परिभाषित करता है।

एक बार परिभाषित करने पर, Gradle स्वचालित रूप से टाइप किए हुए एक्सेसर उत्पन्न करता है, जिससे आपका`build.gradle.kts` beaucoup plus lisible :

[source,kotlin]
----
dependencies {
    // Au lieu de : implementation(&amp;quot;org.jetbrains.kotlin:kotlin-stdlib:1.9.20&amp;quot;)
    implementation(libs.kotlin.stdlib)
}
----

.संस्करण कैटलॉग का डेटा प्रवाह

[plantuml, toml-flow, svg]
----
@startuml
!theme plain
file &amp;quot;gradle/libs.versions.toml&amp;quot; as Toml
node &amp;quot;ग्रैडल&amp;quot; as G
file &amp;quot;build.gradle.kts&amp;quot; as BuildScript

Toml --&amp;amp;gt; G : &amp;quot;द्वारा पढ़ा जाता है&amp;quot;
G --&amp;amp;gt; BuildScript : &amp;quot;एक्सेसर `libs` जेनरेट करें&amp;quot;
BuildScript -&amp;amp;gt; G : &amp;quot;libs` का उपयोग करके निर्भरताओं की घोषणा करें&amp;quot;
@enduml
----

== 2. समस्या: एक संयुक्त बिल्ड और दो अलग‑अलग दुनियाएँ

हमारी परियोजना संरचना एक**JBake को Gradle बिल्ड में JBake Gradle प्लगइन का उपयोग करके या JBake CLI को सीधे कॉल करके एकीकृत किया जा सकता है:

----

tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) { mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;) classpath = configurations[&amp;quot;jbake&amp;quot;] args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;) }**. मुख्य परियोजना (`thymeleaf.cheroliv.com`) inclut le projet du plugin (`site-baker`) के माध्यम से आदेश`includeBuild(&amp;quot;site-baker&amp;quot;)`फ़ाइल में`settings.gradle.kts`.

.build composite की संरचना

[plantuml, composite-build, svg]
----
@startuml
!theme plain
package &amp;quot;मुख्य परियोजना&amp;quot; {
  file &amp;quot;settings.gradle.kts&amp;quot; as MainSettings
  folder &amp;quot;gradle&amp;quot; {
    file &amp;quot;libs.versions.toml&amp;quot; as MainToml
  }
}

package &amp;quot;### ग्रैडल एकीकरण
JBake को JBake ग्रैडल प्लगइन का उपयोग करके या JBake CLI को सीधे कॉल करके ग्रैडल बिल्ड में एकीकृत किया जा सकता है:

```kotlin
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
}&amp;quot; {
  file &amp;quot;settings.gradle.kts&amp;quot; as PluginSettings
  file &amp;quot;build.gradle.kts&amp;quot; as PluginBuild
}

MainSettings -&amp;amp;gt; PluginSettings : `includeBuild(&amp;quot;स्थान-बेकर&amp;quot;)`
PluginBuild ..&amp;amp;gt; MainToml : **Voulait accéder à...**
note right on link: ...mais ne pouvait pas !
@enduml
----

समस्या यह है कि, डिफ़ॉल्ट रूप से, एक शामिल बिल्ड एक है**अलग दुनिया**. इसकी अपनी कॉन्फ़िगरेशन, इसका अपना जीवन चक्र, और यह फ़ाइल को नहीं देखता`libs.versions.toml`मुख्य बिल्ड का. हमारा`plugin/build.gradle.kts`उपयोग करने की कोशिश कर रहा था`libs.plugins.kotlin.jvm`, लेकिन वस्तु`libs`सही TOML फ़ाइल से उत्पन्न नहीं किया गया था, जिससे बिल्ड त्रुटियाँ हुईं।

== 3. समाधान : निर्भरता समाधान साझा करना

कई शोधों के बाद, यह समाधान Gradle की एक ऐसी विशेषता निकली जो इस मामले के लिए विशेष रूप से डिज़ाइन की गई थी :`dependencyResolutionManagement`.

फ़ाइल में`settings.gradle.kts` du **समावेशी निर्माण**import sys

def main(): data = sys.stdin.read() sys.stdout.write(data)

if __name__ == &amp;#39;__main__&amp;#39;: main()`site-baker/settings.gradle.kts`), हम Gradle को बता सकते हैं कि संस्करण कैटलॉग कहाँ से उपयोग करने के लिए प्राप्त किया जा सकता है।

यहाँ वह कॉन्फ़िगरेशन है जिसे हमने जोड़ा है`site-baker/settings.gradle.kts`:

[source,kotlin]
----
// site-baker/settings.gradle.kts

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        gradlePluginPortal()
        mavenCentral()
    }
    versionCatalogs {
        create(&amp;quot;libs&amp;quot;) {
            from(files(&amp;quot;../gradle/libs.versions.toml&amp;quot;))
        }
    }
}

rootProject.name = &amp;quot;site-baker&amp;quot;
include(&amp;quot;plugin&amp;quot;)
----

महत्वपूर्ण भाग का विश्लेषण करें:

[source,kotlin]
----
versionCatalogs {
    create(&amp;quot;libs&amp;quot;) { // Crée un catalogue nommé &amp;#39;libs&amp;#39;
        from(files(&amp;quot;../gradle/libs.versions.toml&amp;quot;)) // En utilisant ce fichier
    }
}
----

*   `create(&amp;quot;libs&amp;quot;)`: हम संस्करणों का एक कैटलॉग घोषित करते हैं जिसे लियास के माध्यम से पहुँचा जा सकेगा`libs`.
*   `from(files(&amp;quot;../gradle/libs.versions.toml&amp;quot;))`: यह जादू है। हम Gradle को बताते हैं कि इस कैटलॉग का स्रोत TOML फ़ाइल निर्देशिका में स्थित है।`gradle` du **मातृ परियोजना**(No output)`../`)

इस कॉन्फ़िगरेशन के साथ, बिल्ड`site-baker`अब उसे पता है कि उसे मुख्य प्रोजेक्ट के संस्करण कैटलॉग का उपयोग करना होगा। वस्तु`libs`सही ढंग से उत्पन्न किया गया है, और निर्भरताएँ अपेक्षित रूप से समाधान कर ली गई हैं।

== 4. निष्कर्ष : अच्छी तरह से प्रबंधित संयुक्त निर्माणों की शक्ति

यह अनुभव सीखों से भरपूर रहा। संस्करण कैटलॉग रखरखाव के लिए एक शानदार उपकरण है, लेकिन कंपोज़िट बिल्ड परिदृश्यों में उसका व्यवहार हमेशा सहज नहीं होता।

की याद रखनी है कि एक समावेशी बिल्ड एक स्वतंत्र बिल्ड ही रहता है। संस्करण कैटलॉग जैसी कॉन्फ़िगरेशन साझा करने के लिए, Gradle द्वारा प्रदान किए गए स्पष्ट तंत्र का उपयोग करना आवश्यक है, जैसे ब्लॉक।`dependencyResolutionManagement`में`settings.gradle.kts`.

इस समस्या को हल करके, हमने न केवल अपने build को साफ़ किया, बल्कि हमने अपने प्रोजेक्ट की स्थिरता को भी मजबूत किया है, यह सुनिश्चित करके कि प्लगइन और मुख्य प्रोजेक्ट एक ही स्रोत की सच्चाई साझा करते हैं अपने dependencies के लिए।

अगले आर्टिकल में, हम अब अधिक जटिल कार्य जोड़कर अपने प्लगइन को समृद्ध करना जारी रखेंगे, क्योंकि अब हमारी निर्भरता प्रबंधन मजबूत और केंद्रीकृत है।&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>अनुच्छेद 4 : ग्रैडल कॉन्फ़िगरेशन कैश का जाल</title>
            <link >https://cheroliv.com/blog/2025/0092_gradle_configuration_cache_post.html</link>
            <pubDate>Fri, 26 Sep 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0092_gradle_configuration_cache_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_लक्षण_भूतिया_बिल्ड्स&amp;quot;&amp;gt;लक्षण : भूतिया बिल्ड्स&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_जांच_कॉन्फ़िगरेशन_कैश_क्या_है&amp;quot;&amp;gt;जांच: कॉन्फ़िगरेशन कैश क्या है?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_का_कारण_एक_अनुपालन_न_करने_वाला_प्लगइन&amp;quot;&amp;gt;समस्या का कारण: एक अनुपालन न करने वाला प्लगइन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अस्थायी_समाधान_कैश_को_निष्क्रिय_करें&amp;quot;&amp;gt;अस्थायी समाधान : कैश को निष्क्रिय करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_वास्तविक_समाधान_प्लगिन_को_संगत_बनाना&amp;quot;&amp;gt;वास्तविक समाधान: प्लगिन को संगत बनाना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;lक्ष्यित दर्शक : वे Gradle डेवलपर्स जो पहले से ही &amp;#39;जादुई&amp;#39; या अप्रत्याशित बिल्ड व्यवहार का सामना कर चुके हैं।&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;हमारे प्लगइन बनाने की यात्रा में`site-baker`, हमने एक कड़े TDD दृष्टिकोण का पालन किया। हर सुविधा का परीक्षण किया गया, सत्यापित किया गया, और हम विश्वास के साथ आगे बढ़ रहे थे। और फिर, एक दिन, अप्रत्याशित घटना हुई। बिल्ड्स अनियमित रूप से व्यवहार करने लगे। प्लगइन के लॉजिक या कॉन्फ़िगरेशन फ़ाइलों में किए गए संशोधनों को नजरअंदाज किया जा रहा प्रतीत होता था, और हमारे कार्यात्मक परीक्षण, जो पहले विश्वसनीय थे, स्पष्ट कारण बिना विफल हो रहे थे।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस तरह की समस्या अविश्वसनीय रूप से निराशाजनक हो सकती है। यह उपकरण की विश्वसनीयता और हमारे कोड की वैधता पर सवाल उठाता है। गहन डिबगिंग सत्र के बाद, दोषी पहचान लिया गया है: वह&amp;lt;strong&amp;gt;Gradle की कॉन्फ़िगरेशन कैश&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_लक्षण_भूतिया_बिल्ड्स&amp;quot;&amp;gt;लक्षण : भूतिया बिल्ड्स&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;समस्या कई तरीकों से प्रकट हो रही थी :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;मैं एक कार्य में एक अक्षर श्रृंखला संशोधित कर रहा था`println`, लेकिन पुरानी स्ट्रिंग चलने के दौरान प्रदर्शित होती रही।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;मैं अपनी फाइल में एक मान बदल रहा था`managed-jbake-context.yml`, लेकिन प्लगिन ऐसा व्यवहार कर रहा था जैसे फ़ाइल में कोई संशोधन नहीं किया गया था।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कार्यात्मक परीक्षण, जो तत्काल परीक्षण परियोजनाएँ बनाते हैं, विफल हो रहे थे क्योंकि प्लगइन प्रतीत होता था कि ताज़ा बनाई गई कॉन्फ़िगरेशन फ़ाइलों का पता नहीं लगा पा रहा है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सब कुछ ऐसा लग रहा था जैसे Gradle हमारे बिल्ड की एक &amp;quot;फ़ेंटम संस्करण&amp;quot; को चला रहा हो, हमारे सबसे हालिया बदलावों को अनदेखा करते हुए।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_जांच_कॉन्फ़िगरेशन_कैश_क्या_है&amp;quot;&amp;gt;जांच: कॉन्फ़िगरेशन कैश क्या है?&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;कन्फ़िगरेशन कैश Gradle की एक आधुनिक और बहुत शक्तिशाली विशेषता है, जो नए संस्करणों में डिफ़ॉल्ट रूप से सक्रिय है। इसका उद्देश्य बिल्ड को तेज़ करना है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;सिद्धांत सरल है :&amp;lt;/div&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;पहली बार चलाने पर, Gradle चरण को निष्पादित करता है&amp;lt;strong&amp;gt;Configuration&amp;lt;/strong&amp;gt; (lecture des &amp;lt;code&amp;gt;build.gradle.kts&amp;lt;/code&amp;gt;, कार्यों की रचना, निर्भरताओं का समाधान) और एक कार्य ग्राफ़ बनाता है.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;इस चरण के अंत में, Gradle&amp;lt;strong&amp;gt;इस टास्क ग्राफ को सिरीयलाइज़ करें&amp;lt;/strong&amp;gt;और वह इसे कैश में रखता/रखती है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;अनुसरण करने वाले निष्पादनों में, यदि कुछ भी नहीं बदलता (बिल्ड स्क्रिप्ट्स,&amp;lt;code&amp;gt;gradle.properties&amp;lt;/code&amp;gt;, etc.), Gradle&amp;lt;strong&amp;gt;यह पूरी तरह से कॉन्फ़िगरेशन चरण को छोड़ देता है&amp;lt;/strong&amp;gt;और कैश किए गए कार्य ग्राफ़ को पुनः उपयोग करता है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;बड़े प्रोजेक्ट्स पर समय की बचत अद्भुत है। हालाँकि, इस प्रदर्शन की एक कीमत है: यह प्लगइन्स के लिखे जाने के तरीके पर सख्त नियम लागू करती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;config-cache-lifecycle.svg&amp;quot; alt=&amp;quot;config cache lifecycle&amp;quot; width=&amp;quot;661&amp;quot; height=&amp;quot;709&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Figure 1. कॉन्फ़िगरेशन कैश का जीवन चक्र&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या_का_कारण_एक_अनुपालन_न_करने_वाला_प्लगइन&amp;quot;&amp;gt;समस्या का कारण: एक अनुपालन न करने वाला प्लगइन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारा प्लगइन`site-baker`वह अनजाने में कॉन्फ़िगरेशन कैश के कई नियमों का उल्लंघन कर रहा था। एक टास्क ग्राफ़ को सीरियलाइज़ करने योग्य बनाने के लिए, टास्क में कॉम्प्लेक्स ऑब्जेक्ट्स जैसे ऑब्जेक्ट के संदर्भ नहीं होने चाहिए।`Project`या फ़ाइलों को निष्पादन चरण के दौरान मनमाने ढंग से पढ़ें।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारी मुख्य त्रुटि यह थी कि हमने YAML फ़ाइल की सामग्री को कार्य के निष्पादन तर्क के भीतर सीधे पढ़ा, अपने एक्सटेंशन में संग्रहीत पथ संदर्भ का उपयोग करके। यह दृष्टिकोण कैश के साथ असंगत है क्योंकि Gradle नहीं जान सकता कि फ़ाइल की सामग्री बदल गई है यदि इस पढ़ाई को मॉडल नहीं बनाया गया है एक के रूप में.&amp;lt;strong&amp;gt;कार्य प्रविष्टि&amp;lt;/strong&amp;gt;(Task Input).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_अस्थायी_समाधान_कैश_को_निष्क्रिय_करें&amp;quot;&amp;gt;अस्थायी समाधान : कैश को निष्क्रिय करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमें अनब्लॉक करने और पूर्वानुमेय बिल्ड व्यवहार को फिर से प्राप्त करने के लिए, सबसे तेज़ समाधान कॉन्फ़िगरेशन कैश को अक्षम करना रहा। बस फ़ाइल में निम्नलिखित लाइन जोड़ें।&amp;lt;code&amp;gt;gradle.properties`प्लगिन का उपयोग करने वाला प्रोजेक्ट (या हमारे मामले में, परीक्षण प्रोजेक्ट)`site-baker&amp;lt;/code&amp;gt;).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-properties hljs&amp;quot; data-lang=&amp;quot;properties&amp;quot;&amp;gt;# site-baker/gradle.properties
org.gradle.configuration-cache=false&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;तुरंत, बिल्ड्स ने अपना सामान्य व्यवहार फिर से हासिल कर लिया। प्रत्येक निष्पादन ने कॉन्फ़िगरेशन चरण को फिर से शुरू किया और हमारे परिवर्तन ध्यान में रखे गए।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हालाँकि, यह एक टर्नअराउंड समाधान है, एक स्थायी समाधान नहीं। यह प्रदर्शन को त्याग देती है और हमारे प्लगइन की मूल समस्या को हल नहीं करती।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_वास्तविक_समाधान_प्लगिन_को_संगत_बनाना&amp;quot;&amp;gt;वास्तविक समाधान: प्लगिन को संगत बनाना&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक प्लगइन आधुनिक Gradle इकोसिस्टम का एक अच्छा नागरिक बनने के लिए, इसे कॉन्फ़िगरेशन कैश के साथ संगत होना चाहिए। इसका मतलब है कि हमें अपने कार्यों की ओर डेटा प्रवाह के तरीके को पुनर्विचार करने की आवश्यकता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;कुंजी का उपयोग करने की&amp;lt;strong&amp;gt;प्रोवाइडर एपीआई&amp;lt;/strong&amp;gt;Gradle के लिए. सीधे मान पास करने के बजाय (जैसे एक`String` ou un &amp;lt;code&amp;gt;File&amp;lt;/code&amp;gt;) हमारे कार्यों के लिए, हमें बिताना चाहिए के`Property&amp;amp;lt;T&amp;amp;gt;`या कुछ`Provider&amp;amp;lt;T&amp;amp;gt;`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;।यहाँ रिफैक्टरिंग योजना :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;कार्य प्रविष्टियों की घोषणा करें:&amp;lt;/strong&amp;gt;YAML फ़ाइल को पार्स करने वाला कार्य इसे इनपुट के रूप में घोषित करना चाहिए। इसके लिए हम एनोटेशन का उपयोग करते हैं।&amp;lt;code&amp;gt;@InputFile&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;[source,kotlin] ---- @get:InputFile अमूर्त मान configFile: RegularFileProperty ----&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>लेख 3 : TDD के साथ YAML पार्सिंग के लिए Jackson का Gradle प्लगिन में एकीकरण</title>
            <link >https://cheroliv.com/blog/2025/0091_jackson_yaml_tdd_post.html</link>
            <pubDate>Thu, 25 Sep 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0091_jackson_yaml_tdd_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_1_संदर्भ_हमारा_प्लग़िन_site_baker&amp;quot;&amp;gt;1. संदर्भ : हमारा प्लग़िन `site-baker&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_2_कॉन्फ़िगरेशन_मॉडलिंग_कोटलिन_में&amp;quot;&amp;gt;2. कॉन्फ़िगरेशन मॉडलिंग कोटलिन में&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_3_jackson_का_build_gradle_kts_में_एकीकरण&amp;quot;&amp;gt;3. Jackson का &amp;lt;code&amp;gt;build.gradle.kts&amp;lt;/code&amp;gt; में एकीकरण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_4_tdd_पद्धति_yaml_पार्सिंग_का_परीक्षण&amp;quot;&amp;gt;4. TDD पद्धति: YAML पार्सिंग का परीक्षण&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_4_1_test_unitaire_mapper_le_yaml_en_objet_kotlin&amp;quot;&amp;gt;4.1. Test Unitaire : Mapper le YAML en Objet Kotlin&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_4_2_कार्यात्मक_परीक्षण_कॉन्फ़िगरेशन_फ़ाइल_की_पढ़ी_को_मान्य_करें&amp;quot;&amp;gt;4.2. कार्यात्मक परीक्षण : कॉन्फ़िगरेशन फ़ाइल की पढ़ी को मान्य करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_5_पार्सिंग_फ़्लो_का_दृश्यीकरण&amp;quot;&amp;gt;5. पार्सिंग फ़्लो का दृश्यीकरण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;लक्ष्य दर्शक: मध्यवर्ती Gradle डेवलपर जो जटिल कॉन्फ़िगरेशन प्रबंधित करना चाहते हैं।&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Gradle प्लगिन डेवलपमेंट में, जटिल कॉन्फ़िगरेशन का प्रबंधन एक सामान्य कार्य है। DSL को हज़ारों प्रॉपर्टीज़ से ओवरलोड करने के बजाय, अक्सर साफ और मेंटेनेबल रखने के लिए कॉन्फ़िगरेशन को YAML जैसे बाहरी फ़ाइल में परिभाषित करना बेहतर होता है। यह लेख आपको Jackson की शक्तिशाली लाइब्रेरी को इंटीग्रेट करने के माध्यम से मार्गदर्शन करता है, जिससे YAML फ़ाइलों को Kotlin ऑब्जेक्ट्स में पार्स किया जा सके, एक कड़ी TDD पद्धति अपनाकर हमारे प्लगिन की रोबस्टनेस सुनिश्चित की जा सके।&amp;lt;code&amp;gt;site-baker&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_1_संदर्भ_हमारा_प्लग़िन_site_baker&amp;quot;&amp;gt;1. संदर्भ : हमारा प्लग़िन `site-baker&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारा प्लगइन`site-baker`इसे एक स्थिर साइट की पीढ़ी और तैनाती को स्वचालित करने के लिए डिज़ाइन किया गया है। इसे YAML कॉन्फ़िगरेशन फ़ाइल पढ़ने की आवश्यकता है (&amp;lt;code&amp;gt;managed-jbake-context.yml&amp;lt;/code&amp;gt;) स्रोतों के पथ, तैनाती के गंतव्य, और Git पहचानकर्ता जैसी जानकारी प्राप्त करने के लिए&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हम जो YAML कॉन्फ़िगरेशन पार्स करना चाहते हैं, वह इस तरह दिखता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-yaml hljs&amp;quot; data-lang=&amp;quot;yaml&amp;quot;&amp;gt;bake:
  srcPath: &amp;quot;./site/jbake&amp;quot;
  destDirPath: &amp;quot;bake&amp;quot;
  cname: &amp;quot;cheroliv.com&amp;quot;
pushPage:
  from: &amp;quot;bake&amp;quot;
  to: &amp;quot;cvs&amp;quot;
  repo:
    name: &amp;quot;trainings&amp;quot;
    repository: &amp;quot;https://github.com/pages-content/pages-content.github.io.git&amp;quot;
    credentials:
      username: &amp;quot;USERNAME&amp;quot;
      password: &amp;quot;SECRET_TOKEN&amp;quot;
  branch: &amp;quot;main&amp;quot;
  message: &amp;quot;cheroliv.com&amp;quot;
# ... autres configurations (pushMaquette, supabase, etc.)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_2_कॉन्फ़िगरेशन_मॉडलिंग_कोटलिन_में&amp;quot;&amp;gt;2. कॉन्फ़िगरेशन मॉडलिंग कोटलिन में&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पार्स करने से पहले, हमें कोटलिन में अपने डेटा की संरचना परिभाषित करनी होगी। जैक्सन इन क्लासेस का उपयोग करके YAML सामग्री को स्वचालित रूप से मैप करेगा।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// plugin/src/main/kotlin/com/cheroliv/site/baker/data/SiteConfiguration.kt
package com.cheroliv.site.baker.data

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import com.fasterxml.jackson.module.kotlin.readValue
import com.fasterxml.jackson.module.kotlin.registerKotlinModule

fun parseSiteConfiguration(yaml: String): SiteConfiguration {
    val mapper = ObjectMapper(YAMLFactory()).registerKotlinModule()
    return mapper.readValue(yaml)
}

data class GitPushConfiguration(
    val from: String = &amp;quot;&amp;quot;,
    val to: String = &amp;quot;&amp;quot;,
    val repo: RepositoryConfiguration = RepositoryConfiguration(),
    val branch: String = &amp;quot;&amp;quot;,
    val message: String = &amp;quot;&amp;quot;,
)

data class RepositoryConfiguration(
    val name: String = &amp;quot;&amp;quot;,
    val repository: String = &amp;quot;&amp;quot;,
    val credentials: RepositoryCredentials = RepositoryCredentials(),
) {
    companion object {
        const val ORIGIN = &amp;quot;origin&amp;quot;
        const val CNAME = &amp;quot;CNAME&amp;quot;
        const val REMOTE = &amp;quot;remote&amp;quot;
    }
}

data class RepositoryCredentials(val username: String = &amp;quot;&amp;quot;, val password: String = &amp;quot;&amp;quot;)

data class SiteConfiguration(
    val bake: BakeConfiguration = BakeConfiguration(),
    val pushPage: GitPushConfiguration = GitPushConfiguration(),
    val pushMaquette: GitPushConfiguration = GitPushConfiguration(),
    val pushSource: GitPushConfiguration? = null,
    val pushTemplate: GitPushConfiguration? = null,
    val supabase: SupabaseContactFormConfig? = null
)

data class BakeConfiguration(
    val srcPath: String = &amp;quot;&amp;quot;,
    val destDirPath: String = &amp;quot;&amp;quot;,
    val cname: String? = null,
)

// ... (autres data classes pour Supabase, si nécessaire)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फ़ंक्शन`parseSiteConfiguration`यह हमारे डीज़ीसीरियलाइज़ेशन के लिए प्रवेश बिंदु है। यह उपयोग करती है`ObjectMapper`Jackson का, कॉन्फ़िगर किया गया`YAMLFactory`YAML प्रारूप के लिए और`registerKotlinModule()`कोटलिन की विशिष्टताओं के समर्थन के लिए (जैसे प्रॉपर्टी के डिफ़ॉल्ट मान).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_3_jackson_का_build_gradle_kts_में_एकीकरण&amp;quot;&amp;gt;3. Jackson का &amp;lt;code&amp;gt;build.gradle.kts&amp;lt;/code&amp;gt; में एकीकरण&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जैकसन का उपयोग करने के लिए, हमें आवश्यक निर्भरताएँ जोड़नी हैं में`build.gradle.kts`हमारे मॉड्यूल का`plugin`(No output)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// plugin/build.gradle.kts
dependencies {
    // Jackson for YAML parsing
    implementation(&amp;quot;com.fasterxml.jackson.module:jackson-module-kotlin:2.18.3&amp;quot;)
    implementation(&amp;quot;com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.18.3&amp;quot;)

    // ... autres dépendances
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हम उपयोग करते हैं`jackson-module-kotlin`कोटलिन समर्थन के लिए और`jackson-dataformat-yaml`YAML प्रारूप के प्रबंधन के लिए&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_4_tdd_पद्धति_yaml_पार्सिंग_का_परीक्षण&amp;quot;&amp;gt;4. TDD पद्धति: YAML पार्सिंग का परीक्षण&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अब, हम अपने पार्सिंग लॉजिक को सत्यापित करने के लिए TDD लागू करते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_4_1_test_unitaire_mapper_le_yaml_en_objet_kotlin&amp;quot;&amp;gt;4.1. Test Unitaire : Mapper le YAML en Objet Kotlin&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हम एक यूनिट टेस्ट से शुरू करते हैं`SiteBakerPluginTest.kt`फ़ंक्शन की जाँच करने के लिए`parseSiteConfiguration`यह YAML स्ट्रिंग को सही ढंग से ऑब्जेक्ट में बदल सकता है`SiteConfiguration`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// plugin/src/test/kotlin/com/cheroliv/site/baker/SiteBakerPluginTest.kt
@Test
fun `can map configuration text to SiteConfiguration object`() {
    val yamlString = &amp;quot;../../managed-jbake-context.yml&amp;quot;
        .run(::File)
        .readText()
        .trimIndent()

    val config: SiteConfiguration = parseSiteConfiguration(yamlString)

    assertEquals(&amp;quot;cheroliv.com&amp;quot;, config.bake.cname)
    assertEquals(&amp;quot;main&amp;quot;, config.pushPage.branch)
    assertEquals(&amp;quot;https://github.com/pages-content/pages-content.github.io.git&amp;quot;, config.pushPage.repo.repository)
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह परीक्षण फ़ाइल की सामग्री पढ़ता है`managed-jbake-context.yml`(जो परीक्षण वैध होने के लिए मौजूद होना चाहिए) और वस्तु पर दावे करता है`SiteConfiguration`परिणामी. यह सत्यापित करता है कि YAML की मुख्य मान सही ढंग से मैप की गई हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_4_2_कार्यात्मक_परीक्षण_कॉन्फ़िगरेशन_फ़ाइल_की_पढ़ी_को_मान्य_करें&amp;quot;&amp;gt;4.2. कार्यात्मक परीक्षण : कॉन्फ़िगरेशन फ़ाइल की पढ़ी को मान्य करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह सुनिश्चित करने के लिए कि प्लगइन अपने DSL के माध्यम से कॉन्फ़िगरेशन फ़ाइल पढ़ सके और पार्सिंग एक वास्तविक Gradle वातावरण में काम करे, हम एक फ़ंक्शनल टेस्ट जोड़ते हैं`SiteBakerPluginFunctionalTest.kt`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह परीक्षण महत्वपूर्ण है क्योंकि यह वास्तविक प्रोजेक्ट में प्लगिन के निष्पादन का अनुकरण करता है। इसे होना चाहिए&amp;lt;strong&amp;gt;हवा-रोधी&amp;lt;/strong&amp;gt;, यानी उसे स्वयं फ़ाइल बनानी चाहिए`managed-jbake-context.yml`नियंत्रित सामग्री के साथ, परीक्षण की पुनरुत्पादन क्षमता और अलगाव सुनिश्चित करने के लिए।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// plugin/src/functionalTest/kotlin/com/cheroliv/site/baker/SiteBakerPluginFunctionalTest.kt
@Test
fun `config file contains good data`(){
    val configContent = configFile.readText(UTF_8)
    // Vérifications comme dans vos commentaires
    assertTrue(configContent.contains(&amp;quot;bake&amp;quot;))
    assertTrue(configContent.contains(&amp;quot;pushPage&amp;quot;))
    assertTrue(configContent.contains(&amp;quot;repository&amp;quot;))
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह कार्यात्मक परीक्षण सत्यापित करता है कि परीक्षण के अस्थायी निर्देशिका में कॉपी किया गया कॉन्फ़िगरेशन फ़ाइल अपेक्षित डेटा रखता है। यद्यपि यह परीक्षण सीधे YAML को Kotlin ऑब्जेक्ट में नहीं पार्स करता, यह फ़ाइल की उपस्थिति और उसकी सामग्री को मान्य करता है, जो प्लगइन द्वारा पार्सिंग के लिए एक आवश्यक प्रारंभिक चरण है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_5_पार्सिंग_फ़्लो_का_दृश्यीकरण&amp;quot;&amp;gt;5. पार्सिंग फ़्लो का दृश्यीकरण&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आरेख निम्नलिखित YAML कॉन्फ़िगरेशन के पार्सिंग के दौरान डेटा प्रवाह और इंटरैक्शन को दर्शाता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-815a0db24710a6a35c19b7f59edc954b.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;1534&amp;quot; height=&amp;quot;472&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;TDD दृष्टिकोण का पालन करते हुए, हमने Gradle प्लगिन के भीतर Kotlin ऑब्जेक्ट्स में YAML कॉन्फ़िगरेशन फ़ाइलों को पार्स करने के लिए जैक्सन लाइब्रेरी को सफलतापूर्वक इंटीग्रेट किया। इस विधि ने हमें करने की अनुमति दी :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;स्पष्ट रूप से मॉडलिंग&amp;lt;/strong&amp;gt;हमारी कॉन्फ़िगरेशन Kotlin डेटा क्लासेस के साथ।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;पार्सिंग लॉजिक को सत्यापित करें&amp;lt;/strong&amp;gt;लक्षित यूनिट परीक्षणों के साथ।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;समेकन सुनिश्चित करें&amp;lt;/strong&amp;gt;वास्तविक Gradle वातावरण में हर्मेटिक कार्यात्मक परीक्षणों के माध्यम से।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह ठोस आधार हमें हमारे प्लगइन को ऐसी सुविधाओं के साथ विस्तार करने के लिए भरोसा दिलाता है जो इस कॉन्फ़िगरेशन पर आधारित हैं, साथ ही कोड की बनाए रखने योग्यता और मजबूती को सुनिश्चित करते हुए। अब YAML पार्सिंग हमारे प्लगइन की एक विश्वसनीय और परीक्षण की गई सुविधा है।&amp;lt;code&amp;gt;site-baker&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>अनुच्छेद २ : TDD दृष्टिकोण के साथ एक Gradle प्लगइन विकसित करें</title>
            <link >https://cheroliv.com/blog/2025/0090_TDD_gradle_plugin_post.html</link>
            <pubDate>Wed, 24 Sep 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0090_TDD_gradle_plugin_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table of Contents&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परियोजना_प्रारम्भ&amp;quot;&amp;gt;परियोजना प्रारम्भ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_2_हमारा_पहला_tdd_चक्र_एक_कार्य_रिकॉर्ड_करें&amp;quot;&amp;gt;2. हमारा पहला TDD चक्र : एक कार्य रिकॉर्ड करें&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_2_1_पहला_परीक्षण_जो_परीक्षण_असफल_होता_है&amp;quot;&amp;gt;2.1. पहला परीक्षण (जो परीक्षण असफल होता है)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_2_2_अगला_कोड_परीक्षा_पास_करना&amp;quot;&amp;gt;2.2. अगला कोड (परीक्षा पास करना)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_3_दूसरा_चक्र_tdd_एक_डीएसएल_एक्सटेंशन_जोड़ें&amp;quot;&amp;gt;3. दूसरा चक्र TDD: एक डीएसएल एक्सटेंशन जोड़ें&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_3_1_पहला_परीक्षण&amp;quot;&amp;gt;3.1. पहला परीक्षण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_3_2_कोड_फिर&amp;quot;&amp;gt;3.2. कोड फिर&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_4_कार्यात्मक_परीक्षण_एकीकरण_को_सत्यापित_करें&amp;quot;&amp;gt;4. कार्यात्मक परीक्षण: एकीकरण को सत्यापित करें&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_4_1_एकीकरण_परीक्षण_एक_नियंत्रित_वातावरण_बनाएँ&amp;quot;&amp;gt;4.1. एकीकरण परीक्षण: एक नियंत्रित वातावरण बनाएँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_4_2_लॉजिक_को_अंतिम_रूप_दें&amp;quot;&amp;gt;4.2. लॉजिक को अंतिम रूप दें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस लेख में, हम जानेंगे कि Gradle प्लगिन के लिए एक मजबूत विकास आधार कैसे स्थापित करें, परीक्षण-निर्देशित विकास (TDD - Test-Driven Development) दृष्टिकोण का उपयोग करके। यह विधि सुनिश्चित करती है कि हमारा कोड मजबूत, रखरखाव योग्य और आवश्यकताओं को सटीक रूप से शुरू से ही पूरा करता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परियोजना_प्रारम्भ&amp;quot;&amp;gt;परियोजना प्रारम्भ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Gradle बहुत सहजता से एक नए प्लगइन के निर्माण को सुविधाजनक बनाता है, कमांड के माध्यम से।&amp;lt;code&amp;gt;gradle init&amp;lt;/code&amp;gt;. कोटलिन के साथ एक &amp;#39;Gradle Plugin&amp;#39; बनाने का चयन करके, हमें एक उपयोग के लिए तैयार प्रोजेक्ट संरचना मिलती है, जिसमें दो महत्वपूर्ण प्रकार के परीक्षण शामिल हैं:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;इकाई परीक्षण :&amp;lt;/strong&amp;gt; Situés dans &amp;lt;code&amp;gt;src/test&amp;lt;/code&amp;gt;, वे हमारे प्लगिन के अलग‑अलग घटकों को सत्यापित करने की अनुमति देते हैं, जैसे किसी कार्य की आंतरिक तर्क या किसी एक्सटेंशन की कॉन्फ़िगरेशन। वे तेज़ हैं और इन्हें ग्रैडल की पूर्ण निष्पादन की आवश्यकता नहीं है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;कार्यात्मक परीक्षण :&amp;lt;/strong&amp;gt;में स्थित`src/functionalTest`, वे उपयोग करते हैं`GradleRunner`पूरी Gradle बिल्ड चलाने के लिए एक अस्थायी परीक्षण प्रोजेक्ट में। यह हमें नियंत्रित वातावरण में प्लगिन के वास्तविक व्यवहार को सत्यापित करने की अनुमति देता है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_2_हमारा_पहला_tdd_चक्र_एक_कार्य_रिकॉर्ड_करें&amp;quot;&amp;gt;2. हमारा पहला TDD चक्र : एक कार्य रिकॉर्ड करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारी पहली आवश्यकता सरल है: प्लगइन को एक नामित कार्य पंजीकृत करना होगा`printSiteConfig`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_2_1_पहला_परीक्षण_जो_परीक्षण_असफल_होता_है&amp;quot;&amp;gt;2.1. पहला परीक्षण (जो परीक्षण असफल होता है)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;TDD के अनुसार, हम पहले एक परीक्षण लिखते हैं जो इस कार्य की मौजूदगी की जाँच करता है। में`SiteBakerPluginTest.kt`(हमारा यूनिट परीक्षण फ़ाइल), हम जोड़ते हैं:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;@Test
fun `plugin registers task`() {
    // Créer un projet de test en mémoire
    val project = ProjectBuilder.builder().build()
    project.plugins.apply(&amp;quot;com.cheroliv.site-baker&amp;quot;)

    // Vérifier que la tâche a bien été enregistrée
    assertNotNull(project.tasks.findByName(&amp;quot;printSiteConfig&amp;quot;))
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह परीक्षण विफल होता है, क्योंकि हमने अभी तक अपने प्लगइन में कोई कोड नहीं लिखा है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_2_2_अगला_कोड_परीक्षा_पास_करना&amp;quot;&amp;gt;2.2. अगला कोड (परीक्षा पास करना)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अब हम आवश्यक न्यूनतम कोड लिख रहे हैं में`SiteBakerPlugin.kt`ताकि परीक्षा पास हो:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;class SiteBakerPlugin: Plugin&amp;amp;lt;Project&amp;amp;gt; {
    override fun apply(project: Project) {
        // Enregistrer une tâche simple
        project.tasks.register(&amp;quot;printSiteConfig&amp;quot;) { task -&amp;amp;gt;
            // ... la logique de la tâche viendra plus tard
        }
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हम परीक्षणों को फिर से चला रहे हैं, और वे पास हो रहे हैं. हमारी पहली सुविधा मान्य है.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_3_दूसरा_चक्र_tdd_एक_डीएसएल_एक्सटेंशन_जोड़ें&amp;quot;&amp;gt;3. दूसरा चक्र TDD: एक डीएसएल एक्सटेंशन जोड़ें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अगली आवश्यकता उपयोगकर्ताओं को उनके DSL ब्लॉक के माध्यम से हमारे प्लग़िन को कॉन्फ़िगर करने की अनुमति देना है`build.gradle.kts`. हम एक ब्लॉक चाहते हैं`site { &amp;amp;#8230;&amp;amp;#8203; }`जहाँ आप एक कॉन्फ़िगरेशन पथ निर्दिष्ट कर सकते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_3_1_पहला_परीक्षण&amp;quot;&amp;gt;3.1. पहला परीक्षण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हम एक परीक्षण जोड़ रहे हैं ताकि यह सत्यापित किया जा सके कि एक्सटेंशन`site`यह ठीक से दर्ज की गई है और हम इसे मान दे सकते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;@Test
fun `plugin registers extension`() {
    val project = ProjectBuilder.builder().build()
    project.plugins.apply(&amp;quot;com.cheroliv.site-baker&amp;quot;)

    // Récupérer l&amp;#39;extension et lui affecter une valeur
    project.extensions
        .findByType(SiteExtension::class.java)!!
        .configPath
        .set(&amp;quot;config.yml&amp;quot;)

    // Vérifier que la valeur a bien été prise en compte
    assertEquals(
        &amp;quot;config.yml&amp;quot;,
        project.extensions.findByType(SiteExtension::class.java)?.configPath?.get()
    )
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह टेस्ट फेल हो जाता है क्योंकि न तो क्लास`SiteExtension`एक्सटेंशन का पंजीकरण भी मौजूद नहीं है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_3_2_कोड_फिर&amp;quot;&amp;gt;3.2. कोड फिर&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हम क्लास बनाते हैं`SiteBakerExtension.kt`और हम अपडेट करते हैं`SiteBakerPlugin.kt`:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// SiteBakerExtension.kt
open class SiteExtension @Inject constructor(objects: ObjectFactory) {
    val configPath: Property&amp;amp;lt;String&amp;amp;gt; = objects.property(String::class.java)
}

// SiteBakerPlugin.kt
class SiteBakerPlugin: Plugin&amp;amp;lt;Project&amp;amp;gt; {
    override fun apply(project: Project) {
        // Enregistrer l&amp;#39;extension
        val extension = project.extensions.create(&amp;quot;site&amp;quot;, SiteExtension::class.java)

        project.tasks.register(&amp;quot;printSiteConfig&amp;quot;) { task -&amp;amp;gt;
            task.doLast {
                // On utilisera l&amp;#39;extension plus tard
            }
        }
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;परीक्षण फिर से पास हो रहे हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_4_कार्यात्मक_परीक्षण_एकीकरण_को_सत्यापित_करें&amp;quot;&amp;gt;4. कार्यात्मक परीक्षण: एकीकरण को सत्यापित करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अब जब इकाइयाँ परीक्षण की गई हैं, हमें यह सुनिश्चित करने की आवश्यकता है कि सब कुछ एक वास्तविक बिल्ड में एक साथ काम करे। यह फ़ंक्शनल परीक्षण की भूमिका है`SiteBakerPluginFunctionalTest.kt`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_4_1_एकीकरण_परीक्षण_एक_नियंत्रित_वातावरण_बनाएँ&amp;quot;&amp;gt;4.1. एकीकरण परीक्षण: एक नियंत्रित वातावरण बनाएँ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह परीक्षण हमारा प्लगइन का उपयोग करके एक वास्तविक प्रोजेक्ट का अनुकरण करेगा। इसे विश्वसनीय होने के लिए, इसे&amp;lt;strong&amp;gt;वायुरोधी&amp;lt;/strong&amp;gt;, यानी इसे मौजूदा फ़ाइलों पर निर्भर नहीं रहना चाहिए। इसे स्वयं सभी आवश्यक शर्तें बनानी चाहिए जो इसके निष्पादन के लिए आवश्यक हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;टेस्ट इसलिए:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एक बनाना`build.gradle.kts`हमारा प्लगिन और इसका DSL का उपयोग करने वाला परीक्षण.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;कॉन्फ़िगरेशन फ़ाइल बनाएँ&amp;lt;/strong&amp;gt;(&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;(Note: The output preserves the exact characters, including spaces and the parenthesis, as there is no translatable text.)&amp;lt;code&amp;gt;managed-jbake-context.yml&amp;lt;/code&amp;gt;) जो प्लगिन को पढ़ना चाहिए। यह परीक्षण की मजबूती के लिए एक महत्वपूर्ण चरण है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कार्य को निष्पादित करें`printSiteConfig`के माध्यम से`GradleRunner`.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;निर्माण आउटपुट सही है, यह सुनिश्चित करें।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;प्रत्येक निष्पादन में इस कॉन्फ़िगरेशन फ़ाइल को कॉपी करके या बनाकर, हम सुनिश्चित करते हैं कि परीक्षण है।&amp;lt;strong&amp;gt;पुनरावृत्ति योग्य&amp;lt;/strong&amp;gt;और यह बाहरी स्थिति पर निर्भर नहीं करता है। यह हमारे परीक्षणों को फ़ाइल पढ़ने से संबंधित रिग्रेशन से सुरक्षित रखता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;@Test fun `can run task with DSL`() {
    // 1. Créer un build.gradle.kts de test
    buildFile.writeText(&amp;quot;&amp;quot;&amp;quot;
        plugins { id(&amp;quot;com.cheroliv.site-baker&amp;quot;) }
        site { configPath = &amp;quot;managed-jbake-context.yml&amp;quot; }
    &amp;quot;&amp;quot;&amp;quot;.trimIndent())

    // 2. Créer le fichier de configuration pour un test contrôlé
    val configFile = File(projectDir, &amp;quot;managed-jbake-context.yml&amp;quot;)
    configFile.writeText(&amp;quot;site: { title: &amp;#39;Mon Site de Test&amp;#39; }&amp;quot;) // Contenu YAML simple

    // 3. Exécuter la build
    val runner = GradleRunner.create()
    runner.withPluginClasspath()
    runner.withArguments(&amp;quot;printSiteConfig&amp;quot;)
    runner.withProjectDir(projectDir) // Spécifier le répertoire du projet de test
    val result = runner.build()

    // 4. Vérifier la sortie
    assertTrue(result.output.contains(&amp;quot;Site config path: managed-jbake-context.yml&amp;quot;))
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह परीक्षा तब तक असफल रहेगी जब तक कि कार्य`printSiteConfig`यह एक्सटेंशन का मान वास्तव में उपयोग नहीं करेगा।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_4_2_लॉजिक_को_अंतिम_रूप_दें&amp;quot;&amp;gt;4.2. लॉजिक को अंतिम रूप दें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हम टास्क को अद्यतन कर रहे हैं में`SiteBakerPlugin.kt`इसे कॉन्फ़िगर किया गया मान प्रदर्शित करने के लिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;project.tasks.register(&amp;quot;printSiteConfig&amp;quot;) { task -&amp;amp;gt;
    task.doLast {
        println(&amp;quot;Site config path: ${extension.configPath.get()}&amp;quot;)
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सभी परीक्षण, इकाई और कार्यात्मक, अब पास हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;TDD दृष्टिकोण का पालन करते हुए, हमने एक प्लगइन को चरणबद्ध और सुरक्षित तरीके से बनाया। प्रत्येक छोटी सुविधा को तुरंत एक परीक्षण द्वारा मान्य किया जाता है, तेज़ इकाई परीक्षणों से लेकर पूरी एकीकरण को मान्य करने वाले कार्यात्मक परीक्षणों तक।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपने परीक्षणों को कार्यात्मक बनाने में सावधानी बरतते हुए&amp;lt;strong&amp;gt;हर्मेटिक&amp;lt;/strong&amp;gt;— विशेषकर प्रोग्रामेटिक रूप से आवश्यक कॉन्फ़िगरेशन फ़ाइलों को बनाकर — हम एक अत्यंत मज़बूत सुरक्षा जाल बुन रहे हैं। यह सख़्ती हमें प्रभावी रूप से रिग्रेशन से बचाती है और हमें भविष्य में अधिक जटिल सुविधाएँ जोड़ने का भरोसा देता है, जैसे YAML कॉन्फ़िगरेशन फ़ाइल का पार्सिंग।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह मजबूत परीक्षण आधार प्लगइन के रखरखाव और भविष्य के विकास के लिए सबसे मूल्यवान संपत्ति है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>अनुच्छेद 1 : gradle init कमांड के साथ A से Z तक Gradle प्लगिन बनाएँ</title>
            <link >https://cheroliv.com/blog/2025/0089_creation_projet_plugin_gradle_post.html</link>
            <pubDate>Tue, 23 Sep 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0089_creation_projet_plugin_gradle_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_1_परियोजना_सहायक_शुरू_करें&amp;quot;&amp;gt;चरण 1: परियोजना सहायक शुरू करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;लक्षित दर्शक : शुरुआती से मध्यम स्तर के डेवलपर Gradle के साथ&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;एक नया Gradle प्लगइन प्रोजेक्ट शुरू करने की प्रक्रिया डरावनी लग सकती है। सौभाग्य से, Gradle एक शक्तिशाली इंटरैक्टिव सहायक प्रदान करता है, कार्य`init`, जो एक पूर्ण, स्वच्छ और उपयोग के लिए तैयार प्रोजेक्ट संरचना उत्पन्न करता है। यह गाइड आपको दिखाएगा कि इस टूल का उपयोग करके एक स्वस्थ प्लगइन आधार कैसे बनाया जाए, इसकी संरचना समझाएगा और आपको दिखाएगा कि पहले बिल्ड कार्य कैसे चलाएँ जाएँ।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_चरण_1_परियोजना_सहायक_शुरू_करें&amp;quot;&amp;gt;चरण 1: परियोजना सहायक शुरू करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;कमांड`gradle init`यह प्रारम्भ बिंदु है। यह एक कमांड-लाइन असिस्टेंट शुरू करता है जो आपको परियोजना को कॉन्फ़िगर करने के लिए प्रश्नों की एक श्रृंखला पूछता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;खाली फ़ोल्डर में अपना टर्मिनल खोलें और चलाएँ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;gradle init&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सहायक आपको मार्गदर्शन करेगा। यहाँ एक कोटलिन में लिखे गए Gradle प्लगिन के लिए किए जाने वाले विकल्प हैं :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;जनरेट करने के लिए परियोजना के प्रकार का चयन करें:&amp;lt;/strong&amp;gt;चुनें`Gradle plugin`.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;कार्यान्वयन भाषा चुनें:&amp;lt;/strong&amp;gt;चुनें`Kotlin`।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;बिल्ड स्क्रिप्ट DSL चुनें:&amp;lt;/strong&amp;gt;चुनिए`Kotlin`.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;परियोजना का नाम:&amp;lt;/strong&amp;gt;अपने प्रोजेक्ट के लिए एक नाम दर्ज करें (उदाहरण:`site-baker`).&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;**&amp;lt;mark&amp;gt;#&amp;lt;/mark&amp;gt; ग्रैडल एकीकरण&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;JBake को JBake Gradle प्लगिन का उपयोग करके या JBake CLI को सीधे कॉल करके Gradle बिल्ड में एकीकृत किया जा सकता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;----
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
}**### ग्रेडल इंटीग्रेशन
JBake को JBake Gradle प्लगिन का उपयोग करके या JBake CLI को सीधे बुलाकर Gradle बिल्ड में इंटीग्रेट किया जा सकता है:

----

tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) { mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;) classpath = configurations[&amp;quot;jbake&amp;quot;] args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;) } ```

अपने प्लगिन के लिए एक विशिष्ट पहचानकर्ता दें (उदाहरण के लिए:`com.cheroliv.site-baker`).

1.  **### gradle एकीकरण

JBake को JBake Gradle प्लगिन का उपयोग करके या JBake CLI को सीधे बुलाकर Gradle बिल्ड में एकीकृत किया जा सकता है:

```kotlin
----
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
}
----

प्लगिन वर्ग:**कार्यान्वयन कक्षा का नाम निर्दिष्ट करें (उदाहरण:`com.cheroliv.SiteBakerPlugin`).

एक बार पूरा हो जाने के बाद, Gradle एक पूर्ण फ़ाइल पदानुक्रम उत्पन्न करता है।

.प्रारंभीकरण प्रक्रिया का आरेख

[plantuml, init-gradle, svg]
----
@startuml
start
:Lancer `gradle init`;
:Choisir &amp;quot;Gradle plugin&amp;quot;;
:Choisir &amp;quot;### Gradle इंटीग्रेशन
JBake को Gradle बिल्ड्स में JBake Gradle प्लगइन का उपयोग करके या JBake CLI को सीधे बुलाकर एकीकृत किया जा सकता है:

```kotlin
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
}&amp;quot; (langage);
:Choisir &amp;quot;### Gradle इंटीग्रेशन
JBake को Gradle बिल्ड्स में JBake Gradle प्लगइन का उपयोग करके या JBake CLI को सीधे बुलाकर एकीकृत किया जा सकता है:

```kotlin
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
}&amp;quot; (DSL);
:Saisir nom, ID, et classe;
:Projet généré;
stop
@enduml
----

== चरण 2 : जनरेट की गई संरचना को समझना

असिस्टेंट एक मल्टी‑मॉड्यूल प्रोजेक्ट संरचना बनाता है, मूल प्रोजेक्ट को प्लगिन के स्रोत कोड से अलग करते हुए।

[source,text]
----
.
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── plugin/
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   └── kotlin/
│       │       └── com/cheroliv/SiteBakerPlugin.kt
│       ├── test/
│       │   └── kotlin/
│       │       └── com/cheroliv/SiteBakerPluginTest.kt
│       └── functionalTest/
│           └── kotlin/
│               └── com/cheroliv/SiteBakerPluginFunctionalTest.kt
└── settings.gradle.kts
----

=== मुख्य फ़ाइलें और फ़ोल्डर

*   `settings.gradle.kts`यह फ़ाइल रूट में बिल्ड में शामिल मॉड्यूल को परिभाषित करती है। यहाँ, यह उप-प्रोजेक्ट शामिल करता है।`plugin`.

[source,kotlin] ---- rootProject.name = &amp;quot;site-baker include(&amp;quot;plugin&amp;quot;) ----
----

----&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>लेख 0 : Gradle प्लगइन बनाने के लिए पर्यावरण स्थापित करना</title>
            <link >https://cheroliv.com/blog/2025/0088_environnement_plugin_gradle_post.html</link>
            <pubDate>Mon, 22 Sep 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0088_environnement_plugin_gradle_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_jdk_gradle_का_इंजन&amp;quot;&amp;gt;JDK : Gradle का इंजन&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_कौन_सा_संस्करण_चुनें&amp;quot;&amp;gt;कौन सा संस्करण चुनें ?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_sdkman_के_माध्यम_से_स्थापना_अनुशंसित&amp;quot;&amp;gt;SDKMAN! के माध्यम से स्थापना (अनुशंसित)&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel3&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_sdkman_स्थापित_करें&amp;quot;&amp;gt;SDKMAN! स्थापित करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_jdk_का_एक_संस्करण_स्थापित_करें&amp;quot;&amp;gt;JDK का एक संस्करण स्थापित करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_स्थापना_की_जाँच_करें&amp;quot;&amp;gt;स्थापना की जाँच करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_2_ide_intellij_idea&amp;quot;&amp;gt;2. IDE: IntelliJ IDEA&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_3_gradle_बिल्ड_टूल&amp;quot;&amp;gt;3. Gradle : बिल्ड टूल&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_sdkman_के_माध्यम_से_इंस्टॉलेशन&amp;quot;&amp;gt;SDKMAN! के माध्यम से इंस्टॉलेशन&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel3&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_gradle_इंस्टॉल_करें&amp;quot;&amp;gt;Gradle इंस्टॉल करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_स्थापना_की_जाँच_करें_2&amp;quot;&amp;gt;स्थापना की जाँच करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_4_jbake_स्थिर_साइट_जेनरेटर&amp;quot;&amp;gt;4. JBake : स्थिर साइट जेनरेटर&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_sdkman_के_माध्यम_से_स्थापना&amp;quot;&amp;gt;SDKMAN! के माध्यम से स्थापना&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel3&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_jbake_इंस्टॉल_करें&amp;quot;&amp;gt;JBake इंस्टॉल करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_इंस्टॉलेशन_की_जाँच_करें&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;इंस्टॉलेशन की जाँच करें&amp;lt;/strong&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_5_gradle_wrapper_सर्वोत्तम_अभ्यास&amp;quot;&amp;gt;5. Gradle Wrapper : सर्वोत्तम अभ्यास&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_6_docker_और_portainer_पुनउत्पादन_योग्य_बिल्ड_के_लिए_वैकल्पिक&amp;quot;&amp;gt;6. Docker और Portainer : पुन:उत्पादन योग्य बिल्ड के लिए (वैकल्पिक)&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_docker_इंजन_की_स्थापना&amp;quot;&amp;gt;Docker इंजन की स्थापना&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel3&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ऑफ़िशियल_स्क्रिप्ट_के_माध्यम_से_docker_स्थापित_करें&amp;quot;&amp;gt;ऑफ़िशियल स्क्रिप्ट के माध्यम से Docker स्थापित करें:&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_docker_को_sudo_के_बिना_प्रबंधित_करें_अनुशंसित&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Docker को &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt; के बिना प्रबंधित करें (अनुशंसित) :&amp;lt;/strong&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_portainer_gui_के_साथ_docker_प्रबंधित_करें&amp;quot;&amp;gt;Portainer (GUI) के साथ Docker प्रबंधित करें&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel3&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पोर्टेनियर_के_डेटा_के_लिए_एक_वॉल्यूम_बनाएँ&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;पोर्टेनियर के डेटा के लिए एक वॉल्यूम बनाएँ :&amp;lt;/strong&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_portainer_कंटेनर_लॉन्च_करें&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Portainer कंटेनर लॉन्च करें :&amp;lt;/strong&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;लक्ष्य दर्शक: ऐसे डेवलपर्स जो Gradle प्लगइन बनाने की शुरुआत करना चाहते हैं।&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;ग्रैडल प्लगइन्स को प्रभावी ढंग से विकसित करने के लिए, एक अच्छी तरह से कॉन्फ़िगर किया गया विकास पर्यावरण आवश्यक है। एक अच्छा सेटअप आपको समय बचाएगा, निराशा कम करेगा और आपके बिल्ड्स की संगति सुनिश्चित करेगा।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;यह गाइड चार आवश्यक स्तंभों पर केन्द्रित है :&amp;lt;/div&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Le &amp;lt;strong&amp;gt;JDK&amp;lt;/strong&amp;gt;(जावा डेवलपमेंट किट), क्योंकि Gradle और JBake JVM पर चलते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Un &amp;lt;strong&amp;gt;IDE&amp;lt;/strong&amp;gt;आधुनिक (IntelliJ IDEA) में कोटलिन और ग्रैडल के लिए अच्छा समर्थन है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Gradle&amp;lt;/strong&amp;gt;स्वयं, परियोजनाओं को प्रारंभ करने के लिए.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;JBake&amp;lt;/strong&amp;gt;, हमारी स्थिर साइट का इंजन।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;images/gradle-env.svg&amp;quot; alt=&amp;quot;gradle env&amp;quot; width=&amp;quot;1637&amp;quot; height=&amp;quot;5696&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Figure 1. विकास पर्यावरण के घटक&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_jdk_gradle_का_इंजन&amp;quot;&amp;gt;JDK : Gradle का इंजन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Gradle एक अनुप्रयोग है जो Java Virtual Machine (JVM) पर चलता है। इसलिए, JDK की स्थापना एक अनिवार्य शर्त है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_कौन_सा_संस्करण_चुनें&amp;quot;&amp;gt;कौन सा संस्करण चुनें ?&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अनुशंसा की जाती है कि जावा के LTS (Long-Term Support) संस्करण का उपयोग किया जाए। वर्तमान में,&amp;lt;strong&amp;gt;JDK 17&amp;lt;/strong&amp;gt; ou &amp;lt;strong&amp;gt;JDK 21&amp;lt;/strong&amp;gt;वे उत्कृष्ट विकल्प हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_sdkman_के_माध्यम_से_स्थापना_अनुशंसित&amp;quot;&amp;gt;SDKMAN! के माध्यम से स्थापना (अनुशंसित)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;SDKMAN! एक शानदार टूल है जो कई SDKs के संस्करणों को प्रबंधित करने के लिए उपयोग किया जाता है, जिसमें Java और Gradle शामिल हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_sdkman_स्थापित_करें&amp;quot;&amp;gt;SDKMAN! स्थापित करें&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;curl -s &amp;quot;https://get.sdkman.io&amp;quot; | bash source &amp;quot;$HOME/.sdkman/bin/sdkman-init.sh&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_jdk_का_एक_संस्करण_स्थापित_करें&amp;quot;&amp;gt;JDK का एक संस्करण स्थापित करें&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Pour lister les versions de Java disponibles sdk list java

# Pour installer Java 17 (par exemple, la distribution Temurin)
sdk install java 17.0.8-tem&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_स्थापना_की_जाँच_करें&amp;quot;&amp;gt;स्थापना की जाँच करें&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;java -version&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आपको स्थापित की गई संस्करण दिखना चाहिए।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_2_ide_intellij_idea&amp;quot;&amp;gt;2. IDE: IntelliJ IDEA&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;ग्रैडल प्लगइन विकास के लिए कोटलिन DSL के साथ,&amp;lt;strong&amp;gt;IntelliJ IDEA&amp;lt;/strong&amp;gt;यह पसंद का उपकरण है। इसका Gradle और Kotlin के साथ एकीकरण अद्वितीय है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;सामुदायिक संस्करण :&amp;lt;/strong&amp;gt;नि:शुल्क और शुरू करने के लिए पर्याप्त से अधिक.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;अल्टीमेट संस्करण :&amp;lt;/strong&amp;gt;भुगतान आधारित, यह वेब विकास और डेटाबेस के लिए उन्नत सुविधाएँ प्रदान करती है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;JetBrains साइट से अपने लिए उपयुक्त संस्करण डाउनलोड करें : &amp;lt;a href=&amp;quot;https://www.jetbrains.com/idea/download/&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://www.jetbrains.com/idea/download/&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;IDE स्वचालित रूप से आपकी फ़ाइलों का पता लगाएगा`build.gradle.kts` et &amp;lt;code&amp;gt;settings.gradle.kts&amp;lt;/code&amp;gt;, आपके लिए शक्तिशाली ऑटोकम्पलीशन, कोड नेविगेशन और एकीकृत डिबगिंग टूल प्रदान करता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_3_gradle_बिल्ड_टूल&amp;quot;&amp;gt;3. Gradle : बिल्ड टूल&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हालांकि प्रत्येक परियोजना अपने स्वयं के Gradle संस्करण का उपयोग Gradle Wrapper के माध्यम से करेगी, लेकिन नए परियोजनाओं को आरंभ करने जैसे कार्यों के लिए एक वैश्विक Gradle स्थापना रखना उपयोगी है (&amp;lt;code&amp;gt;gradle init&amp;lt;/code&amp;gt;).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_sdkman_के_माध्यम_से_इंस्टॉलेशन&amp;quot;&amp;gt;SDKMAN! के माध्यम से इंस्टॉलेशन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;JDK की तरह ही, SDKMAN! Gradle की स्थापना को सरल बनाता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_gradle_इंस्टॉल_करें&amp;quot;&amp;gt;Gradle इंस्टॉल करें&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;sdk install gradle&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_स्थापना_की_जाँच_करें_2&amp;quot;&amp;gt;स्थापना की जाँच करें&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;gradle -v&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह कमांड Gradle, Kotlin, Groovy और JDK के उपयोग किए गए संस्करण दिखाएगी।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_4_jbake_स्थिर_साइट_जेनरेटर&amp;quot;&amp;gt;4. JBake : स्थिर साइट जेनरेटर&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;JBake वह उपकरण है जिसका हम अपने स्रोत फ़ाइलों (जैसे यह) को स्थिर वेबसाइट में परिवर्तित करने के लिए उपयोग करेंगे। स्थानीय इंस्टॉलेशन होना बदलावों का पूर्वावलोकन करने में उपयोगी होता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_sdkman_के_माध्यम_से_स्थापना&amp;quot;&amp;gt;SDKMAN! के माध्यम से स्थापना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अन्य उपकरणों की तरह, SDKMAN! सबसे सरल विधि है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_jbake_इंस्टॉल_करें&amp;quot;&amp;gt;JBake इंस्टॉल करें&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;sdk install jbake&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_इंस्टॉलेशन_की_जाँच_करें&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;इंस्टॉलेशन की जाँच करें&amp;lt;/strong&amp;gt;&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;jbake -v&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह कमांड JBake संस्करण और उपयोग किए जा रहे Java वातावरण की जानकारी प्रदर्शित करेगा।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_5_gradle_wrapper_सर्वोत्तम_अभ्यास&amp;quot;&amp;gt;5. Gradle Wrapper : सर्वोत्तम अभ्यास&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक बार जब आपका प्रोजेक्ट बनाया जाता है (जिसे हम अगले लेख में देखेंगे), आपको वैश्विक कमांड का उपयोग नहीं करना चाहिए।&amp;lt;code&amp;gt;gradle&amp;lt;/code&amp;gt;. इसके बजाय, आप इसका उपयोग करेंगे&amp;lt;strong&amp;gt;ग्रैडल रैपर&amp;lt;/strong&amp;gt;(&amp;lt;code&amp;gt;./gradlew&amp;lt;/code&amp;gt;), un script inclus dans votre projet.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;क्यों ?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;पुनरावृत्ति :&amp;lt;/strong&amp;gt;Wrapper हर व्यक्ति जो प्रोजेक्ट पर काम कर रहा/रही है (आपके CI/CD सर्वर सहित) सटीक रूप से उपयोग करता है la&amp;lt;strong&amp;gt;Gradle का समान संस्करण&amp;lt;/strong&amp;gt;, इस प्रकार विभिन्न पर्यावरणों के कारण होने वाली बिल्ड की त्रुटियों को समाप्त करते हुए।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;सरलता:&amp;lt;/strong&amp;gt;परियोजना में योगदान देने के लिए Gradle को मैन्युअली इंस्टॉल करने की आवश्यकता नहीं है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इसे बस रिपॉजिटरी क्लोन करके चलाएँ`./gradlew`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक सामान्य आदेश इस प्रकार दिखेगा :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Ne pas faire : gradle build
# À faire :
./gradlew build&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_6_docker_और_portainer_पुनउत्पादन_योग्य_बिल्ड_के_लिए_वैकल्पिक&amp;quot;&amp;gt;6. Docker और Portainer : पुन:उत्पादन योग्य बिल्ड के लिए (वैकल्पिक)&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यद्यपि प्लगिन लिखने के लिए सख्त रूप से आवश्यक नहीं हैं, Docker और Portainer आधुनिक DevOps उपकरण हैं जो पुनरुत्पादन योग्य बिल्ड्स बनाने और आपके वातावरण को प्रबंधित करने में अत्यधिक सहायक हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_docker_इंजन_की_स्थापना&amp;quot;&amp;gt;Docker इंजन की स्थापना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Docker आपको अपने एप्लिकेशन और उसकी निर्भरताओं को एक कंटेनर में पैकेज करने की अनुमति देता है.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_ऑफ़िशियल_स्क्रिप्ट_के_माध्यम_से_docker_स्थापित_करें&amp;quot;&amp;gt;ऑफ़िशियल स्क्रिप्ट के माध्यम से Docker स्थापित करें:&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_docker_को_sudo_के_बिना_प्रबंधित_करें_अनुशंसित&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Docker को &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt; के बिना प्रबंधित करें (अनुशंसित) :&amp;lt;/strong&amp;gt;&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपने उपयोगकर्ता को समूह में जोड़ें`docker`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;sudo usod -aG docker $USER&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock important&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-important&amp;quot; title=&amp;quot;Important&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;

&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;docker run hello-world&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_portainer_gui_के_साथ_docker_प्रबंधित_करें&amp;quot;&amp;gt;Portainer (GUI) के साथ Docker प्रबंधित करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Portainer एक हल्का वेब इंटरफ़ेस है जो आपके Docker कंटेनरों को प्रबंधित करने के लिए उपयोग किया जाता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_पोर्टेनियर_के_डेटा_के_लिए_एक_वॉल्यूम_बनाएँ&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;पोर्टेनियर के डेटा के लिए एक वॉल्यूम बनाएँ :&amp;lt;/strong&amp;gt;&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;docker volume create portainer_data&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_portainer_कंटेनर_लॉन्च_करें&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Portainer कंटेनर लॉन्च करें :&amp;lt;/strong&amp;gt;&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आप अब Portainer इंटरफ़ेस पर पहुँच सकते हैं`https://localhost:9443`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आपका वातावरण अब तैयार है ! आपके पास JDK है, सबसे उपयुक्त IDE, Gradle और JBake। Docker के जुड़ने से, आप भी कंटेनराइज़्ड और पुन: प्रस्तुत करने योग्य बिल्ड्स बनाने के लिए तैयार हैं। यह मजबूत आधार आपको आवश्यक पर ध्यान केंद्रित करने की अनुमति देगा : शक्तिशाली और उपयोगी प्लगइन्स का विकास।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आगामी लेख में, हम कमांड का उपयोग करेंगे।`gradle init`हमारे पहले प्लगइन परियोजना की संरचना उत्पन्न करने के लिए.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>CI/CD Python – भाग 3 : Poetry, Docker और उन्नत प्रकाशन के साथ आगे बढ़ें</title>
            <link >https://cheroliv.com/blog/2025/0087_pypi_cicd_part_3_post.html</link>
            <pubDate>Sat, 19 Jul 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0087_pypi_cicd_part_3_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table of Contents&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_poetry_के_साथ_एकीकरण&amp;quot;&amp;gt;Poetry के साथ एकीकरण&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_poetry_की_स्थापना&amp;quot;&amp;gt;Poetry की स्थापना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_प्रोजेक्ट_का_प्रारम्भ&amp;quot;&amp;gt;प्रोजेक्ट का प्रारम्भ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निर्भरताओं_को_जोड़ना_और_इंस्टॉल_करना&amp;quot;&amp;gt;निर्भरताओं को जोड़ना और इंस्टॉल करना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_poetry_के_साथ_प्रकाशन&amp;quot;&amp;gt;Poetry के साथ प्रकाशन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_gradle_integration&amp;quot;&amp;gt;&amp;lt;mark&amp;gt;#&amp;lt;/mark&amp;gt; Gradle Integration&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस श्रृंखला के पहले दो भागों में, हमने : - एक Python एप्लिकेशन के लिए GitHub Actions और PyPI के साथ एक कार्यात्मक CI/CD पाइपलाइन स्थापित किया गया। - इस पाइपलाइन को मल्टी-वर्ज़न टेस्ट के साथ औद्योगिक बनाया गया, Test PyPI के माध्यम से प्रगतिशील प्रकाशन के साथ, और गुणवत्ता और सुरक्षा उपकरणों के साथ।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस तीसरे भाग में, हम जा रहे हैं&amp;lt;strong&amp;gt;PyPI पर सरल प्रकाशन से आगे&amp;lt;/strong&amp;gt;एक पूर्ण, मज़बूत और पेशेवर CI/CD पाइपलाइन बनाने के लिए : - &amp;lt;strong&amp;gt;कविता&amp;lt;/strong&amp;gt;आधुनिक पैकेजिंग के लिए और निर्भरताओं का अनुकूलित प्रबंधन. - &amp;lt;strong&amp;gt;Docker&amp;lt;/strong&amp;gt;पुनरुत्पादन योग्य और बहु‑प्लेटफ़ॉर्म बिल्ड़ बनाने के लिए। - &amp;lt;strong&amp;gt;शर्ती प्रकाशन&amp;lt;/strong&amp;gt;रिलीज़ उम्मीदवार जैसे परिदृश्यों को प्रबंधित करने के लिए - &amp;lt;strong&amp;gt;�ऑटोमेशन टूल्स&amp;lt;/strong&amp;gt;(Renovate, Dependabot) पाइपलाइन को बिना किसी परिश्रम के अद्यतन रखने के लिए&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_poetry_के_साथ_एकीकरण&amp;quot;&amp;gt;Poetry के साथ एकीकरण&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Poetry पैकेजिंग के पुराने उपकरण (setup.py, requirements.txt) को बदल देता है, निर्भरताओं और बिल्ड के प्रबंधन को केंद्रीकृत करके`pyproject.toml`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_poetry_की_स्थापना&amp;quot;&amp;gt;Poetry की स्थापना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;shell&amp;quot;&amp;gt;# Installer Poetry
curl -sSL https://install.python-poetry.org | python3 -
# Vérifier la version
poetry --version&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_प्रोजेक्ट_का_प्रारम्भ&amp;quot;&amp;gt;प्रोजेक्ट का प्रारम्भ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;shell&amp;quot;&amp;gt;# Initialiser un nouveau projet avec Poetry
poetry init
# Suivre l&amp;#39;assistant pour renseigner : nom, version, description, licence, dépendances.&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह एक फ़ाइल बनाता है`pyproject.toml`:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;toml&amp;quot;&amp;gt;[tool.poetry]
name = &amp;quot;playlist-downloader&amp;quot;
version = &amp;quot;0.1.0&amp;quot;
description = &amp;quot;CLI tool for managing YouTube playlists&amp;quot;
authors = [&amp;quot;Christophe Hérolivier &amp;amp;lt;cheroliv@example.com&amp;amp;gt;&amp;quot;]

[tool.poetry.dependencies]
python = &amp;quot;&amp;amp;gt;=3.8&amp;quot;
typer = &amp;quot;^0.9.0&amp;quot;
yt-dlp = &amp;quot;^2023.7.6&amp;quot;
google-api-python-client = &amp;quot;^2.0.0&amp;quot;
google-auth-oauthlib = &amp;quot;^1.0.0&amp;quot;

[tool.poetry.group.dev.dependencies]
pytest = &amp;quot;^7.0&amp;quot;
mypy = &amp;quot;^1.0&amp;quot;
bandit = &amp;quot;^1.7&amp;quot;
safety = &amp;quot;^2.3&amp;quot;
black = &amp;quot;^23.0&amp;quot;
ruff = &amp;quot;^0.1&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_निर्भरताओं_को_जोड़ना_और_इंस्टॉल_करना&amp;quot;&amp;gt;निर्भरताओं को जोड़ना और इंस्टॉल करना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;shell&amp;quot;&amp;gt;poetry add typer yt-dlp google-api-python-client google-auth-oauthlib
poetry add --group dev pytest mypy black bandit safety ruff&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_poetry_के_साथ_प्रकाशन&amp;quot;&amp;gt;Poetry के साथ प्रकाशन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Poetry नैटिव रूप से प्रकाशन प्रबंधित करता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;shell&amp;quot;&amp;gt;# Publication sur Test PyPI
poetry publish --build --repository test-pypi

# Publication sur PyPI
poetry publish --build&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह कमांड स्वचालित रूप से उपलब्ध जानकारी का उपयोग करती है`pyproject.toml`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_gradle_integration&amp;quot;&amp;gt;&amp;lt;mark&amp;gt;#&amp;lt;/mark&amp;gt; Gradle Integration&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;JBake can be integrated into Gradle builds using the JBake Gradle plugin or by calling the JBake CLI directly:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;----
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
}

विकास, CI/CD और उत्पादन में समान निष्पादन सुनिश्चित करने के लिए, Docker Poetry के साथ पूरी तरह से एकीकृत होता है।

=== Dockerfile का उदाहरण

[source,dockerfile]
----
FROM python:3.11-slim

WORKDIR /app
COPY pyproject.toml poetry.lock ./
RUN pip install poetry
RUN poetry install --no-root --only main

COPY . .

CMD [&amp;quot;poetry&amp;quot;, &amp;quot;run&amp;quot;, &amp;quot;python&amp;quot;, &amp;quot;cli.py&amp;quot;]
----

यह सुनिश्चित करता है: - एक जमा हुआ Python वातावरण. - लॉक की गई निर्भरताएँ के माध्यम से`poetry.lock`. Docker को सपोर्ट करने वाले किसी भी सिस्टम पर चलने वाली एक इमेज

=== GitHub Actions में एकीकरण

[source,yaml]
----
name: Docker Build

on:
  push:
    branches: [main]

jobs:
  build-docker:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build Docker image
        run: docker build -t ghcr.io/${{ github.repository }}:latest .
      - name: Push Docker image
        run: docker push ghcr.io/${{ github.repository }}:latest
----

== शर्ती प्रकाशन

एक पेशेवर पाइपलाइन में, केवल कुछ मामलों में प्रकाशित करने में सक्षम होना चाहिए : - रिलीज़ उम्मीदवार Test PyPI की ओर स्थिर संस्करण PyPI की ओर। केवल के लिए Docker बिल्ड्स ट्रिगर किए गए`main`.

[source,yaml]
----
- name: Publish to Test PyPI
  if: contains(github.ref, &amp;#39;-rc&amp;#39;)
  run: poetry publish --build --repository test-pypi

- name: Publish to PyPI
  if: startsWith(github.ref, &amp;#39;refs/tags/v&amp;#39;)
  run: poetry publish --build
----

यह दृष्टिकोण आकस्मिक प्रकाशनों को रोकता है।

== Renovate और Dependabot के साथ निर्भरताओं का स्वचालन

अपनी निर्भरताओं को अप्रचलित होने से बचाने के लिए, स्वचालित अपडेट टूल्स को एकीकृत करें।

=== Dependabot

[source,yaml]
----
version: 2
updates:
  - package-ecosystem: &amp;quot;pip&amp;quot;
    directory: &amp;quot;/&amp;quot;
    schedule:
      interval: &amp;quot;weekly&amp;quot;
  - package-ecosystem: &amp;quot;github-actions&amp;quot;
    directory: &amp;quot;/&amp;quot;
    schedule:
      interval: &amp;quot;weekly&amp;quot;
----

Dependabot हर हफ़्ते Python और GitHub Actions की निर्भरताओं को अपडेट करने के लिए PR खोलता है।

=== सुधारना

[source,json]
----
{
  &amp;quot;extends&amp;quot;: [&amp;quot;config:base&amp;quot;],
  &amp;quot;packageRules&amp;quot;: [
    {
      &amp;quot;matchManagers&amp;quot;: [&amp;quot;pip&amp;quot;],
      &amp;quot;groupName&amp;quot;: &amp;quot;python-dependencies&amp;quot;,
      &amp;quot;schedule&amp;quot;: [&amp;quot;before 6am on monday&amp;quot;]
    }
  ]
}
----

Renovate अधिक सूक्ष्म नियंत्रण की अनुमति देता है: निर्भरता समूहन, योजना, और उन्नत नियम।

== आरेख PlantUML

=== उपयोग मामला – उन्नत CI/CD

[plantuml, usecase-cicd, svg]
----
@startuml
actor Developer
actor GitHub as &amp;quot;GitHub Actions&amp;quot;
actor PyPI
actor DockerRegistry as &amp;quot;डॉकर रजिस्ट्री&amp;quot;
actor Automation as &amp;quot;नवीनीकरण/Dependabot&amp;quot;

Developer --&amp;amp;gt; (Push code)
(Trigger CI) --&amp;amp;gt; GitHub
GitHub --&amp;amp;gt; (Run Tests &amp;amp;amp; Lint)
GitHub --&amp;amp;gt; (Build Docker Image)
GitHub --&amp;amp;gt; DockerRegistry
GitHub --&amp;amp;gt; (Publish to Test PyPI)
GitHub --&amp;amp;gt; (Promote to PyPI)
Automation --&amp;amp;gt; (Update Dependencies)
@enduml
----

=== अनुक्रम – शर्ती प्रकाशन

[plantuml, sequence-cicd, svg]
----
@startuml
!theme vibrant
left to right direction
Developer -&amp;amp;gt; GitHub: Push tag v1.2.3-rc
GitHub -&amp;amp;gt; CI: Run tests
CI -&amp;amp;gt; CD: Check release type
CD -&amp;amp;gt; Test PyPI: Publish RC
Developer -&amp;amp;gt; GitHub: Push tag v1.2.3
GitHub -&amp;amp;gt; CD: Publish to PyPI
CD -&amp;amp;gt; Docker Registry: Push Docker image
@enduml
----

=== राज्य – CI/CD पाइपलाइन

[plantuml, states-cicd, svg]
----
@startuml
[*] --&amp;amp;gt; Idle
Idle --&amp;amp;gt; CI_Running : push
CI_Running --&amp;amp;gt; CI_Success : tests ok
CI_Running --&amp;amp;gt; CI_Failed : tests fail
CI_Success --&amp;amp;gt; CD_Running : tag detected
CD_Running --&amp;amp;gt; CD_Success : publish ok
CD_Running --&amp;amp;gt; CD_Failed : error
CD_Success --&amp;amp;gt; [*]
@enduml
----

=== डिप्लॉयमेंट – आर्किटेक्चर CI/CD

[plantuml, deployment-cicd, svg]
----
@startuml
node &amp;quot;डेवलपर मशीन&amp;quot; {
  component &amp;quot;गिट क्लाइंट&amp;quot;
}

node &amp;quot;गिटहब एक्शंस&amp;quot; {
  component &amp;quot;सीआई वर्कफ़्लो&amp;quot;
  component &amp;quot;CD वर्कफ़्लो&amp;quot;
}

node &amp;quot;पैकेज रिपॉजिटरीज़&amp;quot; {
  artifact &amp;quot;परीक्षण PyPI&amp;quot;
  artifact &amp;quot;PyPI&amp;quot;
  artifact &amp;quot;डॉकर रजिस्ट्री&amp;quot;
}

&amp;quot;डेवलपर मशीन&amp;quot; --&amp;amp;gt; &amp;quot;गिटहब एक्शंस&amp;quot;
&amp;quot;गिटहब एक्शंस&amp;quot; --&amp;amp;gt; &amp;quot;परीक्षण PyPI&amp;quot;
&amp;quot;गिटहब एक्शंस&amp;quot; --&amp;amp;gt; &amp;quot;PyPI&amp;quot;
&amp;quot;गिटहब एक्शंस&amp;quot; --&amp;amp;gt; &amp;quot;डॉकर रजिस्ट्री&amp;quot;
@enduml
----

== निष्कर्ष

इस तीसरे भाग में, हमने देखा कि : - पायथन पैकेजिंग को आधुनिक बनाएं Poetry के साथ - डॉक़र के माध्यम से पुनरावृत्तीय बिल्ड्स सुनिश्चित करें। - एक शर्ती प्रकाशन स्थापित करें। निर्भरताओं के अपडेट को स्वचालित करें।

अब आपके पास एक CI/CD पाइपलाइन**पूर्ण, औद्योगिकीकृत और सुरक्षित**, आपके प्रोजेक्ट्स के साथ विकसित होने के लिए तैयार।
----&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>भाग 2 : औद्योगिक बनाना और सुरक्षित करना एक उन्नत Python CI/CD पाइपलाइन</title>
            <link >https://cheroliv.com/blog/2025/0086_pypi_cicd_part_2_post.html</link>
            <pubDate>Fri, 18 Jul 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0086_pypi_cicd_part_2_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_cicd_पाइपलाइन_की_वास्तुकला&amp;quot;&amp;gt;CI/CD पाइपलाइन की वास्तुकला&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_प्रोजेक्ट_संरचना&amp;quot;&amp;gt;प्रोजेक्ट संरचना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pyproject_toml_के_साथ_पैकेज_कॉन्फ़िगरेशन&amp;quot;&amp;gt;pyproject.toml के साथ पैकेज कॉन्फ़िगरेशन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_cicd_वर्कफ़्लो_परीक्षण_और_गुणवत्ता&amp;quot;&amp;gt;CI/CD वर्कफ़्लो - परीक्षण और गुणवत्ता&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_रिलीज़_और_डिप्लॉयमेंट_वर्कफ़्लो&amp;quot;&amp;gt;रिलीज़ और डिप्लॉयमेंट वर्कफ़्लो&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_आर्किटेक्चर_डायग्राम&amp;quot;&amp;gt;आर्किटेक्चर डायग्राम&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सीक्वेंस_आरेख_रिलीज़_प्रक्रिया&amp;quot;&amp;gt;सीक्वेंस आरेख - रिलीज़ प्रक्रिया&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_स्थिति_आरेख_पैकेज_जीवन_चक्र&amp;quot;&amp;gt;स्थिति आरेख - पैकेज जीवन चक्र&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_डिप्लॉयमेंट_आरेख_cicd_इन्फ्रास्ट्रक्चर&amp;quot;&amp;gt;डिप्लॉयमेंट आरेख - CI/CD इन्फ्रास्ट्रक्चर&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पाइपलाइन_की_वस्तुएँ_और_मॉडल&amp;quot;&amp;gt;पाइपलाइन की वस्तुएँ और मॉडल&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_क्लास_आरेख_cicd_मॉडल&amp;quot;&amp;gt;क्लास आरेख - CI/CD मॉडल&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सिक्रेट्स_की_कॉन्फ़िगरेशन&amp;quot;&amp;gt;सिक्रेट्स की कॉन्फ़िगरेशन&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_github_actions_के_रहस्य&amp;quot;&amp;gt;GitHub Actions के रहस्य&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pypi_टोकन_जनरेशन&amp;quot;&amp;gt;PyPI टोकन जनरेशन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_स्थानीय_विकास_स्क्रिप्ट&amp;quot;&amp;gt;स्थानीय विकास स्क्रिप्ट&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_makefile&amp;quot;&amp;gt;Makefile&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_स्क्रिप्ट_संस्करण&amp;quot;&amp;gt;स्क्रिप्ट संस्करण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अच्छी_प्रथाएँ_और_सिफारिशें&amp;quot;&amp;gt;अच्छी प्रथाएँ और सिफारिशें&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समानार्थिक_संस्करण&amp;quot;&amp;gt;समानार्थिक संस्करण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ब्रांचिंग_रणनीति&amp;quot;&amp;gt;ब्रांचिंग रणनीति&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_टेस्ट_और_कवरेज&amp;quot;&amp;gt;टेस्ट और कवरेज&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सुरक्षा&amp;quot;&amp;gt;सुरक्षा&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_मॉनिटरिंग_और_ऑब्ज़र्वेबिलिटी&amp;quot;&amp;gt;मॉनिटरिंग और ऑब्ज़र्वेबिलिटी&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पाइपलाइन_मेट्रिक्स&amp;quot;&amp;gt;पाइपलाइन मेट्रिक्स&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सूचनाएँ&amp;quot;&amp;gt;सूचनाएँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अतिरिक्त_संसाधन&amp;quot;&amp;gt;अतिरिक्त संसाधन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;उद्देश्य : एक साधारण पाइपलाइन को एक मजबूत औद्योगिक पाइपलाइन में बदलें, आधुनिक पैकेजिंग और सॉफ़्टवेयर इंजीनियरिंग मानकों का पालन करते हुए।&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;इस श्रृंखला के पहले भाग में, हमने एक सरल लेकिन प्रभावी CI/CD पाइपलाइन बनाई जो Python पैकेज के परीक्षण और PyPI पर प्रकाशन को स्वचालित करती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अब इस पाइपलाइन को पेशेवर बनाने का समय है। इस दूसरे भाग में, हम करेंगे :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आधुनिक pyproject.toml मानक की ओर प्रवास करें,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;गुणवत्ता और सुरक्षा उपकरण जोड़ें (Black, Mypy, Bandit, Safety)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;बहु‑संस्करण परीक्षण सेट करें,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Test PyPI के माध्यम से क्रमिक तैनाती एकीकृत करें,&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;संस्करण को स्वचालित करें और पाइपलाइन निगरानी में सुधार करें।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक कार्यात्मक पाइपलाइन से एक पेशेवर CI/CD बुनियादी ढांचे में संक्रमण के लिए खुद को तैयार करें।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक पाइथन एप्लिकेशन को PyPI पर तैनात करने के लिए एक मजबूत CI/CD पाइपलाइन की आवश्यकता होती है जो टेस्ट, बिल्ड और पैकेज प्रकाशन को स्वचालित करती है। इस लेख में GitHub Actions का उपयोग करके एक CLI Python एप्लिकेशन के लिए एक पूर्ण पाइपलाइन सेट अप करने की प्रक्रिया का विस्तृत विवरण दिया गया है, आधुनिक Python इकोसिस्टम की सर्वोत्तम प्रथाओं पर आधारित।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_cicd_पाइपलाइन_की_वास्तुकला&amp;quot;&amp;gt;CI/CD पाइपलाइन की वास्तुकला&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;वह पाइपलाइन जिसे हम निर्माण करने जा रहे हैं, कई चरणों की दृष्टिकोण का पालन करती है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 18) ]

@startuml




...
... ( skipping 138 lines )
...
skinparam UseCaseStereoType {
  FontColor black
  FontName Verdana
}
title पाइपलाइन CI/CD Python PyPI की ओर
skinparam backgroundColor #f8f9fa
skinparam componentStyle rectangle

rectangle &amp;quot;डेवलपर&amp;quot; as dev
rectangle &amp;quot;गिटहब रिपॉजिटरी&amp;quot; as repo {
  rectangle &amp;quot;.github/कार्यप्रवाह/&amp;quot; as workflows
  rectangle &amp;quot;टेस्ट्स/&amp;quot; as tests
  rectangle &amp;quot;setup.py / pyproject.toml&amp;quot; as setup
  rectangle &amp;quot;requirements.txt&amp;quot; as req
}

rectangle &amp;quot;गिटहब एक्शंस&amp;quot; as actions {
  rectangle &amp;quot;टेस्ट रनर&amp;quot; as test_runner
  rectangle &amp;quot;### Gradle एकीकरण
JBake को JBake Gradle प्लगइन का उपयोग करके या JBake CLI को सीधे बुलाकर Gradle बिल्ड में एकीकृत किया जा सकता है:
^^^^^
 Syntax Error? (Assumed diagram type: activity)

@startuml
!theme plain
title पाइपलाइन CI/CD Python PyPI की ओर
skinparam backgroundColor #f8f9fa
skinparam componentStyle rectangle

rectangle &amp;quot;डेवलपर&amp;quot; as dev
rectangle &amp;quot;गिटहब रिपॉजिटरी&amp;quot; as repo {
  rectangle &amp;quot;.github/कार्यप्रवाह/&amp;quot; as workflows
  rectangle &amp;quot;टेस्ट्स/&amp;quot; as tests
  rectangle &amp;quot;setup.py / pyproject.toml&amp;quot; as setup
  rectangle &amp;quot;requirements.txt&amp;quot; as req
}

rectangle &amp;quot;गिटहब एक्शंस&amp;quot; as actions {
  rectangle &amp;quot;टेस्ट रनर&amp;quot; as test_runner
  rectangle &amp;quot;### Gradle एकीकरण
JBake को JBake Gradle प्लगइन का उपयोग करके या JBake CLI को सीधे बुलाकर Gradle बिल्ड में एकीकृत किया जा सकता है:

```kotlin
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
}&amp;quot; as build
  rectangle &amp;quot;सुरक्षा स्कैन&amp;quot; as security
  rectangle &amp;quot;गुणवत्ता जाँच&amp;quot; as quality
}

rectangle &amp;quot;PyPI&amp;quot; as pypi {
  rectangle &amp;quot;टेस्ट PyPI&amp;quot; as test_pypi
  rectangle &amp;quot;उत्पादन PyPI&amp;quot; as prod_pypi
}

rectangle &amp;quot;उपयोगकर्ता&amp;quot; as users

dev --&amp;amp;gt; repo : push/PR
repo --&amp;amp;gt; actions : trigger workflow
actions --&amp;amp;gt; test_runner : run tests
actions --&amp;amp;gt; security : security checks
actions --&amp;amp;gt; quality : code quality
actions --&amp;amp;gt; build : build package
build --&amp;amp;gt; test_pypi : deploy (pre-release)
build --&amp;amp;gt; prod_pypi : deploy (release)
prod_pypi --&amp;amp;gt; users : install package

@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_प्रोजेक्ट_संरचना&amp;quot;&amp;gt;प्रोजेक्ट संरचना&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;वितरण के लिए तैयार Python CLI एप्लिकेशन को एक मानकीकृत संरचना का पालन करना चाहिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;text&amp;quot;&amp;gt;playlist-downloader/
├── .github/
│   └── workflows/
│       ├── ci.yml
│       ├── release.yml
│       └── security.yml
├── src/
│   └── playlist_downloader/
│       ├── __init__.py
│       ├── cli.py
│       ├── core/
│       └── adapters/
├── tests/
│   ├── unit/
│   ├── integration/
│   └── conftest.py
├── docs/
├── pyproject.toml
├── requirements.txt
├── requirements-dev.txt
├── MANIFEST.in
├── README.md
├── LICENSE
└── CHANGELOG.md&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_pyproject_toml_के_साथ_पैकेज_कॉन्फ़िगरेशन&amp;quot;&amp;gt;pyproject.toml के साथ पैकेज कॉन्फ़िगरेशन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फ़ाइल`pyproject.toml`यह Python पैकेज को कॉन्फ़िगर करने का आधुनिक मानक है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;toml&amp;quot;&amp;gt;[build-system]
requires = [&amp;quot;setuptools&amp;amp;gt;=45&amp;quot;, &amp;quot;wheel&amp;quot;, &amp;quot;setuptools_scm&amp;amp;gt;=6.2&amp;quot;]
build-backend = &amp;quot;setuptools.build_meta&amp;quot;

[project]
name = &amp;quot;playlist-downloader&amp;quot;
authors = [
    {name = &amp;quot;Christophe Hérolivier&amp;quot;, email = &amp;quot;cheroliv@example.com&amp;quot;},
]
description = &amp;quot;CLI tool for YouTube playlist management&amp;quot;
readme = &amp;quot;README.md&amp;quot;
requires-python = &amp;quot;&amp;amp;gt;=3.8&amp;quot;
keywords = [&amp;quot;youtube&amp;quot;, &amp;quot;playlist&amp;quot;, &amp;quot;cli&amp;quot;, &amp;quot;downloader&amp;quot;]
license = {text = &amp;quot;MIT&amp;quot;}
classifiers = [
    &amp;quot;Development Status :: 4 - Beta&amp;quot;,
    &amp;quot;Environment :: Console&amp;quot;,
    &amp;quot;Intended Audience :: End Users/Desktop&amp;quot;,
    &amp;quot;License :: OSI Approved :: MIT License&amp;quot;,
    &amp;quot;Operating System :: OS Independent&amp;quot;,
    &amp;quot;Programming Language :: Python :: 3&amp;quot;,
    &amp;quot;Programming Language :: Python :: 3.8&amp;quot;,
    &amp;quot;Programming Language :: Python :: 3.9&amp;quot;,
    &amp;quot;Programming Language :: Python :: 3.10&amp;quot;,
    &amp;quot;Programming Language :: Python :: 3.11&amp;quot;,
    &amp;quot;Topic :: Multimedia :: Sound/Audio&amp;quot;,
    &amp;quot;Topic :: Utilities&amp;quot;,
]
dependencies = [
    &amp;quot;typer&amp;amp;gt;=0.9.0&amp;quot;,
    &amp;quot;yt-dlp&amp;amp;gt;=2023.7.6&amp;quot;,
    &amp;quot;google-api-python-client&amp;amp;gt;=2.0.0&amp;quot;,
    &amp;quot;google-auth-oauthlib&amp;amp;gt;=1.0.0&amp;quot;,
    &amp;quot;pyyaml&amp;amp;gt;=6.0&amp;quot;,
    &amp;quot;rich&amp;amp;gt;=13.0.0&amp;quot;,
]
dynamic = [&amp;quot;version&amp;quot;]

[project.optional-dependencies]
dev = [
    &amp;quot;pytest&amp;amp;gt;=7.0.0&amp;quot;,
    &amp;quot;pytest-cov&amp;amp;gt;=4.0.0&amp;quot;,
    &amp;quot;pytest-mock&amp;amp;gt;=3.10.0&amp;quot;,
    &amp;quot;black&amp;amp;gt;=23.0.0&amp;quot;,
    &amp;quot;flake8&amp;amp;gt;=6.0.0&amp;quot;,
    &amp;quot;mypy&amp;amp;gt;=1.0.0&amp;quot;,
    &amp;quot;pre-commit&amp;amp;gt;=3.0.0&amp;quot;,
    &amp;quot;tox&amp;amp;gt;=4.0.0&amp;quot;,
]
test = [
    &amp;quot;pytest&amp;amp;gt;=7.0.0&amp;quot;,
    &amp;quot;pytest-cov&amp;amp;gt;=4.0.0&amp;quot;,
    &amp;quot;pytest-mock&amp;amp;gt;=3.10.0&amp;quot;,
]

[project.urls]
Homepage = &amp;quot;https://github.com/cheroliv/playlist-downloader&amp;quot;
Documentation = &amp;quot;https://github.com/cheroliv/playlist-downloader#readme&amp;quot;
Repository = &amp;quot;https://github.com/cheroliv/playlist-downloader.git&amp;quot;
&amp;quot;Bug Tracker&amp;quot; = &amp;quot;https://github.com/cheroliv/playlist-downloader/issues&amp;quot;

[project.scripts]
playlist-downloader = &amp;quot;playlist_downloader.cli:main&amp;quot;

[tool.setuptools_scm]
write_to = &amp;quot;src/playlist_downloader/_version.py&amp;quot;

[tool.setuptools.packages.find]
where = [&amp;quot;src&amp;quot;]

[tool.pytest.ini_options]
testpaths = [&amp;quot;tests&amp;quot;]
python_files = [&amp;quot;test_*.py&amp;quot;]
python_classes = [&amp;quot;Test*&amp;quot;]
python_functions = [&amp;quot;test_*&amp;quot;]
addopts = [
    &amp;quot;--cov=src/playlist_downloader&amp;quot;,
    &amp;quot;--cov-report=html&amp;quot;,
    &amp;quot;--cov-report=term-missing&amp;quot;,
    &amp;quot;--cov-fail-under=85&amp;quot;,
]

[tool.black]
line-length = 88
target-version = [&amp;#39;py38&amp;#39;]
include = &amp;#39;\.pyi?$&amp;#39;
extend-exclude = &amp;#39;&amp;#39;&amp;#39;
/(
  \.eggs
  | \.git
  | \.hg
  | \.mypy_cache
  | \.tox
  | \.venv
  | _build
  | buck-out
  | build
  | dist
)/
&amp;#39;&amp;#39;&amp;#39;

[tool.mypy]
python_version = &amp;quot;3.8&amp;quot;
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
check_untyped_defs = true
disallow_untyped_decorators = true
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_no_return = true
warn_unreachable = true
strict_equality = true

[[tool.mypy.overrides]]
module = [
    &amp;quot;yt_dlp.*&amp;quot;,
    &amp;quot;googleapiclient.*&amp;quot;,
    &amp;quot;google_auth_oauthlib.*&amp;quot;,
]
ignore_missing_imports = true&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_cicd_वर्कफ़्लो_परीक्षण_और_गुणवत्ता&amp;quot;&amp;gt;CI/CD वर्कफ़्लो - परीक्षण और गुणवत्ता&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मुख्य कार्यप्रवाह (&amp;lt;code&amp;gt;ci.yml&amp;lt;/code&amp;gt;) कई Python संस्करणों पर टेस्ट चलाता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;yaml&amp;quot;&amp;gt;name: CI

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: [&amp;quot;3.8&amp;quot;, &amp;quot;3.9&amp;quot;, &amp;quot;3.10&amp;quot;, &amp;quot;3.11&amp;quot;]

    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0

    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v4
      with:
        python-version: ${{ matrix.python-version }}

    - name: Cache dependencies
      uses: actions/cache@v3
      with:
        path: |
          ~/.cache/pip
          ~/.cache/pre-commit
        key: ${{ runner.os }}-pip-${{ hashFiles(&amp;#39;**/requirements*.txt&amp;#39;) }}
        restore-keys: |
          ${{ runner.os }}-pip-

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -e &amp;quot;.[dev]&amp;quot;

    - name: Lint with flake8
      run: |
        flake8 src tests --count --select=E9,F63,F7,F82 --show-source --statistics
        flake8 src tests --count --exit-zero --max-complexity=10 --max-line-length=88 --statistics

    - name: Check code formatting with Black
      run: black --check src tests

    - name: Type checking with mypy
      run: mypy src

    - name: Run tests with pytest
      run: |
        pytest tests/ -v --cov=src/playlist_downloader \
          --cov-report=xml --cov-report=term-missing

    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v3
      if: matrix.python-version == &amp;#39;3.11&amp;#39;
      with:
        file: ./coverage.xml
        flags: unittests
        name: codecov-umbrella

  security:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4

    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: &amp;quot;3.11&amp;quot;

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install bandit[toml] safety

    - name: Run security checks with bandit
      run: bandit -r src/ -f json -o bandit-report.json

    - name: Check dependencies with safety
      run: safety check --json --output safety-report.json

    - name: Upload security reports
      uses: actions/upload-artifact@v3
      if: always()
      with:
        name: security-reports
        path: |
          bandit-report.json
          safety-report.json

  build:
    needs: [test, security]
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0

    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: &amp;quot;3.11&amp;quot;

    - name: Install build dependencies
      run: |
        python -m pip install --upgrade pip
        pip install build twine

    - name: Build package
      run: python -m build

    - name: Check package with twine
      run: twine check dist/*

    - name: Upload build artifacts
      uses: actions/upload-artifact@v3
      with:
        name: dist
        path: dist/&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_रिलीज़_और_डिप्लॉयमेंट_वर्कफ़्लो&amp;quot;&amp;gt;रिलीज़ और डिप्लॉयमेंट वर्कफ़्लो&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;रिलीज़ वर्कफ़्लो (&amp;lt;code&amp;gt;release.yml&amp;lt;/code&amp;gt;) पाइपीआई पर स्वचालित प्रकाशन प्रबंधित करता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;yaml&amp;quot;&amp;gt;name: Release

on:
  push:
    tags:
      - &amp;#39;v*.*.*&amp;#39;
  workflow_dispatch:
    inputs:
      environment:
        description: &amp;#39;Deployment environment&amp;#39;
        required: true
        default: &amp;#39;test&amp;#39;
        type: choice
        options:
        - test
        - production

env:
  PYTHON_VERSION: &amp;quot;3.11&amp;quot;

jobs:
  release:
    runs-on: ubuntu-latest
    environment:
      name: ${{ github.event.inputs.environment || (startsWith(github.ref, &amp;#39;refs/tags/&amp;#39;) &amp;amp;amp;&amp;amp;amp; &amp;#39;production&amp;#39; || &amp;#39;test&amp;#39;) }}

    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0

    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: ${{ env.PYTHON_VERSION }}

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install build twine

    - name: Build package
      run: python -m build

    - name: Check package
      run: twine check dist/*

    - name: Publish to Test PyPI
      if: github.event.inputs.environment == &amp;#39;test&amp;#39; || (startsWith(github.ref, &amp;#39;refs/tags/&amp;#39;) &amp;amp;amp;&amp;amp;amp; contains(github.ref, &amp;#39;rc&amp;#39;))
      env:
        TWINE_USERNAME: __token__
        TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
      run: |
        twine upload --repository testpypi dist/*

    - name: Publish to PyPI
      if: github.event.inputs.environment == &amp;#39;production&amp;#39; || (startsWith(github.ref, &amp;#39;refs/tags/&amp;#39;) &amp;amp;amp;&amp;amp;amp; !contains(github.ref, &amp;#39;rc&amp;#39;))
      env:
        TWINE_USERNAME: __token__
        TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
      run: |
        twine upload dist/*

    - name: Create GitHub Release
      if: startsWith(github.ref, &amp;#39;refs/tags/&amp;#39;)
      uses: actions/create-release@v1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        tag_name: ${{ github.ref }}
        release_name: Release ${{ github.ref }}
        draft: false
        prerelease: ${{ contains(github.ref, &amp;#39;rc&amp;#39;) }}

  post-release:
    needs: release
    runs-on: ubuntu-latest
    if: startsWith(github.ref, &amp;#39;refs/tags/&amp;#39;)

    steps:
    - uses: actions/checkout@v4

    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: ${{ env.PYTHON_VERSION }}

    - name: Test installation from PyPI
      run: |
        sleep 60  # Attendre la propagation sur PyPI
        pip install playlist-downloader
        playlist-downloader --version

    - name: Update documentation
      run: |
        # Script pour mettre à jour la documentation
        echo &amp;quot;Documentation updated for version ${GITHUB_REF#refs/tags/}&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_आर्किटेक्चर_डायग्राम&amp;quot;&amp;gt;आर्किटेक्चर डायग्राम&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सीक्वेंस_आरेख_रिलीज़_प्रक्रिया&amp;quot;&amp;gt;सीक्वेंस आरेख - रिलीज़ प्रक्रिया&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;images/diag-plantuml-md5-2046d1c6354b22d072038f56dc40cdee.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;971&amp;quot; height=&amp;quot;832&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_स्थिति_आरेख_पैकेज_जीवन_चक्र&amp;quot;&amp;gt;स्थिति आरेख - पैकेज जीवन चक्र&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;images/diag-plantuml-md5-a7f83cedc9d2d7f434257d8d55623c38.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;525&amp;quot; height=&amp;quot;740&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_डिप्लॉयमेंट_आरेख_cicd_इन्फ्रास्ट्रक्चर&amp;quot;&amp;gt;डिप्लॉयमेंट आरेख - CI/CD इन्फ्रास्ट्रक्चर&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 16) ]

@startuml




...
... ( skipping 136 lines )
...
  BorderColor black
}
skinparam UseCaseStereoType {
  FontColor black
  FontName Verdana
}
title डिप्लॉयमेंट इन्फ्रास्ट्रक्चर
node &amp;quot;GitHub&amp;quot; {
  component &amp;quot;रीपॉज़िटरी&amp;quot; as repo
  component &amp;quot;एक्शन रनर&amp;quot; as runner
  component &amp;quot;रहस्य स्टोर&amp;quot; as secrets
}

node &amp;quot;PyPI इंफ़्रास्ट्रक्चर&amp;quot; {
  component &amp;quot;PyPI&amp;quot; as pypi
  component &amp;quot;टेस्ट PyPI&amp;quot; as testpypi
  database &amp;quot;पैकेज सूचक&amp;quot; as index
}

node &amp;quot;### JBake क्या है?
^^^^^
 Syntax Error? (Assumed diagram type: component)

@startuml
!theme plain
title डिप्लॉयमेंट इन्फ्रास्ट्रक्चर
node &amp;quot;GitHub&amp;quot; {
  component &amp;quot;रीपॉज़िटरी&amp;quot; as repo
  component &amp;quot;एक्शन रनर&amp;quot; as runner
  component &amp;quot;रहस्य स्टोर&amp;quot; as secrets
}

node &amp;quot;PyPI इंफ़्रास्ट्रक्चर&amp;quot; {
  component &amp;quot;PyPI&amp;quot; as pypi
  component &amp;quot;टेस्ट PyPI&amp;quot; as testpypi
  database &amp;quot;पैकेज सूचक&amp;quot; as index
}

node &amp;quot;### JBake क्या है?
JBake एक Java-आधारित, ओपन सोर्स, स्थिर साइट/ब्लॉग जनरेटर है जो डेवलपर्स के लिए है।&amp;quot; {
  component &amp;quot;Git क्लाइंट&amp;quot; as git
  component &amp;quot;Python पर्यावरण&amp;quot; as python
  component &amp;quot;IDE&amp;quot; as ide
}

node &amp;quot;उपयोगकर्ता वातावरण&amp;quot; {
  component &amp;quot;पिप&amp;quot; as pip_client
  component &amp;quot;पायथन रनटाइम&amp;quot; as py_runtime
}

git --&amp;amp;gt; repo : push code/tags
repo --&amp;amp;gt; runner : trigger workflows
runner --&amp;amp;gt; secrets : read API tokens
runner --&amp;amp;gt; testpypi : upload pre-release
runner --&amp;amp;gt; pypi : upload release
pypi --&amp;amp;gt; index : store package
pip_client --&amp;amp;gt; pypi : download package
py_runtime &amp;amp;lt;-- pip_client : install package

@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_पाइपलाइन_की_वस्तुएँ_और_मॉडल&amp;quot;&amp;gt;पाइपलाइन की वस्तुएँ और मॉडल&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_क्लास_आरेख_cicd_मॉडल&amp;quot;&amp;gt;क्लास आरेख - CI/CD मॉडल&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;images/diag-plantuml-md5-b297b21c69498b5bc74f0da88d80315f.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;814&amp;quot; height=&amp;quot;635&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_सिक्रेट्स_की_कॉन्फ़िगरेशन&amp;quot;&amp;gt;सिक्रेट्स की कॉन्फ़िगरेशन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पाइपलाइन काम करने के लिए, आपको GitHub में निम्नलिखित सीक्रेट्स कॉन्फ़िगर करने होंगे :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_github_actions_के_रहस्य&amp;quot;&amp;gt;GitHub Actions के रहस्य&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Dans Settings &amp;amp;gt; Secrets and variables &amp;amp;gt; Actions

# Token PyPI pour la production
PYPI_API_TOKEN=pypi-...

# Token Test PyPI pour les pré-releases
TEST_PYPI_API_TOKEN=pypi-...

# Token GitHub pour créer les releases
GITHUB_TOKEN=(automatiquement fourni)

# Token Codecov (optionnel)
CODECOV_TOKEN=...&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_pypi_टोकन_जनरेशन&amp;quot;&amp;gt;PyPI टोकन जनरेशन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;bash&amp;quot;&amp;gt;# 1. Créer un compte sur PyPI et Test PyPI
# 2. Aller dans Account Settings &amp;amp;gt; API tokens
# 3. Créer un token avec scope &amp;quot;Entire account&amp;quot; ou spécifique au projet
# 4. Format du token : pypi-AgEIcHlwaS5vcmc...&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_स्थानीय_विकास_स्क्रिप्ट&amp;quot;&amp;gt;स्थानीय विकास स्क्रिप्ट&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;विकास को आसान बनाने के लिए, उपयोगिता स्क्रिप्ट बनाएँ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_makefile&amp;quot;&amp;gt;Makefile&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;makefile&amp;quot;&amp;gt;.PHONY: install test lint format security build clean release-test release-prod

install:
	pip install -e &amp;quot;.[dev]&amp;quot;

test:
	pytest tests/ -v --cov=src/playlist_downloader

lint:
	flake8 src tests
	mypy src

format:
	black src tests

security:
	bandit -r src/
	safety check

build:
	python -m build
	twine check dist/*

clean:
	rm -rf build/ dist/ *.egg-info/
	find . -type d -name __pycache__ -delete
	find . -name &amp;quot;*.pyc&amp;quot; -delete

release-test: clean build
	twine upload --repository testpypi dist/*

release-prod: clean build
	twine upload dist/*

pre-commit: format lint test security
	@echo &amp;quot;✅ Prêt pour commit&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_स्क्रिप्ट_संस्करण&amp;quot;&amp;gt;स्क्रिप्ट संस्करण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;python&amp;quot;&amp;gt;#!/usr/bin/env python3
&amp;quot;&amp;quot;&amp;quot;Script pour gérer les versions du projet.&amp;quot;&amp;quot;&amp;quot;

import sys
import subprocess
from pathlib import Path

def get_current_version():
    &amp;quot;&amp;quot;&amp;quot;Récupère la version actuelle depuis git.&amp;quot;&amp;quot;&amp;quot;
    try:
        result = subprocess.run(
            [&amp;quot;git&amp;quot;, &amp;quot;describe&amp;quot;, &amp;quot;--tags&amp;quot;, &amp;quot;--abbrev=0&amp;quot;],
            capture_output=True,
            text=True,
            check=True
        )
        return result.stdout.strip()
    except subprocess.CalledProcessError:
        return &amp;quot;0.0.0&amp;quot;

def create_version_tag(version, message=None):
    &amp;quot;&amp;quot;&amp;quot;Crée un tag de version.&amp;quot;&amp;quot;&amp;quot;
    if not version.startswith(&amp;#39;v&amp;#39;):
        version = f&amp;#39;v{version}&amp;#39;

    tag_message = message or f&amp;quot;Release {version}&amp;quot;

    subprocess.run([&amp;quot;git&amp;quot;, &amp;quot;tag&amp;quot;, &amp;quot;-a&amp;quot;, version, &amp;quot;-m&amp;quot;, tag_message], check=True)
    print(f&amp;quot;✅ Tag {version} créé&amp;quot;)

    # Push le tag
    subprocess.run([&amp;quot;git&amp;quot;, &amp;quot;push&amp;quot;, &amp;quot;origin&amp;quot;, version], check=True)
    print(f&amp;quot;✅ Tag {version} poussé vers origin&amp;quot;)

if __name__ == &amp;quot;__main__&amp;quot;:
    if len(sys.argv) &amp;amp;lt; 2:
        current = get_current_version()
        print(f&amp;quot;Version actuelle: {current}&amp;quot;)
        print(&amp;quot;Usage: python version.py &amp;amp;lt;new_version&amp;amp;gt; [message]&amp;quot;)
        sys.exit(1)

    new_version = sys.argv[1]
    message = sys.argv[2] if len(sys.argv) &amp;amp;gt; 2 else None

    create_version_tag(new_version, message)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_अच्छी_प्रथाएँ_और_सिफारिशें&amp;quot;&amp;gt;अच्छी प्रथाएँ और सिफारिशें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_समानार्थिक_संस्करण&amp;quot;&amp;gt;समानार्थिक संस्करण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सेमेंटिक वर्जनिंग (SemVer) का उपयोग करें:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;MAJOR.MINOR.PATCH&amp;lt;/code&amp;gt; (ex: 1.2.3)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;MAJOR&amp;lt;/code&amp;gt;: असंगत परिवर्तन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;MINOR&amp;lt;/code&amp;gt;: नए संगत विशेषताएँ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;`PATCH`संगत बग सुधार&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ब्रांचिंग_रणनीति&amp;quot;&amp;gt;ब्रांचिंग रणनीति&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;text&amp;quot;&amp;gt;main          ──●──●──●──●──●────●── (releases stables)
               /       /          /
develop    ──●──●──●──●──●──●──●──●── (développement)
            /     /        /
feature/xxx  ●──●──●──●──●──/ (fonctionnalités)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_टेस्ट_और_कवरेज&amp;quot;&amp;gt;टेस्ट और कवरेज&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कोड कवरेज न्यूनतम : 85%&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;यूनिट टेस्ट व्यावसायिक तर्क के लिए&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एडेप्टर्स के लिए एकीकरण परीक्षण&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;CLI के लिए एंड-टू-एंड परीक्षण&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सुरक्षा&amp;quot;&amp;gt;सुरक्षा&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;निर्भरताओं का स्वचालित स्कैन (Safety)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कोड का स्थैतिक विश्लेषण (Bandit)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कोड में कभी भी रहस्य नहीं&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;विशिष्ट PyPI टोकन का उपयोग&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_मॉनिटरिंग_और_ऑब्ज़र्वेबिलिटी&amp;quot;&amp;gt;मॉनिटरिंग और ऑब्ज़र्वेबिलिटी&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_पाइपलाइन_मेट्रिक्स&amp;quot;&amp;gt;पाइपलाइन मेट्रिक्स&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;yaml&amp;quot;&amp;gt;# .github/workflows/metrics.yml
name: Pipeline Metrics

on:
  workflow_run:
    workflows: [&amp;quot;CI&amp;quot;, &amp;quot;Release&amp;quot;]
    types: [completed]

jobs:
  metrics:
    runs-on: ubuntu-latest
    steps:
    - name: Collect metrics
      run: |
        echo &amp;quot;Pipeline: ${{ github.event.workflow_run.name }}&amp;quot;
        echo &amp;quot;Status: ${{ github.event.workflow_run.conclusion }}&amp;quot;
        echo &amp;quot;Duration: ${{ github.event.workflow_run.updated_at - github.event.workflow_run.created_at }}&amp;quot;
        # Envoyer vers système de monitoring&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सूचनाएँ&amp;quot;&amp;gt;सूचनाएँ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;yaml&amp;quot;&amp;gt;# Ajout dans les workflows pour notifications
- name: Notify on failure
  if: failure()
  uses: 8398a7/action-slack@v3
  with:
    status: failure
    text: &amp;quot;❌ Pipeline failed for ${{ github.repository }}&amp;quot;
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह पायथन के लिए पूर्ण CI/CD पाइपलाइन प्रदान करता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;पूर्ण स्वचालन&amp;lt;/strong&amp;gt;: कोड की सत्यापन से प्रकाशन तक&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;सुरक्षा&amp;lt;/strong&amp;gt;स्वचालित स्कैन और सुरक्षित रहस्य प्रबंधन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;गुणवत्ता&amp;lt;/strong&amp;gt;: बहु- संस्करणों के परीक्षण, लिंटिंग और कोड कवरेज&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;विश्वसनीयता&amp;lt;/strong&amp;gt;: Test PyPI के माध्यम से क्रमिक तैनाती&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;ट्रेसेबिलिटी&amp;lt;/strong&amp;gt;: artifacts, रिपोर्ट और releases GitHub&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इन प्रथाओं को अपनाने से आपके Python CLI एप्लिकेशनों के लिए एक मजबूत और पेशेवर डिलीवरी प्रक्रिया सुनिश्चित होती है, जिससे आपके प्रोजेक्ट्स की रखरखाव और दीर्घकालिक विकास आसान हो जाता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_अतिरिक्त_संसाधन&amp;quot;&amp;gt;अतिरिक्त संसाधन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://packaging.python.org/&amp;quot;&amp;gt;Python Packaging User Guide&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://docs.github.com/en/actions&amp;quot;&amp;gt;GitHub Actions दस्तावेज़&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://pypi.org/help/&amp;quot;&amp;gt;PyPI मदद दस्तावेज़&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://semver.org/&amp;quot;&amp;gt;सेमेंटिक वर्ज़निंग विनिर्देश&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://keepachangelog.com/&amp;quot;&amp;gt;चेंजलॉग रखें&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>भाग 1 : Python और PyPI के लिए एक सरल CI/CD पाइपलाइन सेटअप करें</title>
            <link >https://cheroliv.com/blog/2025/0085_pypi_cicd_part_1_post.html</link>
            <pubDate>Thu, 17 Jul 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0085_pypi_cicd_part_1_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पाइपलाइन_आर्किटेक्चर&amp;quot;&amp;gt;पाइपलाइन आर्किटेक्चर&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ci_पाइपलाइन_कॉन्फ़िगरेशन&amp;quot;&amp;gt;CI पाइपलाइन कॉन्फ़िगरेशन&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ci_वर्कफ़्लो_की_संरचना&amp;quot;&amp;gt;CI वर्कफ़्लो की संरचना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ci_चरणों_का_विश्लेषण&amp;quot;&amp;gt;CI चरणों का विश्लेषण&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel3&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_1_ट्रिगर_on&amp;quot;&amp;gt;1. ट्रिगर (&amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;lक्ष्य : पाठक की सहायता करके एक न्यूनतम लेकिन कार्यात्मक CI/CD पाइपलाइन सेट अप करें, एक Python एप्लिकेशन के लिए, जिसमें PyPI पर स्वचालित तैनाती शामिल है।&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;विकास प्रक्रियाओं का स्वचालन आधुनिक परियोजनाओं में अनिवार्य बन गया है। एक अच्छी तरह से डिज़ाइन किया गया CI/CD पाइपलाइन न केवल विकास चक्र के शुरुआती चरण में प्रतिगमन का पता लगाने की अनुमति देता है, बल्कि पूरी तरह से तैनाती प्रक्रिया को स्वचालित भी करता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस लेख में, हम एक Python एप्लिकेशन के लिए GitHub Actions के साथ एक पूर्ण CI/CD पाइपलाइन स्थापित करने का तरीका जानेंगे, निरंतर एकीकरण (CI) से निरंतर वितरण (CD) तक PyPI पर।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_पाइपलाइन_आर्किटेक्चर&amp;quot;&amp;gt;पाइपलाइन आर्किटेक्चर&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारा पाइपलाइन दो अलग वर्कफ़्लो से बना है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;सीआई पाइपलाइन&amp;lt;/strong&amp;gt;हर पुश और pull request पर निष्पादित&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;CD पाइपलाइन&amp;lt;/strong&amp;gt;: केवल GitHub रिलीज़ के दौरान ट्रिगर किया जाता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;images/ci-cd-overview.svg&amp;quot; alt=&amp;quot;ci cd overview&amp;quot; width=&amp;quot;1618&amp;quot; height=&amp;quot;5132&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_ci_पाइपलाइन_कॉन्फ़िगरेशन&amp;quot;&amp;gt;CI पाइपलाइन कॉन्फ़िगरेशन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ci_वर्कफ़्लो_की_संरचना&amp;quot;&amp;gt;CI वर्कफ़्लो की संरचना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;CI वर्कफ़्लो को कोड में प्रत्येक योगदान को मान्य करने के लिए डिज़ाइन किया गया है। यहाँ इसकी पूर्ण कॉन्फ़िगरेशन है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;yaml&amp;quot;&amp;gt;name: CI/CD Pipeline

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: &amp;#39;3.x&amp;#39;

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
        pip install ruff pytest pytest-mock

    - name: Run Linting (Ruff)
      run: ruff check .

    - name: Run Tests (Pytest)
      run: pytest&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ci_चरणों_का_विश्लेषण&amp;quot;&amp;gt;CI चरणों का विश्लेषण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_1_ट्रिगर_on&amp;quot;&amp;gt;1. ट्रिगर (&amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;)&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;pygments highlight&amp;quot;&amp;gt;&amp;lt;code data-lang=&amp;quot;yaml&amp;quot;&amp;gt;----
----
on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main
----

पाइपलाइन ट्रिगर होती है : - हर push शाखा पर`main` - हर पुल अनुरोध की ओर`main`

यह दृष्टिकोण सुनिश्चित करता है कि मुख्य कोड स्थिर रहे और किसी भी योगदान को एकीकरण से पहले मान्य किया जाए।

==== 2. निष्पादन वातावरण

----

runs-on: ubuntu-latest

Ubuntu Latest प्रदर्शन, लागत और संगतता के बीच एक अच्छा संतुलन प्रदान करता है, अधिकांश पायथन परियोजनाओं के लिए।

==== 3. चेकआउट कोड का

```yaml
----
----
- name: Checkout code
  uses: actions/checkout@v4
----

क्रिया`checkout@v4`रेपॉज़िटरी का सोर्स कोड प्राप्त करता है. संस्करण v4 प्रदर्शन और सुरक्षा में सुधार लाता है।

==== 4. कॉन्फ़िगरेशन पाइथन

----

- name: Set up Python uses: actions/setup-python@v5 with: python-version: &amp;#39;3.x&amp;#39;

का उपयोग`&amp;#39;3.x&amp;#39;`यह Python 3 के नवीनतम स्थिर संस्करण का स्वचालित रूप से उपयोग करने की सुविधा प्रदान करता है, जिससे रखरखाव सरल हो जाता है।

==== 5. निर्भरताओं की स्थापना

```yaml
----
----
- name: Install dependencies
  run: |
    python -m pip install --upgrade pip
    pip install -r requirements.txt
    pip install ruff pytest pytest-mock
----

यह चरण : - Met à jour pip vers la dernière version - परियोजना की निर्भरताएँ स्थापित करें विकास उपकरण जोड़ें (लिंटिंग और परीक्षण)

==== 6. Ruff के साथ लिंटिंग

----

- name: Run Linting (Ruff) run: ruff check .

**Ruff**यह एक अत्यंत तेज़ Python लिंटर है, जो रस्ट में लिखा गया है। यह कई टूल (Flake8, Black, isort) की विशेषताओं को एक ही उच्च प्रदर्शन वाले टूल में जोड़ता है।

==== 7. परीक्षण का निष्पादन

```yaml
----
----
- name: Run Tests (Pytest)
  run: pytest
----

Pytest पूरे टेस्ट सुइट को चलाता है, जिससे यह सुनिश्चित होता है कि संशोधन कोई रिग्रेशन नहीं लाते।

== डिप्लॉयमेंट पाइपलाइन (CD) की कॉन्फ़िगरेशन

=== सीडी वर्कफ़्लो की संरचना

CD वर्कफ़्लो केवल GitHub रिलीज़ पर ट्रिगर होता है और PyPI पर प्रकाशन को स्वचालित बनाता है :

[source,yaml]
----
name: Publish to PyPI

on:
  release:
    types:
      - published

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: &amp;#39;3.x&amp;#39;

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install setuptools wheel twine

    - name: Build and publish
      env:
        TWINE_USERNAME: __token__
        TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
      run: |
        python setup.py sdist bdist_wheel
        twine upload dist/*
----

=== CD चरणों का विश्लेषण

==== ट्रिगर रिलीज़

----

on: release: types: - published

CD पाइपलाइन केवल GitHub रिलीज़ प्रकाशित होने पर ही ट्रिगर होती है। यह दृष्टिकोण तैनाती पर सटीक नियंत्रण सुनिश्चित करता है।

==== 2. बिल्ड टूल्स की स्थापना

```yaml
----
----
pip install setuptools wheel twine
----

- **setuptools**पायथन पैकेजिंग टूल्स - **चक्का**: आधुनिक पायथन वितरण प्रारूप - **twine**: सुरक्षित उपकरण PyPI में अपलोड करने के लिए

==== 3. प्रमाणीकरण की कॉन्फ़िगरेशन

----

env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}

प्रमाणीकरण PyPI API टोकन का उपयोग करता है, जो GitHub पर एक राज के रूप में संग्रहीत किया जाता है, और यह सामान्य पहचान प्रमाणपत्रों की तुलना में अधिक सुरक्षित है।

==== 4. बिल्ड और प्रकाशन

```yaml
----
----
run: |
  python setup.py sdist bdist_wheel
  twine upload dist/*
----

- `sdist`: एक स्रोत वितरण बनाएँ - `bdist_wheel`: wheel बनाएँ (बाइनरी वितरण) - `twine upload`: प्रकाशित करें वितरण PyPI पर

== पायथन पैकेज की कॉन्फ़िगरेशन

=== setup.py की संरचना

पाइपलाइन को काम करने के लिए, आपके प्रोजेक्ट में एक फ़ाइल शामिल होनी चाहिए`setup.py`:

[source,python]
----
from setuptools import setup, find_packages

with open(&amp;quot;README.adoc&amp;quot;, &amp;quot;r&amp;quot;, encoding=&amp;quot;utf-8&amp;quot;) as fh:
    long_description = fh.read()

setup(
    name=&amp;quot;playlist-downloader&amp;quot;,
    version=&amp;quot;1.0.0&amp;quot;,
    author=&amp;quot;Votre Nom&amp;quot;,
    author_email=&amp;quot;votre.email@example.com&amp;quot;,
    description=&amp;quot;CLI tool for managing YouTube playlists&amp;quot;,
    long_description=long_description,
    long_description_content_type=&amp;quot;text/plain&amp;quot;,
    url=&amp;quot;https://github.com/cheroliv/playlist-downloader&amp;quot;,
    packages=find_packages(),
    classifiers=[
        &amp;quot;Development Status :: 4 - Beta&amp;quot;,
        &amp;quot;Intended Audience :: Developers&amp;quot;,
        &amp;quot;License :: OSI Approved :: MIT License&amp;quot;,
        &amp;quot;Operating System :: OS Independent&amp;quot;,
        &amp;quot;Programming Language :: Python :: 3&amp;quot;,
        &amp;quot;Programming Language :: Python :: 3.8&amp;quot;,
        &amp;quot;Programming Language :: Python :: 3.9&amp;quot;,
        &amp;quot;Programming Language :: Python :: 3.10&amp;quot;,
        &amp;quot;Programming Language :: Python :: 3.11&amp;quot;,
    ],
    python_requires=&amp;quot;&amp;amp;gt;=3.8&amp;quot;,
    install_requires=[
        &amp;quot;typer&amp;amp;gt;=0.9.0&amp;quot;,
        &amp;quot;yt-dlp&amp;amp;gt;=2023.1.6&amp;quot;,
        &amp;quot;google-api-python-client&amp;amp;gt;=2.70.0&amp;quot;,
        &amp;quot;google-auth-oauthlib&amp;amp;gt;=0.7.1&amp;quot;,
        &amp;quot;pymonad&amp;amp;gt;=2.4.0&amp;quot;,
        &amp;quot;pyyaml&amp;amp;gt;=6.0&amp;quot;,
    ],
    entry_points={
        &amp;quot;console_scripts&amp;quot;: [
            &amp;quot;playlist-downloader=cli:app&amp;quot;,
        ],
    },
)
----

=== setup.py के मुख्य बिंदु

1. **मेटाडेटा**: नाम, संस्करण, लेखक, विवरण
2. **निर्भरताएँ**: आवश्यक पैकेजों की सूची
3. **प्रवेश बिंदु**### ग्रेडल एकीकरण
JBake को JBake Gradle प्लगिन का उपयोग करके या JBake CLI को सीधे बुलाकर Gradle बिल्ड में एकीकृत किया जा सकता है:

----

tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) { mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;) classpath = configurations[&amp;quot;jbake&amp;quot;] args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;) } ```

: CLI कमांड्स उजागर

1. **वर्गीकरणकर्ता**PyPI के लिए मेटाडेटा

== गिटहब सीक्रेट्स के साथ सुरक्षा

=== PyPI टोकन की कॉन्फ़िगरेशन

1. **PyPI पर API टोकन बनाएं**:

- PyPI पर लॉग इन करें - जाएँ Account Settings &amp;amp;gt; API tokens - Créez un nouveau token avec les permissions appropriées

1. **GitHub में सीक्रेट जोड़ें**:

- रिपॉज़िटरी सेटिंग्स &amp;amp;gt; सीक्रेट्स और चर &amp;amp;gt; क्रियाएँ - एक नया सीक्रेट नामित करें`PYPI_API_TOKEN` अपना PyPI टोकन पेस्ट करें

[plantuml, secrets-flow, svg]
----
@startuml
!theme plain

actor Developer as dev
participant &amp;quot;गिटहब रिपॉजिटरी&amp;quot; as repo
participant &amp;quot;GitHub Actions&amp;quot; as actions
participant PyPI

dev -&amp;amp;gt; repo : Configure PYPI_API_TOKEN secret
repo -&amp;amp;gt; actions : Trigger CD pipeline on release
actions -&amp;amp;gt; actions : Access secret securely
actions -&amp;amp;gt; PyPI : Authenticate with token
PyPI -&amp;amp;gt; PyPI : Validate and publish package

note over actions, PyPI
  Token never exposed in logs
  Automatic rotation possible
end note

@enduml
----

== पूर्ण तैनाती वर्कफ़्लो

=== डिप्लॉयमेंट अनुक्रम

[plantuml, deployment-sequence, svg]
----
@startuml
!theme plain

actor Developer as dev
participant &amp;quot;Local Git&amp;quot; as git
participant &amp;quot;GitHub&amp;quot; as github
participant &amp;quot;GitHub Actions&amp;quot; as actions
participant PyPI
participant &amp;quot;End Users&amp;quot; as users

dev -&amp;amp;gt; git : git tag v1.0.0
dev -&amp;amp;gt; git : git push origin v1.0.0
git -&amp;amp;gt; github : Push tag
dev -&amp;amp;gt; github : Create release from tag
github -&amp;amp;gt; actions : Trigger CD pipeline
actions -&amp;amp;gt; actions : Checkout code
actions -&amp;amp;gt; actions : Setup Python environment
actions -&amp;amp;gt; actions : Install build tools
actions -&amp;amp;gt; actions : Build distributions (sdist + wheel)
actions -&amp;amp;gt; PyPI : Upload to PyPI with token
PyPI -&amp;amp;gt; PyPI : Validate and publish
users -&amp;amp;gt; PyPI : pip install playlist-downloader

note over dev, github
  Release creation can be automated
  or done manually through GitHub UI
end note

@enduml
----

=== पाइपलाइन की स्थिति

[plantuml, pipeline-states, svg]
----
@startuml
!theme plain

[*] --&amp;amp;gt; Idle

Idle --&amp;amp;gt; CI_Running : Push/PR created
CI_Running --&amp;amp;gt; CI_Success : All checks pass
CI_Running --&amp;amp;gt; CI_Failed : Linting/Tests fail
CI_Success --&amp;amp;gt; Idle : Merge completed
CI_Failed --&amp;amp;gt; Idle : Fix and retry

Idle --&amp;amp;gt; CD_Running : Release published
CD_Running --&amp;amp;gt; CD_Success : Package published
CD_Running --&amp;amp;gt; CD_Failed : Build/Upload error
CD_Success --&amp;amp;gt; Idle : Package available on PyPI
CD_Failed --&amp;amp;gt; Idle : Fix and retry release

note on link #red : Blocks merge
note on link #green : Allows deployment

@enduml
----

== अच्छी प्रथाएँ और अनुकूलन

=== 1. संस्करण प्रबंधन

सार्थक Git टैग्स का उपयोग करें :

```bash
----
----
git tag -a v1.2.3 -m &amp;quot;Release version 1.2.3&amp;quot;
git push origin v1.2.3
----

=== 2. मैट्रिक्स परीक्षण

बहुत से Python संस्करणों पर परीक्षण करने के लिए:

----

strategy: matrix: python-version: [3.8, 3.9, &amp;quot;3.10&amp;quot;, &amp;quot;3.11&amp;quot;]

=== 3. Cache des Dépendances

बिल्ड्स को कैश के साथ तेज़ करें :

```yaml
----
----
- name: Cache pip dependencies
  uses: actions/cache@v3
  with:
    path: ~/.cache/pip
    key: ${{ runner.os }}-pip-${{ hashFiles(&amp;#39;**/requirements.txt&amp;#39;) }}
----

=== 4. परिनियोजन पर्यावरण

गिटहब वातावरणों का उपयोग नियंत्रित तैनाती के लिए करें :

----

jobs: deploy: environment: production runs-on: ubuntu-latest

== उपयोग केस और आर्किटेक्चर

=== केस उपयोग आरेख

[plantuml, use-cases, svg]
----
@startuml
!theme plain

left to right direction

actor &amp;quot;डेवलपर&amp;quot; as dev
actor &amp;quot;GitHub Actions&amp;quot; as ga
actor &amp;quot;End User&amp;quot; as user

package &amp;quot;CI/CD प्रणाली&amp;quot; {
  usecase &amp;quot;लिंटिंग चलाएँ&amp;quot; as lint
  usecase &amp;quot;टेस्ट निष्पादित करें&amp;quot; as test
  usecase &amp;quot;### gradle का एकीकरण
JBake को JBake Gradle प्लगिन का उपयोग करके या JBake CLI को सीधे बुलाकर Gradle बिल्ड में एकीकृत किया जा सकता है:

```kotlin
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
}&amp;quot; as build
  usecase &amp;quot;PyPI पर प्रकाशित करें&amp;quot; as publish
  usecase &amp;quot;Create Release&amp;quot; as release
}

dev --&amp;amp;gt; lint : Pushes code
dev --&amp;amp;gt; test : Pushes code
dev --&amp;amp;gt; release : Creates release
ga --&amp;amp;gt; build : On release trigger
ga --&amp;amp;gt; publish : After successful build
user --&amp;amp;gt; publish : Downloads package

lint .&amp;amp;gt; test : triggers
test .&amp;amp;gt; build : on success
build .&amp;amp;gt; publish : on success

@enduml
----

=== डिप्लॉयमेंट आर्किटेक्चर

[plantuml, deployment-architecture, svg]
----
@startuml
!theme plain

cloud &amp;quot;GitHub&amp;quot; {
  [Source Repository]
  [GitHub Actions]
  [Secrets Store]
}

cloud &amp;quot;PyPI&amp;quot; {
  [Package Registry]
  [Distribution Files]
}

node &amp;quot;CI/CD पाइपलाइन&amp;quot; {
  [Linting]
  [Testing]
  [Building]
  [Publishing]
}

[Source Repository] --&amp;amp;gt; [GitHub Actions] : Triggers
[GitHub Actions] --&amp;amp;gt; [Linting]
[Linting] --&amp;amp;gt; [Testing]
[Testing] --&amp;amp;gt; [Building]
[Building] --&amp;amp;gt; [Publishing]
[Publishing] --&amp;amp;gt; [Package Registry] : Uploads
[Secrets Store] --&amp;amp;gt; [Publishing] : Provides token

note as N1
  Secure token-based
  authentication
end note

[Secrets Store] .. N1

@enduml
----

== मॉनिटरिंग और डिबगिंग

=== लॉग्स और मॉनिटरिंग

GitHub Actions प्रत्येक चरण के लिए विस्तृत लॉग प्रदान करता है। डीबग करने के लिए :

1. **लॉग्स की जाँच करें**हर स्टेप का
2. **डिबग को सक्रिय करें**साथ`ACTIONS_STEP_DEBUG`
3. **आर्टिफैक्ट्स का उपयोग करें**बिल्ड फ़ाइलों को सहेजने के लिए

```yaml
----
----
- name: Upload build artifacts
  uses: actions/upload-artifact@v3
  if: failure()
  with:
    name: build-logs
    path: build/
----

=== सूचनाएँ

स्लैक या ईमेल सूचनाएँ जोड़ें :

----

- name: Notify on failure if: failure() uses: 8398a7/action-slack@v3 with: status: ${{ job.status }} webhook_url: ${{ secrets.SLACK_WEBHOOK }}

== निष्कर्ष

गिटहब एक्शंस के साथ एक मजबूत CI/CD पाइपलाइन स्थापित करने से विकास अनुभव में रैडिकल परिवर्तन आ जाता है। लिंटिंग, परीक्षण और तैनाती को स्वचालित करके, आप:

- **त्रुटियों को कम करें**उत्पादन में - **चक्रों को तेज़ करें**विकास का - **विश्वास में सुधार लाएँ**आपके रिलीज़ में - **सहयोग को सुगम बनाएँ**में टीम

इस पाइपलाइन को विभिन्न प्रकार के Python प्रोजेक्ट्स के लिए लिंटिंग टूल्स, टेस्ट फ्रेमवर्क और डिप्लॉयमेंट गंतव्यों को समायोजित करके अनुकूलित किया जा सकता है।

इन वर्कफ़्लो को कॉन्फ़िगर करने के प्रारंभिक निवेश को समय की बचत और तैनाती के दौरान मैन्युअल त्रुटियों में कमी के माध्यम से तेज़ी से पुनः प्राप्त किया जाता है।

== पूरक संसाधन

- https://docs.github.com/en/actions[GitHub Actions दस्तावेज़] - https://packaging.python.org/[Python पैकेजिंग गाइड] - https://docs.pytest.org/[Pytest दस्तावेज़] - https://docs.astral.sh/ruff/[दस्तावेज़ Ruff] - https://twine.readthedocs.io/[दस्तावेज़ीकरण Twine]

�✅ कार्यात्मक पाइपलाइन पहुँच गई ! अब आपके पास एक सरल CI/CD पाइपलाइन है जो आपको अपने टेस्ट को स्वचालित करने और अपने Python पैकेज को PyPI पर GitHub Actions से सीधे प्रकाशित करने की अनुमति देती है।

हालाँकि, यह पाइपलाइन स्वैच्छिक रूप से न्यूनतम रखी गई है। यह अभी तक पेशेवर संदर्भ में आवश्यक कुछ पहलुओं को कवर नहीं करती :

Python के कई संस्करणों के परीक्षण,

स्वचालित सुरक्षा विश्लेषण

टेस्ट PyPI के माध्यम से धीरे-धीरे तैनाती,

पाइपलाइन की निगरानी और मेट्रिक्स,

संस्करण नियंत्रण का स्वचालन और आधुनिक सर्वोत्तम प्रथाओं का एकीकरण (pyproject.toml)

अगले भाग में, हम अगले स्तर पर पहुँचेंगे। आप सीखेंगे कि इस बुनियादी पाइपलाइन को एक वास्तविक औद्योगिक तैनाती श्रृंखला में बदलें, जो मजबूत, सुरक्षित हो और उत्पादन के Python प्रोजेक्ट्स के लिए तैयार हो।&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>डिस्कॉर्ड संगीत बॉट का विकास : कार्यात्मक आर्किटेक्चर और लॉग-ड्रिवन डेवलपमेंट</title>
            <link >https://cheroliv.com/blog/2025/0084_disco_bot_discord_python_post.html</link>
            <pubDate>Wed, 16 Jul 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0084_disco_bot_discord_python_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table of Contents&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संदर्भ_और_वर्तमान_चुनौतियाँ&amp;quot;&amp;gt;संदर्भ और वर्तमान चुनौतियाँ&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संगीत_apis_का_विकास&amp;quot;&amp;gt;संगीत APIs का विकास&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_लॉग_चालित_विकास_की_पद्धति&amp;quot;&amp;gt;लॉग-चालित विकास की पद्धति&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सैद्धांतिक_वास्तुकला&amp;quot;&amp;gt;सैद्धांतिक वास्तुकला&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_स्टैक_तकनीक_और_फ़ंक्शनल_पैराडाइम&amp;quot;&amp;gt;स्टैक तकनीक और फ़ंक्शनल पैराडाइम&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_तकनीकी_विकल्प&amp;quot;&amp;gt;तकनीकी विकल्प&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_लागू_कार्यात्मक_सिद्धांत&amp;quot;&amp;gt;लागू कार्यात्मक सिद्धांत&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_agile_पद्धति_और_बैकलॉग&amp;quot;&amp;gt;Agile पद्धति और बैकलॉग&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_एपिक_मुख्य&amp;quot;&amp;gt;एपिक मुख्य&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel3&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_epic_1_आधारभूत_संरचना_बॉट_discord&amp;quot;&amp;gt;Epic 1: आधारभूत संरचना बॉट Discord&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_epic_2_स्पोटिफ़ाई_का_एकीकरण&amp;quot;&amp;gt;Epic 2 : स्पोटिफ़ाई का एकीकरण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_epic_3_youtube_का_एकीकरण&amp;quot;&amp;gt;Epic 3 : YouTube का एकीकरण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_epic_4_संगीत_विशेषताएँ&amp;quot;&amp;gt;Epic 4 : संगीत विशेषताएँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_विस्तृत_उपयोगकर्ता_कहानियाँ&amp;quot;&amp;gt;विस्तृत उपयोगकर्ता कहानियाँ&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel3&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_us1_1_बॉट_की_इनिशियलाइज़ेशन&amp;quot;&amp;gt;US1.1 : बॉट की इनिशियलाइज़ेशन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_us2_1_spotify_की_स्मार्ट_खोज&amp;quot;&amp;gt;US2.1 : Spotify की स्मार्ट खोज&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_us3_1_निष्कर्षण_यूट्यूब_लचीली&amp;quot;&amp;gt;US3.1 : निष्कर्षण यूट्यूब लचीली&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_approche_log_driven_development&amp;quot;&amp;gt;Approche Log Driven Development&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_लॉगिंग_रणनीति&amp;quot;&amp;gt;लॉगिंग रणनीति&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_लॉग्स_की_संरचना&amp;quot;&amp;gt;लॉग्स की संरचना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_exemple_de_log_design&amp;quot;&amp;gt;Exemple de Log Design&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_pydantic_के_साथ_सत्यापन_आर्किटेक्चर&amp;quot;&amp;gt;Pydantic के साथ सत्यापन आर्किटेक्चर&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_डेटा_मॉडल&amp;quot;&amp;gt;डेटा मॉडल&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_कार्यात्मक_त्रुटि_प्रबंधन&amp;quot;&amp;gt;कार्यात्मक त्रुटि प्रबंधन&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_monades_और_error_handling&amp;quot;&amp;gt;Monades और Error Handling&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_प्रतिबंधों_से_बचने_की_रणनीति&amp;quot;&amp;gt;प्रतिबंधों से बचने की रणनीति&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_बहु_स्रोत_दृष्टिकोण&amp;quot;&amp;gt;बहु-स्रोत दृष्टिकोण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_आवर्ती_विकास_योजना&amp;quot;&amp;gt;आवर्ती विकास योजना&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_स्प्रिंट_योजना&amp;quot;&amp;gt;स्प्रिंट योजना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_गुणवत्ता_मेट्रिक्स&amp;quot;&amp;gt;गुणवत्ता मेट्रिक्स&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_तैनाती_और_मॉनिटरिंग&amp;quot;&amp;gt;तैनाती और मॉनिटरिंग&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_उत्पादन_वास्तुकला&amp;quot;&amp;gt;उत्पादन वास्तुकला&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_प्रोएक्टिव_मॉनिटरिंग&amp;quot;&amp;gt;प्रोएक्टिव मॉनिटरिंग&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष_और_संभावनाएँ&amp;quot;&amp;gt;निष्कर्ष और संभावनाएँ&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अगले_चरण&amp;quot;&amp;gt;अगले चरण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिचय&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_परिचय&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Discord बॉट विकसित करने की प्रक्रिया जिसमें Spotify और YouTube APIS का एकीकरण होता है, एक आधुनिक तकनीकी चुनौती पेश करता है, विशेषकर हालिया प्रतिबंधों और प्लेटफ़ॉर्म के विकास के प्रकाश में। यह लेख एक पद्धति-आधारित दृष्टिकोण प्रस्तुत करता है जो के आधार पर&amp;lt;strong&amp;gt;लॉग-आधारित विकास&amp;lt;/strong&amp;gt;(LDD), टेस्ट-चालित विकास का एक विस्तार, फ़ंक्शनल प्रोग्रामिंग पैराडाइम में Python के साथ लागू।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारा लक्ष्य: एक मजबूत, बनाए रखने योग्य और विस्तारशील बॉट बनाना जो वर्तमान संगीत APIs की सीमाओं को नेविगेट कर सके और Discord पर एक सुचारू उपयोगकर्ता अनुभव प्रदान कर सके।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_संदर्भ_और_वर्तमान_चुनौतियाँ&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_संदर्भ_और_वर्तमान_चुनौतियाँ&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;संदर्भ और वर्तमान चुनौतियाँ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_संगीत_apis_का_विकास&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_संगीत_apis_का_विकास&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;संगीत APIs का विकास&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;संगीत प्लेटफ़ॉर्म ने अपनी एक्सेस नीतियों को काफी कड़ा कर दिया है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Spotify&amp;lt;/strong&amp;gt;: मेटाडेटा तक पहुँच पर प्रतिबंध, कोटा सीमा&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;YouTube&amp;lt;/strong&amp;gt;: एंटी-बॉट नीति मजबूत, प्रमाणीकरण की जटिलता&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;विवाद&amp;lt;/strong&amp;gt;: नई सुरक्षा और प्रदर्शन आवश्यकताएँ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_लॉग_चालित_विकास_की_पद्धति&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_लॉग_चालित_विकास_की_पद्धति&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;लॉग-चालित विकास की पद्धति&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;LDD टडी को बढ़ाती है, लॉग्स को विकास के केंद्र में रखकर :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;लॉग्स की परिभाषा&amp;lt;/strong&amp;gt;कार्यान्वयन से पहले&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;अवलोकन द्वारा सत्यापन&amp;lt;/strong&amp;gt;अपेक्षित व्यवहार&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;पूर्ण ट्रेसेबिलिटी&amp;lt;/strong&amp;gt;कुछ डेटा प्रवाह&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;प्रोएक्टिव डिबगिंग&amp;lt;/strong&amp;gt;त्रुटियों की आशा में&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_सैद्धांतिक_वास्तुकला&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_सैद्धांतिक_वास्तुकला&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;सैद्धांतिक वास्तुकला&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-f1d31f810392545930e5846c4a418193.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;777&amp;quot; height=&amp;quot;618&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_स्टैक_तकनीक_और_फ़ंक्शनल_पैराडाइम&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_स्टैक_तकनीक_और_फ़ंक्शनल_पैराडाइम&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;स्टैक तकनीक और फ़ंक्शनल पैराडाइम&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_तकनीकी_विकल्प&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_तकनीकी_विकल्प&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;तकनीकी विकल्प&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारा स्टैक फंक्शनल प्रोग्रामिंग के इर्द-गिर्द घूमता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;PyMonade&amp;lt;/strong&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;साइड इफ़ेक्ट्स का प्रबंधन और फ़ंक्शनों का संयोजन&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Pydantic&amp;lt;/strong&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;टाइप-सेप डेटा मान्यता और सीरियलाइज़ेशन&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Asyncio&amp;lt;/strong&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;असिंक्रोनस प्रोग्रामिंग APIs के लिए&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Structlog&amp;lt;/strong&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;संरचित लॉगिंग LDD के लिए&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_लागू_कार्यात्मक_सिद्धांत&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_लागू_कार्यात्मक_सिद्धांत&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;लागू कार्यात्मक सिद्धांत&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-23984f615f87034b3a75a30579e94d0f.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;690&amp;quot; height=&amp;quot;554&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_agile_पद्धति_और_बैकलॉग&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_agile_पद्धति_और_बैकलॉग&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;Agile पद्धति और बैकलॉग&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_एपिक_मुख्य&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_एपिक_मुख्य&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;एपिक मुख्य&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारा विकास 4 प्रमुख एपिक्स के इर्द-गिर्द आयोजित है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_epic_1_आधारभूत_संरचना_बॉट_discord&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_epic_1_आधारभूत_संरचना_बॉट_discord&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;Epic 1: आधारभूत संरचना बॉट Discord&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;व्यवसाय मूल्य&amp;lt;/strong&amp;gt; : आधार मजबूत और विस्तारयोग्य&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;स्वीकृति मानदंड&amp;lt;/strong&amp;gt; : - स्थिर Discord कनेक्शन, पुनः कनेक्शन प्रबंधन के साथ - मॉड्यूलर कमांड सिस्टम - एकीकृत संरचित लॉगिंग - केंद्रीकृत त्रुटि प्रबंधन&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_epic_2_स्पोटिफ़ाई_का_एकीकरण&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_epic_2_स्पोटिफ़ाई_का_एकीकरण&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;Epic 2 : स्पोटिफ़ाई का एकीकरण&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;व्यवसायिक मूल्य&amp;lt;/strong&amp;gt;: संगीत मेटाडेटा तक पहुंच&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;स्वीकृति मानदंड&amp;lt;/strong&amp;gt; : - सुरक्षित OAuth2 प्रमाणीकरण स्मार्ट कैश के साथ ट्रैक्स की खोज - API कोटा प्रबंधन नेटवर्क त्रुटियों पर फ़ॉलबैक&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_epic_3_youtube_का_एकीकरण&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_epic_3_youtube_का_एकीकरण&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;Epic 3 : YouTube का एकीकरण&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;व्यवसायिक मूल्य&amp;lt;/strong&amp;gt; : ऑडियो सामग्री तक पहुंच&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;स्वीकृति मानक&amp;lt;/strong&amp;gt; : - प्रतिबंधों का क़ानूनी परिहार - अनुकूलित ऑडियो एक्सट्रैक्शन निजी/हटाए गए वीडियो का प्रबंधन - Respect des ToS YouTube&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_epic_4_संगीत_विशेषताएँ&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_epic_4_संगीत_विशेषताएँ&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;Epic 4 : संगीत विशेषताएँ&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;व्यवसाय मूल्य&amp;lt;/strong&amp;gt; : पूर्ण उपयोगकर्ता अनुभव&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;स्वीकृति मानदंड : - उच्च गुणवत्ता ऑडियो लेक्चर - बुद्धिमान पढ़ने की क़्यू - Discord वॉयस कमांड - क्रॉस‑प्लेटफ़ॉर्म सिंक्रोनाइज़ेशन&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_विस्तृत_उपयोगकर्ता_कहानियाँ&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_विस्तृत_उपयोगकर्ता_कहानियाँ&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;विस्तृत उपयोगकर्ता कहानियाँ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_us1_1_बॉट_की_इनिशियलाइज़ेशन&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_us1_1_बॉट_की_इनिशियलाइज़ेशन&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;US1.1 : बॉट की इनिशियलाइज़ेशन&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;जैसे एक&amp;lt;/strong&amp;gt; डेवलपर &amp;lt;strong&amp;gt;मैं चाहता हूँ&amp;lt;/strong&amp;gt; एक डिस्कॉर्ड बॉट जो विश्वसनीय तरीके से जुड़ता है &amp;lt;strong&amp;gt;इसके लिए&amp;lt;/strong&amp;gt; सेवा की उपलब्धता सुनिश्चित करना&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;DoD (पूरा होने की परिभाषा)&amp;lt;/strong&amp;gt; : - [ ] बॉट स्टार्टअप पर स्वचालित रूप से कनेक्ट होता है - [ ] स्ट्रक्चर्ड लॉग प्रत्येक चरण का दस्तावेज़ीकरण करते हैं विच्छेद होने पर स्वचालित पुनर्संयोजन - [ ] एकीकरण परीक्षण पास होते हैं&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_us2_1_spotify_की_स्मार्ट_खोज&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_us2_1_spotify_की_स्मार्ट_खोज&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;US2.1 : Spotify की स्मार्ट खोज&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;के रूप में&amp;lt;/strong&amp;gt; Discord उपयोगकर्ता &amp;lt;strong&amp;gt;मैं&amp;lt;/strong&amp;gt; Spotify के माध्यम से ट्रैक्स खोजना &amp;lt;strong&amp;gt;के लिए&amp;lt;/strong&amp;gt; संगीत खोजने और साझा करने&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;DoD&amp;lt;/strong&amp;gt; : - [ ] आदेश`/search`कार्यात्मक - [ ] प्रासंगिक परिणाम मेटाडेटा के साथ - [ ] अनुरोधों को अनुकूलित करने के लिए स्थानीय कैश - [ ] API त्रुटियों का शालीन प्रबंधन&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_us3_1_निष्कर्षण_यूट्यूब_लचीली&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_us3_1_निष्कर्षण_यूट्यूब_लचीली&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;US3.1 : निष्कर्षण यूट्यूब लचीली&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;के रूप में&amp;lt;/strong&amp;gt; प्रणाली &amp;lt;strong&amp;gt;मैं चाहता हूँ&amp;lt;/strong&amp;gt; यूट्यूब ऑडियो को विश्वसनीय तरीके से निकालना &amp;lt;strong&amp;gt;के लिए&amp;lt;/strong&amp;gt; सेवा की निरंतरता बनाए रखना&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;DoD&amp;lt;/strong&amp;gt; : - [ ] Extraction sans violation des ToS - [ ] इष्टतम ऑडियो गुणवत्ता - [ ] भौगोलिक प्रतिबंधों का प्रबंधन - [ ] ऑपरेशनों के विस्तृत लॉग&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_approche_log_driven_development&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_approche_log_driven_development&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;Approche Log Driven Development&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_लॉगिंग_रणनीति&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_लॉगिंग_रणनीति&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;लॉगिंग रणनीति&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-33bca791609096cfd7cfaef40f1259bd.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;687&amp;quot; height=&amp;quot;633&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_लॉग्स_की_संरचना&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_लॉग्स_की_संरचना&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;लॉग्स की संरचना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारा LDD दृष्टिकोण संरचित लॉग्स का उपयोग करता है जिसमें समान्यात्मक स्तर होते हैं :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;ट्रेस&amp;lt;/strong&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;विस्तृत डेटा प्रवाह&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;डिबग&amp;lt;/strong&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;फ़ंक्शन के आंतरिक स्थितियाँ&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;सूचना&amp;lt;/strong&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;सफल व्यवसाय संचालन&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;चेतावनी&amp;lt;/strong&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;खराब स्थितियाँ लेकिन नियंत्रित&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;त्रुटि&amp;lt;/strong&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;हस्तक्षेप की आवश्यकता वाली त्रुटियाँ&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;(no output)&amp;lt;/strong&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;सिस्टम विफलताएँ&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_exemple_de_log_design&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_exemple_de_log_design&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;Exemple de Log Design&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Spotify की खोज सुविधा को लागू करने से पहले, हम इसके लॉग्स को परिभाषित करते हैं :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-none hljs&amp;quot;&amp;gt;INFO: spotify.search.start query=&amp;quot;bohemian rhapsody&amp;quot; user_id=123456
DEBUG: spotify.search.validation query_length=16 safe_chars=true
DEBUG: spotify.search.api_call endpoint=&amp;quot;/search&amp;quot; params={...}
INFO: spotify.search.success results_count=15 duration_ms=340&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_pydantic_के_साथ_सत्यापन_आर्किटेक्चर&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_pydantic_के_साथ_सत्यापन_आर्किटेक्चर&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;Pydantic के साथ सत्यापन आर्किटेक्चर&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_डेटा_मॉडल&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_डेटा_मॉडल&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;डेटा मॉडल&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारी कार्यात्मक दृष्टिकोण प्रारंभिक सत्यापन को प्राथमिकता देता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-ebd4e1dfbd7b19d5a6054ecf213e9e2d.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;696&amp;quot; height=&amp;quot;339&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_कार्यात्मक_त्रुटि_प्रबंधन&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_कार्यात्मक_त्रुटि_प्रबंधन&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;कार्यात्मक त्रुटि प्रबंधन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_monades_और_error_handling&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_monades_और_error_handling&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;Monades और Error Handling&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;PyMonad का उपयोग करके त्रुटियों का सुंदर प्रबंधन संभव है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-9c75436a1e6a2d62a1bee6a3d76f9c26.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;467&amp;quot; height=&amp;quot;494&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_प्रतिबंधों_से_बचने_की_रणनीति&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_प्रतिबंधों_से_बचने_की_रणनीति&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;प्रतिबंधों से बचने की रणनीति&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_बहु_स्रोत_दृष्टिकोण&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_बहु_स्रोत_दृष्टिकोण&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;बहु-स्रोत दृष्टिकोण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;API प्रतिबंधों के सामने, हम विविधीकरण रणनीति अपनाते हैं:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-22ce201786335de12a3ea5910f11bd8f.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;665&amp;quot; height=&amp;quot;744&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_आवर्ती_विकास_योजना&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_आवर्ती_विकास_योजना&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;आवर्ती विकास योजना&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_स्प्रिंट_योजना&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_स्प्रिंट_योजना&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;स्प्रिंट योजना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारा विकास 2 सप्ताह के स्प्रिंट चक्र का पालन करता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;स्प्रिंट 1-2&amp;lt;/strong&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;इंफ्रास्ट्रक्चर और डिस्कॉर्ड बॉट कोर&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;स्प्रिंट 3-4&amp;lt;/strong&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;Spotify के साथ LDD का एकीकरण&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;स्प्रिंट 5-6&amp;lt;/strong&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;यूट्यूब एकीकरण और परिहार&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;स्प्रिंट 7-8&amp;lt;/strong&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;उन्नत संगीत सुविधाएँ&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;स्प्रिंट 9-10&amp;lt;/strong&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;अनुकूलन और उत्पादन&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_गुणवत्ता_मेट्रिक्स&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_गुणवत्ता_मेट्रिक्स&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;गुणवत्ता मेट्रिक्स&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;प्रत्येक स्प्रिंट का मूल्यांकन :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;लॉग कवरेज&amp;lt;/strong&amp;gt;&amp;amp;gt;90% महत्वपूर्ण पथों&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;API की विश्वसनीयता&amp;lt;/strong&amp;gt;: &amp;amp;lt;1% अप्रबंधित त्रुटियाँ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;प्रदर्शन&amp;lt;/strong&amp;gt;: &amp;amp;lt;500ms औसत प्रतिक्रिया समय&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;रखरखाव क्षमता&amp;lt;/strong&amp;gt;: चक्रीय जटिलता &amp;amp;lt;10&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_तैनाती_और_मॉनिटरिंग&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_तैनाती_और_मॉनिटरिंग&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;तैनाती और मॉनिटरिंग&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_उत्पादन_वास्तुकला&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_उत्पादन_वास्तुकला&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;उत्पादन वास्तुकला&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-4cbca3e909d595589b6e714a88a8217e.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;938&amp;quot; height=&amp;quot;381&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_प्रोएक्टिव_मॉनिटरिंग&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_प्रोएक्टिव_मॉनिटरिंग&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;प्रोएक्टिव मॉनिटरिंग&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;LDD इंटेलिजेंट मॉनिटरिंग को सुगम बनाता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;लॉग पैटर्न पर आधारित अलर्ट&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;व्यवहारिक असामान्यताओं का पता लगाना&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;वास्तविक समय के व्यावसायिक मेट्रिक्स&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;लॉग सहसंबंध द्वारा सहायता प्राप्त डिबगिंग&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष_और_संभावनाएँ&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_निष्कर्ष_और_संभावनाएँ&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;निष्कर्ष और संभावनाएँ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह पद्धतिगत दृष्टिकोण कार्यात्मक प्रतिमान के लाभों को Log Driven Development की मजबूती के साथ जोड़ता है। यह हमें करने देता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;समस्याओं की भविष्यवाणी&amp;lt;/strong&amp;gt;अग्रिम रूप से डिज़ाइन किए गए लॉग्स के कारण&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;गुणवत्ता बनाए रखें&amp;lt;/strong&amp;gt;लगातार मान्यता के माध्यम से&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;जल्दी से अनुकूलित करना&amp;lt;/strong&amp;gt;एपीआई परिवर्तनों के लिए&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;ट्रेसेबिलिटी सुनिश्चित करें&amp;lt;/strong&amp;gt;संचालन का समापन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इटरेटिव विकास और मॉड्यूलर वास्तुकला बदलते संगीत प्लेटफ़ॉर्म की बाधाओं के प्रति स्केलेबिलिटी सुनिश्चित करती हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_अगले_चरण&amp;quot;&amp;gt;&amp;lt;a class=&amp;quot;anchor&amp;quot; href=&amp;quot;#_अगले_चरण&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;अगले चरण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;फ़ेज़ 1&amp;lt;/strong&amp;gt;PyMonade के साथ कोर का कार्यान्वयन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;फ़ेज़ 2&amp;lt;/strong&amp;gt;: Spotify के साथ स्मार्ट कैश का एकीकरण&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;फ़ेज़ 3&amp;lt;/strong&amp;gt;: समाधान YouTube लचीली&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;चरण ४&amp;lt;/strong&amp;gt;: उन्नत सुविधाएँ और अनुकूलन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह मजबूत अवधारणात्मक आधार हमें तकनीकी चुनौतियों से निपटने और एक असाधारण उपयोगकर्ता अनुभव प्रदान करने में सक्षम बनाएगा।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;इस लेख के बाद एक तकनीकी श्रृंखला आएगी जिसमें प्रत्येक घटक के कार्यान्वयन का विस्तृत विवरण दिया जाएगा, कोड उदाहरणों और कार्यात्मक पैटर्न के साथ।&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>अपने लैपटॉप को ठंडा रखें और उबंटू पर तापमान की निगरानी करें</title>
            <link >https://cheroliv.com/blog/2025/0083_cold_computer_post.html</link>
            <pubDate>Tue, 15 Jul 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0083_cold_computer_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table of Contents&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_इस_गाइड_का_उद्देश्य&amp;quot;&amp;gt;इस गाइड का उद्देश्य&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पूर्वापेक्षा&amp;quot;&amp;gt;पूर्वापेक्षा&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_इंस्टॉल_और_कॉन्फ़िगर_करें_उपकरण&amp;quot;&amp;gt;इंस्टॉल और कॉन्फ़िगर करें उपकरण&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_lm_sensors_सेंसरों_का_पता_लगाने_के_लिए&amp;quot;&amp;gt;lm-sensors सेंसरों का पता लगाने के लिए&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_tlp_स्मार्ट_ऊर्जा_प्रबंधक&amp;quot;&amp;gt;tlp` : स्मार्ट ऊर्जा प्रबंधक&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_cpufrequtils_सीपीयू_की_आवृत्तियों_को_सीमित_करना&amp;quot;&amp;gt;cpufrequtils` : सीपीयू की आवृत्तियों को सीमित करना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_auto_cpufreq_सरलीकृत_गतिशील_प्रबंधन&amp;quot;&amp;gt;auto-cpufreq` : सरलीकृत गतिशील प्रबंधन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_thermald_स्वचालित_तापीय_संरक्षण&amp;quot;&amp;gt;thermald` : स्वचालित तापीय संरक्षण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_वास्तविक_समय_में_निगरानी&amp;quot;&amp;gt;वास्तविक समय में निगरानी&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_sensors_कमांड_लाइन_में&amp;quot;&amp;gt;sensors` कमांड लाइन में&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_विकल्प_gui_psensor&amp;quot;&amp;gt;विकल्प GUI : `psensor&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अतिरिक्त_सुझाव&amp;quot;&amp;gt;अतिरिक्त सुझाव&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सिस्टम_को_साफ़_करके_अतिभार_को_सीमित_करना&amp;quot;&amp;gt;सिस्टम को साफ़ करके अतिभार को सीमित करना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ज्यादा_आगे_जाने_के_लिए&amp;quot;&amp;gt;ज्यादा आगे जाने के लिए&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;�📚 निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;क्या आप महसूस करते हैं कि आपका लैपटॉप Ubuntu पर असामान्य रूप से गर्म हो रहा है ? यह लेख आपको एक विधि प्रस्तुत करता है&amp;lt;strong&amp;gt;सॉफ़्टवेयर&amp;lt;/strong&amp;gt;पूरा के लिए&amp;lt;strong&amp;gt;ठंडा करना&amp;lt;/strong&amp;gt;, &amp;lt;strong&amp;gt;निरीक्षण करना&amp;lt;/strong&amp;gt; et &amp;lt;strong&amp;gt;तापमान को नियंत्रित करना&amp;lt;/strong&amp;gt;आपकी मशीन का।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_इस_गाइड_का_उद्देश्य&amp;quot;&amp;gt;इस गाइड का उद्देश्य&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कंप्यूटर की वैश्विक तापमान को कम करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;ऊर्जा प्रबंधन को अनुकूलित करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आलोचनात्मक घटकों (CPU, GPU, आदि) की निगरानी करें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;धीमी गति से बचें&amp;lt;strong&amp;gt;तापीय थ्रॉटलिंग&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;gestion_thermique.svg&amp;quot; alt=&amp;quot;gestion thermique&amp;quot; width=&amp;quot;392&amp;quot; height=&amp;quot;298&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_पूर्वापेक्षा&amp;quot;&amp;gt;पूर्वापेक्षा&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एक Ubuntu मशीन (20.04 या उससे ऊपर अनुशंसित)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;इंटरनेट कनेक्शन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कमांड लाइन दक्षता (प्रारंभिक से मध्यम स्तर)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_इंस्टॉल_और_कॉन्फ़िगर_करें_उपकरण&amp;quot;&amp;gt;इंस्टॉल और कॉन्फ़िगर करें उपकरण&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_lm_sensors_सेंसरों_का_पता_लगाने_के_लिए&amp;quot;&amp;gt;lm-sensors सेंसरों का पता लगाने के लिए&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;sudo apt install lm-sensors
sudo sensors-detect
sensors&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;Note&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जवाब दें`YES`सभी प्रश्नों के लिए`sensors-detect`मॉड्यूल की पहचान करने के लिए&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_tlp_स्मार्ट_ऊर्जा_प्रबंधक&amp;quot;&amp;gt;tlp` : स्मार्ट ऊर्जा प्रबंधक&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;sudo apt install tlp tlp-rdw
sudo systemctl enable tlp
sudo systemctl start tlp&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;tlp_etat.svg&amp;quot; alt=&amp;quot;tlp etat&amp;quot; width=&amp;quot;311&amp;quot; height=&amp;quot;390&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_cpufrequtils_सीपीयू_की_आवृत्तियों_को_सीमित_करना&amp;quot;&amp;gt;cpufrequtils` : सीपीयू की आवृत्तियों को सीमित करना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;sudo apt install cpufrequtils
cpufreq-info
sudo cpufreq-set -g powersave&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;powersave&amp;lt;/code&amp;gt;: आवृत्ति शिखरों को सीमित करता है&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;performance&amp;lt;/code&amp;gt;: शक्ति को प्राथमिकता देता है, तापमान के नुकसान पर&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_auto_cpufreq_सरलीकृत_गतिशील_प्रबंधन&amp;quot;&amp;gt;auto-cpufreq` : सरलीकृत गतिशील प्रबंधन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;git clone https://github.com/AdnanHodzic/auto-cpufreq.git
cd auto-cpufreq
sudo ./auto-cpufreq-installer
sudo auto-cpufreq --install&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;auto_cpufreq_cycle.svg&amp;quot; alt=&amp;quot;auto cpufreq cycle&amp;quot; width=&amp;quot;189&amp;quot; height=&amp;quot;298&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_thermald_स्वचालित_तापीय_संरक्षण&amp;quot;&amp;gt;thermald` : स्वचालित तापीय संरक्षण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;sudo apt install thermald
sudo systemctl enable thermald
sudo systemctl start thermald&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_वास्तविक_समय_में_निगरानी&amp;quot;&amp;gt;वास्तविक समय में निगरानी&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_sensors_कमांड_लाइन_में&amp;quot;&amp;gt;sensors` कमांड लाइन में&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;watch -n 2 sensors&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_विकल्प_gui_psensor&amp;quot;&amp;gt;विकल्प GUI : `psensor&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;sudo apt install psensor&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सरल ग्राफ़िकल इंटरफ़ेस CPU, GPU, पंखों के लिए।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_अतिरिक्त_सुझाव&amp;quot;&amp;gt;अतिरिक्त सुझाव&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;भारी टैब्स और अनुप्रयोग बंद करें (उदा: ब्राउज़र)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;बैटरी पर तीव्र उपयोग से बचें&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;प्रक्रियाओं की निगरानी करना माध्यम से`htop`(No output)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;sudo apt install htop
htop&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_सिस्टम_को_साफ़_करके_अतिभार_को_सीमित_करना&amp;quot;&amp;gt;सिस्टम को साफ़ करके अतिभार को सीमित करना&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash hljs&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;sudo apt autoremove
sudo apt autoclean
sudo journalctl --vacuum-time=3d&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_ज्यादा_आगे_जाने_के_लिए&amp;quot;&amp;gt;ज्यादा आगे जाने के लिए&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आप एक सेवा बना सकते हैं`systemd`स्टार्टअप पर स्वचालित रूप से कुछ सेटिंग्स लागू करने के लिए कस्टम. क्या आप अगले लेख में एक उदाहरण चाहते हैं? मुझे बताइए !&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;�📚 निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इन साधारण उपकरणों को संयोजित करके, आप हासिल करेंगे :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;नियंत्रित CPU तापमान&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कम वेंटिलेशन शोर&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एक बेहतर स्वायत्तता&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपने तापमान को नियमित रूप से निगरानी करना न भूलें, जिससे कोई अतितापन न हो।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;(No output) अपने CPU को पिघलने से रोकना बेहतर है। (No output)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>डिबगिंग की कहानी: बूटस्ट्रैप 5 के साथ फ़ायरफ़ॉक्स की अजीब हरकतों को काबू करना</title>
            <link >https://cheroliv.com/blog/2025/0082_ui_struggle_post.html</link>
            <pubDate>Mon, 14 Jul 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0082_ui_struggle_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_युद्ध_का_मैदान_एक_मॉकअप_तीन_ब्राउज़र_बहुतेरे_रेंडर&amp;quot;&amp;gt;युद्ध का मैदान : एक मॉकअप, तीन ब्राउज़र, बहुतेरे रेंडर&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_1_सेक्शन_hero_की_उड़ती_हुई_कार्ड&amp;quot;&amp;gt;समस्या 1: सेक्शन &amp;quot;Hero&amp;quot; की उड़ती हुई कार्ड&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_2_कैनिबल_नेविगेशन_बार&amp;quot;&amp;gt;समस्या 2 : कैनिबल नेविगेशन बार&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_3_अराजक_टाइपोग्राफी&amp;quot;&amp;gt;समस्या 3: अराजक टाइपोग्राफी&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_4_नेविगेशन_बार_जो_बाहर_निकलती_है&amp;quot;&amp;gt;समस्या 4 : नेविगेशन बार जो बाहर निकलती है&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_5_अदृश्य_हैम्बर्गर_मेनू&amp;quot;&amp;gt;समस्या 5: अदृश्य हैम्बर्गर मेनू&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष_अथक_डिबगिंग_के_सबक&amp;quot;&amp;gt;निष्कर्ष: अथक डिबगिंग के सबक&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock note&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-note&amp;quot; title=&amp;quot;Note&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;पढ़ने का समय :&amp;lt;/strong&amp;gt; लगभग 7 मिनट &amp;lt;strong&amp;gt;स्तर :&amp;lt;/strong&amp;gt; मध्यवर्ती&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस विस्तृत केस स्टडी में, हम ब्राउज़र संगतता की सबसे सामान्य और कभी‑कभी सबसे निराशाजनक समस्याओं का विश्लेषण करेंगे जो Bootstrap 5.2 के साथ UI मॉकअप बनाने के दौरान सामना किए जाते हैं। फ्लेक्सबॉक्स प्रबंधन से लेकर फ़ॉन्ट रेंडरिंग की सूक्ष्मता तक, हमारा डिबगिंग यात्रा देखें कि फायरफ़ॉक्स के तहत एक विकृत डिज़ाइन को कैसे सभी ब्राउज़रों पर पिक्सेल‑परफेक्ट अनुभव में बदलें।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_युद्ध_का_मैदान_एक_मॉकअप_तीन_ब्राउज़र_बहुतेरे_रेंडर&amp;quot;&amp;gt;युद्ध का मैदान : एक मॉकअप, तीन ब्राउज़र, बहुतेरे रेंडर&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हर फ्रंट‑एंड डेवलपर को यह भावना होती है. घंटों की मेहनत के बाद मॉकअप आखिरकार परफेक्ट हो जाती है. संरेखण सटीक होते हैं, टाइपोग्राफी सुंदर होती है, एनिमेशन चिकनी होती हैं. हम संतोष की सांस लेते हैं, अपने काम को क्रोम (या ब्रेव, या एज) पर देखते हैं, फिर सावधानी बरतते हुए प्रोजेक्ट को फ़ायरफ़ॉक्स पर खोलते हैं. और उसी moment पर, आपदा आ जाती है. त element बाहर निकल जाते हैं, संरेखण टूट जाते हैं, फॉन्ट के आकार अव्यवस्थित हो जाते हैं&amp;amp;#8230;&amp;amp;#8203; सुंदर सामंजस्य उड़ जाता है.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह बिल्कुल वही परिदृश्य है जिसका सामना हमने एक नई पोर्टफ़ोलियो इंटरफेस विकसित करते समय किया। ज़रूरतें सरल थीं: एक आधुनिक, उत्तरदायी होम पेज, जिसमें थीम सेलेक्टर (हल्का, गहरा, और उच्च विपरीत), &amp;lt;strong&amp;gt;vanilla JavaScript&amp;lt;/strong&amp;gt; का उपयोग करके और &amp;lt;strong&amp;gt;Bootstrap 5.2&amp;lt;/strong&amp;gt; के नवीनतम संस्करण के साथ।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह लेख चमत्कारिक समाधानों की सूची नहीं है। यह हमारे डिबगिंग सत्र का लॉगबुक है, ब्लिंक (Chromium, Brave) और गेको (Firefox) इंजनों के रेंडरिंग अंतर के &amp;quot;क्यों&amp;quot; में एक गहरा गोता, और यह प्रदर्शित करता है कि मजबूत और आधुनिक समाधान हमेशा जल्दबाजी में लगाए गए पैचों से बेहतर होते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/usecase-debugging-firefox.svg&amp;quot; alt=&amp;quot;usecase debugging firefox&amp;quot; width=&amp;quot;1250&amp;quot; height=&amp;quot;5544&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Figure 1. उपयोग केस आरेख: डिबगिंग प्रक्रिया&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/components-solution-architecture.svg&amp;quot; alt=&amp;quot;components solution architecture&amp;quot; width=&amp;quot;1209&amp;quot; height=&amp;quot;5160&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Figure 2. घटक आरेख: फ्रंट-एंड समाधान की वास्तुकला&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या_1_सेक्शन_hero_की_उड़ती_हुई_कार्ड&amp;quot;&amp;gt;समस्या 1: सेक्शन &amp;quot;Hero&amp;quot; की उड़ती हुई कार्ड&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पहला बग भी सबसे स्पष्ट था. स्वागत अनुभाग (&amp;quot;hero&amp;quot;) दो कॉलम से मिलकर बना है: बायाँ ओर मुख्य शीर्षक; दायाँ ओर एक परिचय कार्ड।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;लक्षण:&amp;lt;/strong&amp;gt;Chrome और Brave पर, दोनों कॉलम लंबवत रूप से पूरी तरह से केंद्रित थे। फ़ायरफ़ॉक्स पर, दायाँ कार्ड अनियमित रूप से बाएँ पाठ के नीचे गिर रहा था।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;जाँच :&amp;lt;/strong&amp;gt;HTML कोड फिर भी सरल और सही लग रहा था, Bootstrap के मानक क्लासेस का उपयोग करके।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html hljs&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;section id=&amp;quot;home&amp;quot; class=&amp;quot;hero-section&amp;quot;&amp;amp;gt;
    &amp;amp;lt;div class=&amp;quot;container&amp;quot;&amp;amp;gt;
        &amp;amp;lt;!-- Cette ligne est la clé du problème --&amp;amp;gt;
        &amp;amp;lt;div class=&amp;quot;row align-items-center min-vh-100&amp;quot;&amp;amp;gt;
            &amp;amp;lt;div class=&amp;quot;col-lg-6&amp;quot;&amp;amp;gt;
                &amp;amp;lt;!-- Contenu de gauche --&amp;amp;gt;
            &amp;amp;lt;/div&amp;amp;gt;
            &amp;amp;lt;div class=&amp;quot;col-lg-6&amp;quot;&amp;amp;gt;
                &amp;amp;lt;!-- Carte de droite --&amp;amp;gt;
            &amp;amp;lt;/div&amp;amp;gt;
        &amp;amp;lt;/div&amp;amp;gt;
    &amp;amp;lt;/div&amp;amp;gt;
&amp;amp;lt;/section&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारा अनुकूलित CSS के लिए`.hero-section`परिभाषित कर रहा था`display: flex` et &amp;lt;code&amp;gt;align-items: center&amp;lt;/code&amp;gt;, और कक्षा`min-vh-100`दिया गया था एक न्यूनतम ऊँचाई पंक्ति को (&amp;lt;code&amp;gt;div.row&amp;lt;/code&amp;gt;). तो फ़ायरफ़ॉक्स ने कॉलम को केंद्रित करने से क्यों इनकार कर दिया ?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;गहरा कारण :&amp;lt;/strong&amp;gt;यह एक पाठ्यपुस्तक उदाहरण है कि रेंडर इंजन निहित ऊँचाइयों की व्याख्या कैसे करते हैं। La`&amp;amp;lt;section&amp;amp;gt;`की एक`min-height`, लेकिन नहीं`height`स्पष्ट. लागू करने के लिए`align-items-center`के भीतर`div.row`, Firefox को इस कंटेनर की संदर्भ ऊंचाई जानने की आवश्यकता है। जैसे उसके माता-पिता (&amp;lt;code&amp;gt;div.container&amp;lt;/code&amp;gt; et la `&amp;amp;lt;section&amp;amp;gt;`खुद) की कोई ऊँचाई नहीं थी&amp;lt;strong&amp;gt;सख्त&amp;lt;/strong&amp;gt;, Firefox खो गया था। Blink इंजन, अधिक उदार, की &amp;quot;deviner&amp;quot; करने की क्षमता रखता है और तत्वों को केंद्रित करने में सक्षम है। Gecko, विनिर्देश के प्रति अधिक पालन करने वाला, ऐसा नहीं करता।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;हल :&amp;lt;/strong&amp;gt;�ऊँचाई स्पष्ट करें। हमने मजबूर किया वह`.container` et le `.row`अपने संबंधित पैरेंट की 100% ऊँचाई लेने के लिए यूटिलिटी क्लास का उपयोग करना`h-100`Bootstrap का&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html hljs&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;section id=&amp;quot;home&amp;quot; class=&amp;quot;hero-section&amp;quot;&amp;amp;gt;
    &amp;amp;lt;div class=&amp;quot;container h-100&amp;quot;&amp;amp;gt;
        &amp;amp;lt;div class=&amp;quot;row align-items-center min-vh-100 h-100&amp;quot;&amp;amp;gt;
            &amp;amp;lt;!-- ... --&amp;amp;gt;
        &amp;amp;lt;/div&amp;amp;gt;
    &amp;amp;lt;/div&amp;amp;gt;
&amp;amp;lt;/section&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock tip&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-tip&amp;quot; title=&amp;quot;Tip&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जब एक`align-items`Flexbox लंबवत अक्ष पर अपेक्षा के अनुसार काम नहीं करता, हमेशा सुनिश्चित करें कि कंटेनर में एक ऊँचाई है (&amp;lt;code&amp;gt;height&amp;lt;/code&amp;gt; ou &amp;lt;code&amp;gt;min-height&amp;lt;/code&amp;gt;) परिभाषित और, यदि समस्या बनी रहती है (विशेषकर Firefox पर), सुनिश्चित करें कि मध्यवर्ती मातृ कंटेनर इस ऊँचाई को अच्छी तरह से प्रसारित करते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या_2_कैनिबल_नेविगेशन_बार&amp;quot;&amp;gt;समस्या 2 : कैनिबल नेविगेशन बार&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;हीरो सेक्शन संरेखित होने के बाद, एक और समस्या सामने आई: नेविगेशन बार, जिसमें उसका वर्ग है`fixed-top`, शीर्षक पर आच्छादित हो रहा था. एक`padding-top: 80px`सेक्शन &amp;#39;Hero&amp;#39; पर समाधान के रूप में लागू किया गया था।&amp;lt;/div&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;लक्षण :&amp;lt;/strong&amp;gt; Le `padding`यह क्रोम पर पर्याप्त था, लेकिन फायरफ़ॉक्स पर नहीं, जहाँ शीर्षक हमेशा आंशिक रूप से छिपा रहता था।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;गहरा कारण:&amp;lt;/strong&amp;gt;एक &amp;quot;जादुई संख्या&amp;quot; का उपयोग (&amp;lt;code&amp;gt;80px&amp;lt;/code&amp;gt;) यह एक बहुत खराब अभ्यास है। एक तत्व की ऊँचाई, जैसे कि नेविगेशन बार, कुछ पिक्सेल तक एक ब्राउज़र से दूसरे ब्राउज़र में बदल सकती है, क्योंकि फ़ॉन्ट रेंडरिंग, स्पेसिंग या उपयोगकर्ता विकल्पों में सूक्ष्म अंतर होते हैं। एक स्थिर मान पर निर्भर रहना एक नाज़ुक डिज़ाइन की रेसिपी है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;समाधान:&amp;lt;/strong&amp;gt;JavaScript में एक गतिशील और अनफ़ेलिबल समाधान। हमने एक छोटा स्क्रिप्ट लिखा:&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;पेज के रेंडर होने के बाद नेविगेशन बार की &amp;lt;strong&amp;gt;वास्तविक&amp;lt;/strong&amp;gt; ऊँचाई मापें।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;इस मापी हुई ऊँचाई को लागू करें`padding-top`Hero&amp;quot; सेक्शन में&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;इस फ़ंक्शन को हर बार विंडो के आकार बदलने पर फिर से चलाएँ ताकि बदलावों के अनुकूल बनाया जा सके (जैसे हैमबर्गर मेन्यू में स्विच करना).&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript hljs&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, function() {
    function adjustHeroPadding() {
        const navbar = document.querySelector(&amp;#39;.navbar.fixed-top&amp;#39;);
        const heroSection = document.querySelector(&amp;#39;.hero-section&amp;#39;);

        if (navbar &amp;amp;amp;&amp;amp;amp; heroSection) {
            const navbarHeight = navbar.offsetHeight;
            heroSection.style.paddingTop = navbarHeight + &amp;#39;px&amp;#39;;
        }
    }

    // Ajuster au chargement et au redimensionnement
    adjustHeroPadding();
    window.addEventListener(&amp;#39;resize&amp;#39;, adjustHeroPadding);
});&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/sequence-dynamic-padding.svg&amp;quot; alt=&amp;quot;sequence dynamic padding&amp;quot; width=&amp;quot;887&amp;quot; height=&amp;quot;703&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Figure 3. अनुक्रम आरेख: पैडिंग का गतिशील समायोजन&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;समांतर में, हमने बेशक नियम हटा दिया`padding-top: 80px;`हमारी फ़ाइल का`styles.css`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या_3_अराजक_टाइपोग्राफी&amp;quot;&amp;gt;समस्या 3: अराजक टाइपोग्राफी&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;आगामी चिंता ब्रांड छवि के लिए सबसे अधिक हानिकारक थी: मुख्य शीर्षक का आकार।&amp;lt;/div&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;लक्षण :&amp;lt;/strong&amp;gt;फ़ायरफ़ॉक्स पर, &amp;quot;Développeur Formateur&amp;amp;#8230;&amp;amp;#8203;&amp;quot; शीर्षक का फ़ॉन्ट विशाल था, लगभग चौंकाने वाला, जबकि यह अन्य ब्राउज़र पर सामंजस्यपूर्ण थी।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;गहरा कारण :&amp;lt;/strong&amp;gt;शीर्षक ने एक क्लास का उपयोग किया`display-4`बूटस्ट्रैप का ये कक्षाएं प्रतिक्रियाशील फॉन्ट आकार का उपयोग करती हैं, जो अक्सर इकाई पर आधारित होती हैं`rem`फिर से, फ़ायरफ़ॉक्स का रेंडरिंग एल्गोरिदम, &amp;quot;Inter&amp;quot; फ़ॉन्ट के साथ संयुक्त, हमारे 1920x1080 रिज़ॉल्यूशन पर आकार की बहुत बड़ी गणना हो रही थी।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;समाधान:&amp;lt;/strong&amp;gt;CSS फ़ंक्शन के साथ नियंत्रण पुनः प्राप्त करें`clamp()&amp;lt;code&amp;gt;. यह सुविधा सुचारू टाइपोग्राफी के लिए एक क्रांति है। यह आपको तीन मानों के साथ एक फ़ॉन्ट आकार निर्धारित करने की अनुमति देता है: एक न्यूनतम आकार, एक &amp;quot;préférée&amp;quot; आकार (जो दृश्य की चौड़ाई के अनुसार अनुकूलित होता है,`vw&amp;lt;/code&amp;gt;), और एक अधिकतम आकार।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-css hljs&amp;quot; data-lang=&amp;quot;css&amp;quot;&amp;gt;.hero-content h1 {
    color: var(--text-primary);
    line-height: 1.2;
    /*
       Min: 2rem
       Préférée: s&amp;#39;adapte à la vue
       Max: 2.5rem (40px)
    */
    font-size: clamp(2rem, 1.2rem + 1.5vw, 2.5rem);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;के साथ`clamp()&amp;lt;code&amp;gt;, हम ब्राउज़र से कह सके: &amp;quot;स्क्रीन के साथ फ़ॉन्ट बढ़ाएँ, लेकिन अधिक नहीं&amp;lt;strong&amp;gt;कभी नहीं&amp;lt;/strong&amp;gt;सीमा का`2.5rem&amp;lt;/code&amp;gt;. इसने सभी ब्राउज़रों पर रेंडरिंग को तुरंत समायोजित कर दिया, जिससे हमें अंतिम दिखावट पर पूर्ण नियंत्रण मिल गया।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या_4_नेविगेशन_बार_जो_बाहर_निकलती_है&amp;quot;&amp;gt;समस्या 4 : नेविगेशन बार जो बाहर निकलती है&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;यह वही समस्या है जिसने हमें सबसे अधिक परेशानी दी और अंततः रेंडरिंग के सूक्ष्म अंतरों की गहरी प्रकृति को प्रकट किया।&amp;lt;/div&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;लक्षण:&amp;lt;/strong&amp;gt;1920x1080 स्क्रीन पर, मेनू के अंतिम लिंक (&amp;quot;Blog&amp;quot;, &amp;quot;Contact&amp;quot;) स्क्रीन के दाहिनी ओर धकेल दिए गए थे, लेकिन केवल फ़ायरफ़ॉक्स पर.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;गहरा कारण:&amp;lt;/strong&amp;gt;कई असफल प्रयासों के बाद (बूटस्ट्रैप के ब्रेकपॉइंट्स बदलने`lg` à &amp;lt;code&amp;gt;xl`फिर`xxl&amp;lt;/code&amp;gt;) हमने समझा। कारण बूटस्ट्रैप की लॉजिक नहीं थी, बल्कि सरल चौड़ाई की गणना थी। फ़ायरफ़ॉक्स पर, सभी लिंक की चौड़ाइयों का योग, उनके शामिल`padding` et `margin`sub-pixel के स्तर तक, यह &amp;lt;strong&amp;gt;légèrement&amp;lt;/strong&amp;gt; 1920 पिक्सेल से अधिक थी। Chrome पर, यही समान योग &amp;lt;strong&amp;gt;légèrement&amp;lt;/strong&amp;gt; कम थी। हमें कुछ पिक्सेल की कमी थी।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;समाधान:&amp;lt;/strong&amp;gt;एक सर्जिकल स्तर के अंतराल में कमी। क्योंकि फ़ायरफ़ॉक्स को विशेष रूप से लक्षित करना पुराने CSS &amp;amp;#8220;hacks&amp;amp;#8221; के साथ बाहर के सवाल में था, एकमात्र समाधान एक सामान्य शैली खोजने का था जो हर जगह काम करती। हमने इसलिए प्रत्येक नेविगेशन लिंक के क्षैतिज मार्जिन और पैडिंग को थोड़ा कम कर दिया।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-css hljs&amp;quot; data-lang=&amp;quot;css&amp;quot;&amp;gt;/* La version finale, légèrement plus compacte */
.navbar-nav .nav-link {
    font-size: 0.9rem; /* 90% de la taille de base */
    color: var(--text-primary) !important;
    font-weight: 500;
    margin: 0 0.2rem;
    padding: 0.5rem 0.5rem !important;
    border-radius: 0.375rem;
    transition: all 0.3s ease;
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह कमी, एकल तत्व पर नग्न आँख से लगभग अदृश्य, हमें सामूहिक रूप से आवश्यक स्थान प्रदान कर दिया जिससे कि सभी लिंक फ़ायरफ़ॉक्स के फ्रेम में आ जाएँ, जबकि अन्य ब्राउज़र पर लगभग समान दिखावट बनी रहे।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या_5_अदृश्य_हैम्बर्गर_मेनू&amp;quot;&amp;gt;समस्या 5: अदृश्य हैम्बर्गर मेनू&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अंतिम समस्या, और कम नहीं थी, मोबाइल एक्सेसिबिलिटी से संबंधित थी।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;लक्षण :&amp;lt;/strong&amp;gt;रिस्पॉन्सिव मोड (मेनू &amp;quot;hamburger&amp;quot;) में, मेनू का आइकॉन थीम &amp;quot;dark&amp;quot; और &amp;quot;high-contrast&amp;quot; पर अदृश्य था।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;गहरा कारण :&amp;lt;/strong&amp;gt;Bootstrap 5 का मेनू आइकन एक`background-image`(एक URL में एन्कोड किया गया SVG)। डिफ़ॉल्ट रूप से, इसकी रेखा का रंग गहरा होता है, हल्के पृष्ठभूमि के लिए अनुकूलित। यह थीम परिवर्तन के अनुसार स्वचालित रूप से अनुकूल नहीं होती।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;समाधान :&amp;lt;/strong&amp;gt;Bootstrap के CSS चर का उपयोग करके आइकन को ओवरराइड करें। हमने एक नया SVG आइकन निर्धारित किया, लेकिन इस बार एक सफेद स्ट्रोक के साथ।&amp;lt;code&amp;gt;#ffffff&amp;lt;/code&amp;gt;), और हमने इसे विशेष रूप से लागू किया जब विषय`dark` ou `high-contrast`वे सक्रिय हैं।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-css hljs&amp;quot; data-lang=&amp;quot;css&amp;quot;&amp;gt;/* ======================
   Fix pour l&amp;#39;icône du menu Burger (Blanc)
   ====================== */
[data-bs-theme=&amp;quot;dark&amp;quot;] .navbar-toggler-icon,
[data-bs-theme=&amp;quot;high-contrast&amp;quot;] .navbar-toggler-icon {
    --bs-navbar-toggler-icon-bg: url(&amp;quot;data:image/svg+xml,%3csvg xmlns=&amp;#39;http://www.w3.org/2000/svg&amp;#39; viewBox=&amp;#39;0 0 30 30&amp;#39;%3e%3cpath stroke=&amp;#39;%23ffffff&amp;#39; stroke-linecap=&amp;#39;round&amp;#39; stroke-miterlimit=&amp;#39;10&amp;#39; stroke-width=&amp;#39;2&amp;#39; d=&amp;#39;M4 7h22M4 15h22M4 23h22&amp;#39;/%3e%3c/svg%3e&amp;quot;);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock important&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-important&amp;quot; title=&amp;quot;Important&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;बूटस्ट्रैप घटकों जैसे इस का अनुकूलन अब CSS चर के ओवरराइड के माध्यम से बढ़ता जा रहा है (&amp;lt;code&amp;gt;--bs-component-property&amp;lt;/code&amp;gt;), qui est la méthode la plus propre et la plus pérenne.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष_अथक_डिबगिंग_के_सबक&amp;quot;&amp;gt;निष्कर्ष: अथक डिबगिंग के सबक&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह यात्रा, हालांकि कभी‑कभी निराशाजनक होती है, सीखों से भरपूर है। हर हल की गई समस्या वेब विकास के एक मौलिक सत्य को मजबूत करती है :&amp;lt;strong&amp;gt;कुछ भी एक कठोर बहु-ब्राउज़र परीक्षण का विकल्प नहीं है&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/mindmap-debugging-summary.svg&amp;quot; alt=&amp;quot;mindmap debugging summary&amp;quot; width=&amp;quot;999&amp;quot; height=&amp;quot;866&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Figure 4. Mindmap : डीबगिंग का सारांश और सीखे गए सबक&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;ये हैं सीख जो हमने रखी हैं :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Firefox एक सहयोगी है :&amp;lt;/strong&amp;gt;इसकी CSS मानकों के प्रति सबसे बड़ी वफ़ादारी हमें अधिक मजबूत और कम अस्पष्ट कोड लिखने के लिए मजबूर करती है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;जादुई संख्याओं से बचें :&amp;lt;/strong&amp;gt;स्थिर मान (जैसे`padding-top: 80px`) समय bombs हैं। हमेशा गतिशील समाधानों को प्राथमिकता दें या सापेक्ष (Flexbox, Grid)।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;अपनी टाइपोग्राफी को मास्टर करें:&amp;lt;/strong&amp;gt;इस्तेमाल करें`clamp()`अनुकूलन योग्य फ़ॉन्ट के आकार पर पूर्ण नियंत्रण रखने के लिए।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;घटक के रूप में सोचें:&amp;lt;/strong&amp;gt;बूटस्ट्रैप को अनुकूलित करने के लिए, उसके CSS चरों को ओवरराइड करें, बजाय फ्रेमवर्क को ओवरराइट करने वाले नियमों को गुणा करने के।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;एक ब्राउज़र मत लक्ष्य कीजिए:&amp;lt;/strong&amp;gt;समाधान लगभग कभी भी किसी विशिष्ट ब्राउज़र के लिए &amp;quot;hack&amp;quot; करने का नहीं होता, बल्कि एक सामान्य शैली खोजने का होती है जो हर जगह काम करती है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अंत में, मॉकअप अब मजबूत, पूर्वानुमान योग्य और टेम्प्लेटिंग सिस्टम में एकीकृत होने के लिए तैयार है। प्रत्येक ठीक किया गया बग असफलता नहीं था, बल्कि बेहतर गुणवत्ता वाले कोड की ओर एक कदम था।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>gradle.properties` के साथ Gradle यूनिट टेस्टिंग चुनौती को सुलझाएँ</title>
            <link >https://cheroliv.com/blog/2025/0081_TDD_Gradle_Properties_Fix_post.html</link>
            <pubDate>Sun, 13 Jul 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0081_TDD_Gradle_Properties_Fix_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_gradle_प्लगिन_के_यूनिट_टेस्ट्स_को_अलग_करना&amp;quot;&amp;gt;समस्या: Gradle प्लगिन के यूनिट टेस्ट्स को अलग करना&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_की_वास्तुकला&amp;quot;&amp;gt;समस्या की वास्तुकला&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_एक_गलत_अच्छे_विचार_की_आकर्षण&amp;quot;&amp;gt;एक गलत अच्छे विचार की आकर्षण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समाधान_संपत्ति_का_सिमुलेट_extrapropertiesextension_के_साथ&amp;quot;&amp;gt;समाधान: संपत्ति का सिमुलेट &amp;lt;code&amp;gt;ExtraPropertiesExtension&amp;lt;/code&amp;gt; के साथ&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_1_extrapropertiesextension_को_समझें&amp;quot;&amp;gt;चरण 1 : ExtraPropertiesExtension को समझें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_2_परीक्षण_की_व्यवस्था_तैयारी&amp;quot;&amp;gt;चरण 2 : परीक्षण की व्यवस्था - तैयारी&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_3_संपत्ति_का_इंजेक्शन&amp;quot;&amp;gt;चरण 3 : संपत्ति का इंजेक्शन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_4_समाधान_प्रवाह_आरेख&amp;quot;&amp;gt;चरण 4: समाधान प्रवाह आरेख&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_5_पहलेपश्चात_तुलना&amp;quot;&amp;gt;चरण 5: पहले/पश्चात तुलना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_6_कई_टेस्ट_केसों_का_प्रबंधन&amp;quot;&amp;gt;चरण 6: कई टेस्ट केसों का प्रबंधन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समाधान_का_अंतिम_वास्तुकला&amp;quot;&amp;gt;समाधान का अंतिम वास्तुकला&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_इस_दृष्टिकोण_के_लाभ&amp;quot;&amp;gt;इस दृष्टिकोण के लाभ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अच्छे_अभ्यास_और_सलाह&amp;quot;&amp;gt;अच्छे अभ्यास और सलाह&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_एक_उपयोगिता_विधि_बनाएँ&amp;quot;&amp;gt;एक उपयोगिता विधि बनाएँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_गुणों_की_पुष्टि&amp;quot;&amp;gt;गुणों की पुष्टि&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या_gradle_प्लगिन_के_यूनिट_टेस्ट्स_को_अलग_करना&amp;quot;&amp;gt;समस्या: Gradle प्लगिन के यूनिट टेस्ट्स को अलग करना&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Gradle प्लगिन के लिए यूनिट परीक्षण लिखते समय, एक सामान्य चुनौती प्रोजेक्ट की कॉन्फ़िगरेशन के अनुसार निर्भरताओं को प्रबंधित करने की है, जैसी फ़ाइल में परिभाषित गुण`gradle.properties`. हमारे केस में, प्लगइन`jbake.ghpages`एक संपत्ति पढ़नी थी`site_config_path`सही ढंग से काम करने के लिए. कार्य के लिए यूनिट परीक्षण`initialize`प्लगइन के व्यवहार की जाँचना इस संपत्ति की उपस्थिति में करनी चाहिए थी।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मूल समस्या यह है कि यूनिट टेस्ट, डिज़ाइन द्वारा, &amp;lt;strong&amp;gt;इसोलेटेड&amp;lt;/strong&amp;gt; होने चाहिए। का उपयोग`ProjectBuilder`Gradle का एक उदाहरण बनाता है`Project`मेमोरी में, फ़ाइल सिस्टम पर एक वास्तविक प्रोजेक्ट से पूरी तरह डिस्कनेक्टेड। इसलिए, इस टेस्ट इंस्टेंस द्वारा फ़ाइल को स्वचालित रूप से नहीं पढ़ा जाता।&amp;lt;code&amp;gt;gradle.properties`और इसलिए संपत्ति की जानकारी नहीं है`site_config_path&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_समस्या_की_वास्तुकला&amp;quot;&amp;gt;समस्या की वास्तुकला&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;निम्नलिखित आरेख परीक्षण वातावरण और फ़ाइल सिस्टम के बीच के असंपर्क को दर्शाता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/test-isolation-problem.svg&amp;quot; alt=&amp;quot;test isolation problem&amp;quot; width=&amp;quot;1192&amp;quot; height=&amp;quot;5799&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_एक_गलत_अच्छे_विचार_की_आकर्षण&amp;quot;&amp;gt;एक गलत अच्छे विचार की आकर्षण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक पहला दृष्टिकोण हो सकता है कि एक फ़ाइल बनाई जाए`gradle.properties`फर्जी परीक्षण संसाधनों में।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;// src/test/resources/gradle.properties
site_config_path=src/jbake/settings/site.yml&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हालाँकि, यह विधि विफल होने के लिए नियत है क्योंकि`ProjectBuilder`यह फ़ाइल सिस्टम को कॉन्फ़िगरेशन फ़ाइलों की खोज के लिए स्कैन करने के लिए डिज़ाइन नहीं किया गया है। परीक्षण अलग-थलग रहेगा और इस फ़ाइल को अनदेखा कर देगा।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समाधान_संपत्ति_का_सिमुलेट_extrapropertiesextension_के_साथ&amp;quot;&amp;gt;समाधान: संपत्ति का सिमुलेट &amp;lt;code&amp;gt;ExtraPropertiesExtension&amp;lt;/code&amp;gt; के साथ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस समस्या का शानदार समाधान फ़ाइल को &amp;lt;strong&amp;gt;lire&amp;lt;/strong&amp;gt; करने से नहीं है, बल्कि ऑब्जेक्ट में संपत्ति की उपस्थिति को &amp;lt;strong&amp;gt;simuler&amp;lt;/strong&amp;gt; करने से है`Project`टेस्ट। Gradle इसके लिए एक शक्तिशाली तंत्र प्रदान करता है : &amp;lt;strong&amp;gt;अतिरिक्त गुण&amp;lt;/strong&amp;gt; (Extra Properties).&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_चरण_1_extrapropertiesextension_को_समझें&amp;quot;&amp;gt;चरण 1 : ExtraPropertiesExtension को समझें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;`ExtraPropertiesExtension`यह Gradle मॉडल के प्रत्येक ऑब्जेक्ट से जुड़ा एक कुंजी-मूल्य कंटेनर है। यह परियोजना, किसी कार्य, या किसी अन्य Gradle एक्सटेंशन में गतिशील रूप से गुण जोड़ने की अनुमति देता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/extra-properties-architecture.svg&amp;quot; alt=&amp;quot;extra properties architecture&amp;quot; width=&amp;quot;533&amp;quot; height=&amp;quot;436&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_चरण_2_परीक्षण_की_व्यवस्था_तैयारी&amp;quot;&amp;gt;चरण 2 : परीक्षण की व्यवस्था - तैयारी&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आइए, हम अपने यूनिट टेस्ट की बुनियादी संरचना बनाना शुरू करते हैं :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;JbakeGhPagesPluginTest.kt - Structure de base&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;class JbakeGhPagesPluginTest {

    @TempDir
    lateinit var testProjectDir: File

    @Test
    fun `check initialize and config yaml file if not existing`() {
        // Étape 1 : Créer un projet de test isolé
        val project = ProjectBuilder.builder()
            .withProjectDir(testProjectDir)
            .build()

        // Suite des étapes...
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_चरण_3_संपत्ति_का_इंजेक्शन&amp;quot;&amp;gt;चरण 3 : संपत्ति का इंजेक्शन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह परियोजना में संपत्ति इंजेक्ट करने के लिए विस्तृत प्रक्रिया है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;JbakeGhPagesPluginTest.kt - Injection complète&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;@Test
fun `check initialize and config yaml file if not existing`() {
    // Étape 1 : Créer un projet de test isolé en mémoire
    val project = ProjectBuilder.builder()
        .withProjectDir(testProjectDir)
        .build()

    // Étape 2 : Récupérer le gestionnaire de propriétés supplémentaires
    val extra = project.extensions.getByType(ExtraPropertiesExtension::class.java)

    // Étape 3 : Définir la propriété requise pour ce test
    extra.set(&amp;quot;site_config_path&amp;quot;, &amp;quot;src/jbake/settings/site.yml&amp;quot;)

    // Étape 4 : Vérifier que la propriété est bien injectée
    assertTrue(project.hasProperty(&amp;quot;site_config_path&amp;quot;))

    // Étape 5 : Appliquer le plugin qui pourra maintenant accéder à la propriété
    project.plugins.apply(&amp;quot;jbake.ghpages&amp;quot;)

    // Étape 6 : Exécuter la tâche et vérifier son comportement
    val task: Task = project.tasks.findByName(&amp;quot;initialize&amp;quot;)
        .apply(::assertNotNull)!!

    // Étape 7 : Exécuter les actions de la tâche
    task.actions.forEach { it.execute(task) }

    // Étape 8 : Assertions finales
    assertEquals(
        &amp;quot;src/jbake/settings/site.yml&amp;quot;,
        project.properties[&amp;quot;site_config_path&amp;quot;],
        &amp;quot;La propriété devrait être accessible dans le projet&amp;quot;
    )
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_चरण_4_समाधान_प्रवाह_आरेख&amp;quot;&amp;gt;चरण 4: समाधान प्रवाह आरेख&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/solution-flow.svg&amp;quot; alt=&amp;quot;solution flow&amp;quot; width=&amp;quot;242&amp;quot; height=&amp;quot;807&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_चरण_5_पहलेपश्चात_तुलना&amp;quot;&amp;gt;चरण 5: पहले/पश्चात तुलना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/before-after-comparison.svg&amp;quot; alt=&amp;quot;before after comparison&amp;quot; width=&amp;quot;1202&amp;quot; height=&amp;quot;5771&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_चरण_6_कई_टेस्ट_केसों_का_प्रबंधन&amp;quot;&amp;gt;चरण 6: कई टेस्ट केसों का प्रबंधन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;विभिन्न परिदृश्यों का परीक्षण करने के लिए, विभिन्न कॉन्फ़िगरेशन के साथ कई परीक्षण बनाइए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Tests multiples avec configurations différentes&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;class JbakeGhPagesPluginTest {

    @TempDir
    lateinit var testProjectDir: File

    private fun createProjectWithProperty(propertyValue: String?): Project {
        val project = ProjectBuilder.builder()
            .withProjectDir(testProjectDir)
            .build()

        // Injection conditionnelle de la propriété
        propertyValue?.let { value -&amp;amp;gt;
            val extra = project.extensions.getByType(ExtraPropertiesExtension::class.java)
            extra.set(&amp;quot;site_config_path&amp;quot;, value)
        }

        return project
    }

    @Test
    fun `should work with valid property`() {
        val project = createProjectWithProperty(&amp;quot;src/jbake/settings/site.yml&amp;quot;)
        project.plugins.apply(&amp;quot;jbake.ghpages&amp;quot;)

        val task = project.tasks.findByName(&amp;quot;initialize&amp;quot;)!!
        task.actions.forEach { it.execute(task) }

        // Assertions pour le cas normal
        assertEquals(&amp;quot;src/jbake/settings/site.yml&amp;quot;, project.properties[&amp;quot;site_config_path&amp;quot;])
    }

    @Test
    fun `should handle missing property gracefully`() {
        val project = createProjectWithProperty(null) // Pas de propriété
        project.plugins.apply(&amp;quot;jbake.ghpages&amp;quot;)

        val task = project.tasks.findByName(&amp;quot;initialize&amp;quot;)!!

        // Le plugin devrait gérer l&amp;#39;absence de propriété
        assertDoesNotThrow {
            task.actions.forEach { it.execute(task) }
        }
    }

    @Test
    fun `should handle invalid property path`() {
        val project = createProjectWithProperty(&amp;quot;invalid/path/to/config.yml&amp;quot;)
        project.plugins.apply(&amp;quot;jbake.ghpages&amp;quot;)

        val task = project.tasks.findByName(&amp;quot;initialize&amp;quot;)!!

        // Test du comportement avec un chemin invalide
        assertThrows&amp;amp;lt;FileNotFoundException&amp;amp;gt; {
            task.actions.forEach { it.execute(task) }
        }
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_समाधान_का_अंतिम_वास्तुकला&amp;quot;&amp;gt;समाधान का अंतिम वास्तुकला&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/final-architecture.svg&amp;quot; alt=&amp;quot;final architecture&amp;quot; width=&amp;quot;1204&amp;quot; height=&amp;quot;5851&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_इस_दृष्टिकोण_के_लाभ&amp;quot;&amp;gt;इस दृष्टिकोण के लाभ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;पूर्ण पृथक्करण&amp;lt;/strong&amp;gt;परीक्षण किसी बाहरी फ़ाइल पर निर्भर नहीं है। यह स्वतंत्र है और किसी भी पर्यावरण (स्थानीय, CI/CD आदि) में विश्वसनीय रूप से चलाया जा सकता है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;स्पष्टता और इरादा&amp;lt;/strong&amp;gt;परीक्षण स्पष्ट रूप से अपने निष्पादन के लिए पूर्व शर्तों की घोषणा करता है। जो कोई भी परीक्षण पढ़ता है, वह तुरंत देखता है कि प्लगिन को संपत्ति की आवश्यकता होती है।`site_config_path`चलने के लिए.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;रखरखावीयता&amp;lt;/strong&amp;gt;: यदि संपत्ति का नाम बदलता है, तो बस परीक्षण में एक स्थान पर इसे अपडेट करना पर्याप्त है, परीक्षण कॉन्फ़िगरेशन फ़ाइलों को संशोधित किए बिना।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;लचीलापन&amp;lt;/strong&amp;gt;परीक्षण करना बहुत आसान हो जाता है विभिन्न परिदृश्यों का, क्योंकि प्रत्येक परीक्षण में इंजेक्ट की गई संपत्ति के मान को बस बदल दिया जाता है (वैध मान, अमान्य मान, अनुपस्थित, आदि)।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;प्रदर्शन&amp;lt;/strong&amp;gt;: फ़ाइलों की कोई पढ़ाई नहीं, सब मेमोरी में होता है, जो परीक्षणों को तेज़ बनाता है.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;पुनरावृत्ति&amp;lt;/strong&amp;gt;परीक्षण निर्धारित हैं क्योंकि वे फ़ाइल सिस्टम की स्थिति पर निर्भर नहीं करते।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_अच्छे_अभ्यास_और_सलाह&amp;quot;&amp;gt;अच्छे अभ्यास और सलाह&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_एक_उपयोगिता_विधि_बनाएँ&amp;quot;&amp;gt;एक उपयोगिता विधि बनाएँ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Méthode utilitaire pour la réutilisation&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;class GradleTestUtils {
    companion object {
        fun createProjectWithProperties(
            projectDir: File,
            properties: Map&amp;amp;lt;String, String&amp;amp;gt;
        ): Project {
            val project = ProjectBuilder.builder()
                .withProjectDir(projectDir)
                .build()

            val extra = project.extensions.getByType(ExtraPropertiesExtension::class.java)
            properties.forEach { (key, value) -&amp;amp;gt;
                extra.set(key, value)
            }

            return project
        }
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_गुणों_की_पुष्टि&amp;quot;&amp;gt;गुणों की पुष्टि&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;Validation robuste&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;@Test
fun `should validate property injection`() {
    val project = createProjectWithProperty(&amp;quot;test-value&amp;quot;)

    // Vérifications multiples
    assertTrue(project.hasProperty(&amp;quot;site_config_path&amp;quot;))
    assertEquals(&amp;quot;test-value&amp;quot;, project.property(&amp;quot;site_config_path&amp;quot;))
    assertNotNull(project.properties[&amp;quot;site_config_path&amp;quot;])

    // Vérification que la propriété est accessible par le plugin
    project.plugins.apply(&amp;quot;jbake.ghpages&amp;quot;)
    // ... reste du test
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यूनिट परीक्षण वातावरण के लिए कॉन्फ़िगरेशन फ़ाइलें पढ़ने के लिए संघर्ष करने के बजाय, सर्वोत्तम अभ्यास आवश्यक स्थिति को अनुकरण करने से बना है। का उपयोग`ExtraPropertiesExtension`ग्रैडल गुणों को प्रोग्रामेटिक रूप से परिभाषित करने की विधि प्रभावी और विश्वसनीय प्लगइन यूनिट परीक्षण करने के लिए सबसे स्वच्छ और सबसे मजबूत तरीका है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह तकनीक एक बाह्य निर्भरता समस्या को एक सरल निर्भरता इंजेक्शन में बदल देती है, जो टेस्ट-ड्रिवन डेवलपमेंट (TDD) के दर्शन के मूल में होती है। यह परीक्षण पर्यावरण पर पूर्ण नियंत्रण प्रदान करती है जबकि उच्च गुणवत्ता वाले यूनिट परीक्षण के लिए आवश्यक अलगाव को बनाए रखती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस लेख में प्रस्तुत आरेख और उदाहरण दिखाते हैं कि इस दृष्टिकोण को कैसे चरणबद्ध और प्रणालीगत तरीके से लागू किया जा सकता है, जिससे आपके Gradle प्लगइन के लिए एक मजबूत और बनाए रखने योग्य टेस्ट सूट बनाया जा सकता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Gradle कार्य प्रबंधन को Kotlin DSL और buildSrc के साथ अनुकूलित करें</title>
            <link >https://cheroliv.com/blog/2025/0079_gradle_tasks_tests_report_post.html</link>
            <pubDate>Fri, 11 Jul 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0079_gradle_tasks_tests_report_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_allprojects_और_subprojects_के_साथ_configurations_को_केंद्रीकृत_करें&amp;quot;&amp;gt;allprojects` और &amp;lt;code&amp;gt;subprojects&amp;lt;/code&amp;gt; के साथ Configurations को केंद्रीकृत करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_sourceplantuml&amp;quot;&amp;gt;[source,plantuml]&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ग्रैडल_एकीकरण_jbake_को_jbake_gradle_प्लगिन_का_उपयोग_करके_या_jbake_cli_को_सीधे_बुलाकर_gradle_बिल्ड्स_में_एकीकृत_किया_जा_सकता_है&amp;quot;&amp;gt;ग्रैडल एकीकरण JBake को JBake Gradle प्लगिन का उपयोग करके या JBake CLI को सीधे बुलाकर Gradle बिल्ड्स में एकीकृत किया जा सकता है:&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_initialize_a_new_jbake_project_jbake_i&amp;quot;&amp;gt;Initialize a new JBake project jbake -i&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_generate_the_site_jbake_b&amp;quot;&amp;gt;Bake (generate) the site jbake -b&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_and_serve_locally_jbake_b_s&amp;quot;&amp;gt;Bake and serve locally jbake -b -s&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_bake_and_watch_for_changes_jbake_b_reset&amp;quot;&amp;gt;Bake and watch for changes jbake -b --reset&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_specify_source_and_destination_jbake_source_folder_output_folder&amp;quot;&amp;gt;Specify source and destination jbake source_folder output_folder&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_clear_the_output_directory_before_baking_jbake_b_output_reset&amp;quot;&amp;gt;Clear the output directory before baking jbake -b . output --reset &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt;&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_gradle_एकीकरण_jbake_को_gradle_निर्माण_में_jbake_gradle_प्लगइन_का_उपयोग_करके_या_jbake_cli_को_सीधे_बुलाकर_एकीकृत_किया_जा_सकता_है_kotlin_tasks_registerjavaexecbake_mainclass_setorg_jbake_launcher_main_classpath_configurationsjbake_args_listofprojectdir_absolutepath_builddirjbake&amp;quot;&amp;gt;Gradle एकीकरण JBake को Gradle निर्माण में JBake Gradle प्लगइन का उपयोग करके या JBake CLI को सीधे बुलाकर एकीकृत किया जा सकता है: &amp;lt;code&amp;gt;&amp;lt;code&amp;gt;kotlin tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) { mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;) classpath = configurations[&amp;quot;jbake&amp;quot;] args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;) } &amp;lt;/code&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_abstract_class_reportfunctionalteststask_opentestreporttask_init_description_फ़ायरफ़ॉक्स_में_फंक्शनल_टेस्ट_रिपोर्ट_खोलता_है_reportpath_buildreportstestsfunctionaltestindex_html&amp;quot;&amp;gt;abstract class ReportFunctionalTestsTask : OpenTestReportTask() { init { description = &amp;quot;फ़ायरफ़ॉक्स में फंक्शनल टेस्ट रिपोर्ट खोलता है।&amp;quot; reportPath = &amp;quot;build/reports/tests/functionalTest/index.html&amp;quot; } }&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_sourcekotlin&amp;quot;&amp;gt;[source,kotlin]&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_tasks_registercom_yourpackage_reportunitteststaskreporttests_tasks_registercom_yourpackage_reportfunctionalteststaskreportfunctionaltests&amp;quot;&amp;gt;tasks.register\&amp;amp;lt;com.yourpackage.ReportUnitTestsTask\&amp;amp;gt;(&amp;quot;reportTests&amp;quot;) {} tasks.register\&amp;amp;lt;com.yourpackage.ReportFunctionalTestsTask\&amp;amp;gt;(&amp;quot;reportFunctionalTests&amp;quot;) {}&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_रिपोर्ट_कार्यों_का_uml_आरेख_कोड_plantuml&amp;quot;&amp;gt;रिपोर्ट कार्यों का UML आरेख (कोड PlantUML)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_sourceplantuml_2&amp;quot;&amp;gt;[source,plantuml]&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_enduml&amp;quot;&amp;gt;@enduml&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सॉफ्टवेयर प्रोजेक्ट के लिए बिल्ड कार्यों का स्वचालन महत्वपूर्ण है, और Gradle, अपने Kotlin DSL के साथ, असाधारण लचीलापन प्रदान करता है। हमारी बातचीत के दौरान, हमने बिल्ड लॉजिक को केंद्रीकृत और पुनः उपयोग करने के तरीकों का पता लगाया, विशेष रूप से टेस्ट रिपोर्ट के लिए, का लाभ उठाते हुए&amp;lt;strong&amp;gt;सभी परियोजनाएँ&amp;lt;/strong&amp;gt;, &amp;lt;strong&amp;gt;बिल्डSrc&amp;lt;/strong&amp;gt;, और Kotlin में कस्टम कार्य&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_allprojects_और_subprojects_के_साथ_configurations_को_केंद्रीकृत_करें&amp;quot;&amp;gt;allprojects` और &amp;lt;code&amp;gt;subprojects&amp;lt;/code&amp;gt; के साथ Configurations को केंद्रीकृत करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;ब्लॉक`allprojects` et `subprojects`आपके`build.gradle.kts`जड़ आपके मल्टी-मॉड्यूल प्रोजेक्ट में सामान्य कॉन्फ़िगरेशन लागू करने के लिए बुनियादी है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;*&amp;lt;code&amp;gt;allprojects { &amp;amp;#8230;&amp;amp;#8203; }`कॉन्फ़िगरेशन लागू करें&amp;lt;strong&amp;gt;मूल परियोजना और इसकी सभी उप-परियोजनाओं के लिए&amp;lt;/strong&amp;gt;। परिभाषित करने के लिए आदर्श`group&amp;lt;/code&amp;gt;, एक`version`, या कुछ`repositories`सामान्य (No output)&amp;lt;code&amp;gt;subprojects { &amp;amp;#8230;&amp;amp;#8203; }`कॉन्फ़िगरेशन लागू करें&amp;lt;strong&amp;gt;केवल उप-परियोजनाओं तक&amp;lt;/strong&amp;gt;, मूल परियोजना को छोड़कर. परफेक्ट मॉड्यूल-विशिष्ट प्लगिन लागू करने के लिए (जैसे`java&amp;lt;/code&amp;gt; ou &amp;lt;code&amp;gt;kotlin-jvm&amp;lt;/code&amp;gt;) या आपकी लाइब्रेरी के सामान्य निर्भरताएँ।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ एक उदाहरणात्मक उदाहरण :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// build.gradle.kts (projet racine)
plugins {
    base // Appliqué au projet racine
}

allprojects {
    group = &amp;quot;com.example&amp;quot;
    version = &amp;quot;1.0.0&amp;quot;

    repositories {
        mavenCentral()
    }

    tasks.withType&amp;amp;lt;org.gradle.api.tasks.testing.Test&amp;amp;gt; {
        useJUnitPlatform() // Configuration commune des tests pour tous les projets
    }
}

subprojects {
    apply(plugin = &amp;quot;java&amp;quot;)
    apply(plugin = &amp;quot;org.jetbrains.kotlin.jvm&amp;quot;)

    dependencies {
        implementation(&amp;quot;org.jetbrains.kotlin:kotlin-stdlib-jdk8&amp;quot;)
    }

}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;\==`buildSrc`बिल्ड तर्क का स्विस आर्मी चाकू&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जब आपके कार्यों की तर्क जटिल हो जाती है या इसे पुनः उपयोग में लाने की आवश्यकता होती है,&amp;lt;strong&amp;gt;buildSrc&amp;lt;/strong&amp;gt;यह प्राथमिक समाधान है। यह एक विशेष Gradle मॉड्यूल है जो मुख्य बिल्ड स्क्रिप्ट्स से पहले संकलित किया जाता है, जिससे इसकी क्लासेस आपके बिल्ड के पूरे क्लासपाथ पर उपलब्ध हो जाती हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;\=== क्यों उपयोग करें`buildSrc`कार्यों के लिए ?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;पुन: उपयोगिता&amp;lt;/strong&amp;gt;एक परिभाषित कार्य में`buildSrc`इस बिल्ड के किसी भी प्रोजेक्ट में लागू किया जा सकता है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;संगठन&amp;lt;/strong&amp;gt;: बिल्ड कोड को सेंट्रलाइज़ करें, जिससे यह अधिक साफ़ और रखरखाव योग्य हो।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;टाइप सुरक्षा और ऑटो‑कम्प्लीशन&amp;lt;/strong&amp;gt;: कोटलिन कोड में`buildSrc`इसे संकलित किया जाता है, जो आपके IDE में त्रुटि जाँच और स्वत पूर्णता प्रदान करता है, विकास अनुभव को बेहतर बनाता है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;\=== प्रवाह आरेख`buildSrc`(कोड PlantUML)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस आरेख को उत्पन्न करने के लिए, नीचे दिया गया कोड कॉपी करें और PlantUML समर्थन करने वाले टूल में पेस्ट करें।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_sourceplantuml&amp;quot;&amp;gt;[source,plantuml]&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;@startuml skinparam handwritten true skinparam monochrome true&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ग्रैडल_एकीकरण_jbake_को_jbake_gradle_प्लगिन_का_उपयोग_करके_या_jbake_cli_को_सीधे_बुलाकर_gradle_बिल्ड्स_में_एकीकृत_किया_जा_सकता_है&amp;quot;&amp;gt;ग्रैडल एकीकरण JBake को JBake Gradle प्लगिन का उपयोग करके या JBake CLI को सीधे बुलाकर Gradle बिल्ड्स में एकीकृत किया जा सकता है:&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;----
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
}
----

rectangle &amp;quot;ग्रैडल बिल्ड प्रक्रिया घटक &amp;quot;buildSrc&amp;quot; जैसे BS { फ़ाइल &amp;quot;MyCustomTask.kt&amp;quot; के रूप में T फ़ाइल &amp;quot;MyConventionPlugin.kt&amp;quot; के रूप में P } घटक &amp;quot;Root Project&amp;quot; के रूप में RP घटक &amp;quot;Subproject A&amp;quot; के रूप में SA घटक &amp;quot;Subproject B&amp;quot; को SB के रूप में }

T --\&amp;amp;gt; P : &amp;quot;is defined in&amp;quot; P --&amp;amp;gt; RP : &amp;quot;इस पर लागू किया जाता है P --&amp;amp;gt; SA : &amp;quot;लागू किया जाता है P --\&amp;amp;gt; SB : &amp;quot;लागू किया जाता है

RP --|\&amp;amp;gt; SA : &amp;quot;शामिल RP --|\&amp;amp;gt; SB : &amp;quot;शामिल

RP -up-&amp;amp;gt; BS : \&amp;quot;निर्भर करता है (बिल्ड लॉजिक के लिए)\ SA -up-&amp;amp;gt; BS : &amp;quot;निर्माण तर्क के लिए (निर्भर करता है) SB -up-&amp;amp;gt; BS : &amp;quot;निर्भर करता है (बिल्ड तर्क के लिए)

T के दाएँ ओर नोट कस्टम टास्क वर्ग (उदाहरण: OpenTestReportTask) end note

पी के दाएँ नोट कॉन्वेंशन प्लगइन वे कार्यों को दर्ज करते हैं end note

## @enduml

\== अभिव्यक्त रिपोर्ट कार्यों का निर्माण

टेस्ट रिपोर्ट्स को संभालने के लिए, हमने एक मॉड्यूलर दृष्टिकोण तैयार किया एक अमूर्त कार्य क्लास का उपयोग करके में`buildSrc`. आपकी आवश्यकताओं के अनुसार, यह वर्ग से विरासत में ले सकता है`DefaultTask` ou de `Exec`.

\=== अमूर्त कार्य`OpenTestReportTask`(से विरासत में प्राप्त`DefaultTask`)

यदि आपको फ़ाइल सिस्टम या अन्य Gradle API के साथ बातचीत करने वाली कस्टम Kotlin तर्क चाहिए, और फिर बाहरी कमांड चलाने की आवश्यकता हो, तो इस दृष्टिकोण की सिफारिश की जाती है।

## [source,kotlin]

package com.yourpackage

आयात org.gradle.api.DefaultTask आयात org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction import java.io.File

abstract class OpenTestReportTask : DefaultTask() {&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;init {
    group = &amp;quot;verification&amp;quot;
    description = &amp;quot;Opens a test report in Firefox.&amp;quot;
    dependsOn(&amp;quot;check&amp;quot;) // Assure que les rapports sont générés
}&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;@get:Input
abstract var reportPath: String&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;@TaskAction
fun openReport() {
    val separator = File.separator
    val reportFile = project.layout.projectDirectory.asFile.toPath()
        .resolve(reportPath.replace(&amp;quot;/&amp;quot;, separator))
        .toAbsolutePath()
        .toFile()&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;literalblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;if (!reportFile.exists()) {
    logger.warn(&amp;quot;Report file does not exist: $reportFile. Ensure &amp;#39;check&amp;#39; ran.&amp;quot;)
    return
}&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;literalblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;    project.exec {
        commandLine(&amp;quot;firefox&amp;quot;, &amp;quot;--new-tab&amp;quot;, reportFile.absolutePath)
    }
    logger.lifecycle(&amp;quot;Opened test report: ${reportFile.absolutePath}&amp;quot;)
}&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;## }

\=== वास्तविक कार्यान्वयन

ये क्लासेस अमूर्त कार्य से विरासत में लेती हैं और रिपोर्ट के विशिष्ट पथ को परिभाषित करती हैं।

## [source,kotlin]

पैकेज com.yourpackage

अमूर्त वर्ग ReportUnitTestsTask : OpenTestReportTask() { init { description = &amp;quot;फ़ायरफ़ॉक्स में यूनिट परीक्षण रिपोर्ट खोलता है। reportPath = &amp;quot;build/reports/tests/test/index.html } }

package com.yourpackage

= मेरा ब्लॉग पोस्ट शीर्षक
2026-01-15
:jbake-title: मेरा ब्लॉग पोस्ट शीर्षक
:jbake-tags: java, gradle, ट्यूटोरियल
:jbake-type: पोस्ट
:jbake-status: प्रकाशित
:jbake-date: 2026-01-15
:jbake-summary: पोस्ट का संक्षिप्त सारांश
:jbake-author: लेखक का नाम
:jbake-description: SEO के लिए मेटा विवरण
:jbake-slug: my-blog-post-slug
:jbake-reading-time: 5 मिनट
:imagesdir: ./images
:source-highlighter: highlight.js
:icons: फ़ॉन्ट
:toc: बाएँ
:toclevels: 3
:toc-title: सामग्री की तालिका

### JBake CLI आदेश&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;h1 id=&amp;quot;_initialize_a_new_jbake_project_jbake_i&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Initialize a new JBake project jbake -i&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_generate_the_site_jbake_b&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake (generate) the site jbake -b&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_and_serve_locally_jbake_b_s&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake and serve locally jbake -b -s&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_bake_and_watch_for_changes_jbake_b_reset&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Bake and watch for changes jbake -b --reset&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_specify_source_and_destination_jbake_source_folder_output_folder&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Specify source and destination jbake source_folder output_folder&amp;lt;/h1&amp;gt;

&amp;lt;h1 id=&amp;quot;_clear_the_output_directory_before_baking_jbake_b_output_reset&amp;quot; class=&amp;quot;sect0&amp;quot;&amp;gt;Clear the output directory before baking jbake -b . output --reset &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt;&amp;lt;/h1&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_gradle_एकीकरण_jbake_को_gradle_निर्माण_में_jbake_gradle_प्लगइन_का_उपयोग_करके_या_jbake_cli_को_सीधे_बुलाकर_एकीकृत_किया_जा_सकता_है_kotlin_tasks_registerjavaexecbake_mainclass_setorg_jbake_launcher_main_classpath_configurationsjbake_args_listofprojectdir_absolutepath_builddirjbake&amp;quot;&amp;gt;Gradle एकीकरण JBake को Gradle निर्माण में JBake Gradle प्लगइन का उपयोग करके या JBake CLI को सीधे बुलाकर एकीकृत किया जा सकता है: &amp;lt;code&amp;gt;&amp;lt;code&amp;gt;kotlin tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) { mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;) classpath = configurations[&amp;quot;jbake&amp;quot;] args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;) } &amp;lt;/code&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/h3&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_abstract_class_reportfunctionalteststask_opentestreporttask_init_description_फ़ायरफ़ॉक्स_में_फंक्शनल_टेस्ट_रिपोर्ट_खोलता_है_reportpath_buildreportstestsfunctionaltestindex_html&amp;quot;&amp;gt;abstract class ReportFunctionalTestsTask : OpenTestReportTask() { init { description = &amp;quot;फ़ायरफ़ॉक्स में फंक्शनल टेस्ट रिपोर्ट खोलता है।&amp;quot; reportPath = &amp;quot;build/reports/tests/functionalTest/index.html&amp;quot; } }&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;\=== कार्यों का अभिलेख&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;में`build.gradle.kts`आपके मूल प्रोजेक्ट :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_sourcekotlin&amp;quot;&amp;gt;[source,kotlin]&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_tasks_registercom_yourpackage_reportunitteststaskreporttests_tasks_registercom_yourpackage_reportfunctionalteststaskreportfunctionaltests&amp;quot;&amp;gt;tasks.register\&amp;amp;lt;com.yourpackage.ReportUnitTestsTask\&amp;amp;gt;(&amp;quot;reportTests&amp;quot;) {} tasks.register\&amp;amp;lt;com.yourpackage.ReportFunctionalTestsTask\&amp;amp;gt;(&amp;quot;reportFunctionalTests&amp;quot;) {}&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_रिपोर्ट_कार्यों_का_uml_आरेख_कोड_plantuml&amp;quot;&amp;gt;रिपोर्ट कार्यों का UML आरेख (कोड PlantUML)&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;नीचे दिया गया कोड कॉपी करें और इसे PlantUML को समर्थन करने वाले उपकरण में पेस्ट करें।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_sourceplantuml_2&amp;quot;&amp;gt;[source,plantuml]&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;@startuml skinparam handwritten true skinparam monochrome true&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;abstract class DefaultTask { }&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;abstract class Exec { \+ commandLine(args: String&amp;amp;#8230;&amp;amp;#8203;) \+ exec() }&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;abstract class OpenTestReportTask extends DefaultTask { \+ group: String = &amp;quot;verification \+ description: String \+ dependsOn(&amp;quot;check&amp;quot;) \+ abstract reportPath: String \+ openReport() : void }&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अमूर्त वर्ग AbstractJbakeExecTask Exec को विस्तारित करता है { \+ group: String = &amp;quot;verification \+ विवरण: स्ट्रिंग \+ dependsOn(&amp;quot;check&amp;quot;) \+ abstract reportRelativePath: String \+ exec() : void }&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;class ReportUnitTestsTask extends OpenTestReportTask { \+ reportPath: String = &amp;quot;build/reports/tests/test/index.html }&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;क्लास ReportFunctionalTestsTask विस्तार OpenTestReportTask { \+ reportPath: String = &amp;quot;build/reports/tests/functionalTest/index.html }&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;class ReportJbakeTestsTask extends AbstractJbakeExecTask { + reportRelativePath: String = &amp;quot;build/reports/tests/test/index.html }&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;class ReportJbakeFunctionalTestsTask extends AbstractJbakeExecTask { \+ reportRelativePath: String = &amp;quot;build/reports/tests/functionalTest/index.html }&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;OpenTestReportTask &amp;amp;lt;-- ReportUnitTestsTask OpenTestReportTask &amp;amp;lt;-- ReportFunctionalTestsTask&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;AbstractJbakeExecTask &amp;amp;lt;-- ReportJbakeTestsTask AbstractJbakeExecTask &amp;amp;lt;-- ReportJbakeFunctionalTestsTask&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;DefaultTask \&amp;amp;lt;|-- OpenTestReportTask Exec \&amp;amp;lt;|-- AbstractJbakeExecTask &amp;lt;mark&amp;gt;#&amp;lt;/mark&amp;gt; ग्रेडल एकीकरण JBake को JBake ग्रेडल प्लगइन का उपयोग करके या JBake सीएलआई को सीधे बुलाकर ग्रेडल बिल्ड में एकीकृत किया जा सकता है: ```kotlin tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) { mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;) classpath = configurations[&amp;quot;jbake&amp;quot;] args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;) }&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_enduml&amp;quot;&amp;gt;@enduml&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अमूर्त कार्य`AbstractJbakeExecTask`(विरासत प्राप्त`Exec`)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यदि आपका कार्य मुख्य रूप से परिवर्तनीय तर्कों के साथ एक बाहरी कमांड निष्पादित करने तक सीमित है, तो सीधे से विरासत में लेना**&amp;lt;mark&amp;gt;#&amp;lt;/mark&amp;gt; ग्रेडल एकीकरण JBake को Gradle बिल्ड में JBake Gradle प्लगइन का उपयोग करके या JBake CLI को सीधे बुलाकर एकीकृत किया जा सकता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;----
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
}**यह अधिक सीधा है।

## [source,kotlin]

package com.yourpackage

import org.gradle.api.tasks.Exec import org.gradle.api.tasks.Input import java.io.File

अमूर्त वर्ग AbstractJbakeExecTask : Exec() {

----

init { group = &amp;quot;verification&amp;quot; description = &amp;quot;Opens a Jbake project report in Firefox.&amp;quot; dependsOn(&amp;quot;check&amp;quot;) }

@get:Input abstract var reportRelativePath: String

override fun exec() { val separator = File.separator val reportFile = project.layout.projectDirectory.asFile.toPath() .resolve(reportRelativePath.replace(&amp;quot;/&amp;quot;, separator)) .toAbsolutePath() .toFile()

if (!reportFile.exists()) { logger.warn(&amp;quot;Report file does not exist: $reportFile. Ensure &amp;#39;check&amp;#39; ran.&amp;quot;) return }

commandLine(&amp;quot;firefox&amp;quot;, &amp;quot;--new-tab&amp;quot;, reportFile.absolutePath) logger.lifecycle(&amp;quot;Attempting to open report: ${reportFile.absolutePath}&amp;quot;) super.exec() // Appelle la méthode exec() de la super-classe Exec }

## }

\=== ठोस कार्यान्वयन के लिए`Exec`

## [source,kotlin]

package com.yourpackage

अमूर्त वर्ग ReportJbakeTestsTask : AbstractJbakeExecTask() init { फ़ायरफ़ॉक्स में Jbake यूनिट टेस्ट रिपोर्ट खोलता है। reportRelativePath = &amp;quot;build/reports/tests/test/index.html } }

package com.yourpackage

## abstract class ReportJbakeFunctionalTestsTask : AbstractJbakeExecTask() { init { description = &amp;quot;फ़ायरफ़ॉक्स में फ़ंक्शनल टेस्ट रिपोर्ट खोलता है।&amp;quot; reportRelativePath = &amp;quot;build/reports/tests/functionalTest/index.html&amp;quot; } }

\== कार्यों की दृश्यता`buildSrc`

आप जो कार्य और वर्ग परिभाषित करते हैं**buildSrc**हैं :

***दृश्य और उपयोगी**आपके मुख्य बिल्ड के सभी प्रोजेक्ट्स (रूट और सब-प्रोजेक्ट्स)। इसलिए आप उपयोग कर सकते हैं`com.yourpackage.ReportUnitTestsTask`में`allprojects { ... }`. ***गैर-निष्पाद्य**सीधे buildSrc कार्यों के रूप में (उदाहरण के लिए,`gradle :buildSrc:reportTests`यदि कार्य को विशिष्ट रूप से में दर्ज नहीं किया गया है तो यह काम नहीं करेगा`buildSrc/build.gradle.kts`).`buildSrc`यह एक संकलन मॉड्यूल है, एक निष्पादन योग्य एप्लिकेशन मॉड्यूल नहीं, इन मुख्य बिल्ड कार्यों के लिए।

\=== परीक्षणों के लिए एक रिपोर्ट चलाएँ`buildSrc`खुद

Si `buildSrc`अपने स्वयं के परीक्षण होते हैं और यह रिपोर्ट उत्पन्न करता है, आप रिपोर्ट कार्य को सीधे में दर्ज कर सकते हैं`buildSrc/build.gradle.kts`(Empty)

## [source,kotlin]

प्लगइंस { `kotlin-jvm` आप एक पेशेवर अनुवादक हैं। fr से hi तक अनुवाद करें। सभी बैकटिक कोड स्पैन (`...`) को ठीक वैसे ही संरक्षित रखें — कभी भी बैकटिक की सामग्री, अंतराल या स्थिति को न बदलें। यह पाठ किसी बड़े वाक्य का अंश हो सकता है — अतिरिक्त संदर्भ मांगे बिना उस अंश का अनुवाद करें। केवल अनुवादित पाठ आउटपुट करें — कोई स्पष्टीकरण, कोई टिप्पणी, कोई परिचय, कोई विकल्प, कोई विकल्प नहीं।

repositories { mavenCentral() }

tasks.withType\&amp;amp;lt;Test\&amp;amp;gt; { useJUnitPlatform() reports.html.outputLocation.set(layout.buildDirectory.dir(&amp;quot;reports/tests&amp;quot;)) }

import com.yourpackage.ReportJbakeTestsTask // अपनी टास्क क्लास आयात करें

tasks.register&amp;amp;lt;ReportJbakeTestsTask&amp;amp;gt;(&amp;quot;reportBuildSrcTests&amp;quot;) { // पथ क्लास में पहले से परिभाषित है, यह buildSrc रिपोर्ट्स की ओर इशारा करेगा }

आप फिर इसे निष्पादित कर सकते हैं:`./gradlew :buildSrc:test`के बाद`./gradlew :buildSrc:reportBuildSrcTests`.

इन प्रथाओं को अपनाने से, आप Kotlin DSL में Gradle बिल्ड सिस्टम बनाएँगे जो न केवल शक्तिशाली होंगे, बल्कि अविश्वसनीय रूप से मॉड्यूलर, बनाए रखने में आसान और समझने में सरल भी होंगे।&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>JBake और JGit के साथ कॉन्फ़िगरेबल कोटलिन Gradle प्लगिन का TDD</title>
            <link >https://cheroliv.com/blog/2025/0078_jbake_gradle_plugin_syntaxe_post.html</link>
            <pubDate>Wed, 9 Jul 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0078_jbake_gradle_plugin_syntaxe_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_उद्देश्य&amp;quot;&amp;gt;उद्देश्य&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_घोषणात्मक_विन्यास&amp;quot;&amp;gt;घोषणात्मक विन्यास&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_प्लगइन_की_आर्किटेक्चर&amp;quot;&amp;gt;प्लगइन की आर्किटेक्चर&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_dsl_एक्सटेंशन_की_परिभाषा&amp;quot;&amp;gt;DSL एक्सटेंशन की परिभाषा&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_कस्टमाइज़्ड_कार्य_की_परिभाषा&amp;quot;&amp;gt;कस्टमाइज़्ड कार्य की परिभाषा&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_इंटरफ़ेस_gitadapter&amp;quot;&amp;gt;इंटरफ़ेस GitAdapter&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_jgit_के_साथ_वास्तविक_कार्यान्वयन&amp;quot;&amp;gt;JGit के साथ वास्तविक कार्यान्वयन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_कॉन्फ़िगरेशन_dsl_कोटलिन&amp;quot;&amp;gt;कॉन्फ़िगरेशन DSL कोटलिन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_मॉकिटो_के_साथ_यूनिट_टेस्ट&amp;quot;&amp;gt;मॉकिटो के साथ यूनिट टेस्ट&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निर्भरताएँ&amp;quot;&amp;gt;निर्भरताएँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_गिट_व्यवहार_का_परीक्षण&amp;quot;&amp;gt;गिट व्यवहार का परीक्षण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_आगामी_कदम&amp;quot;&amp;gt;आगामी कदम&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह पोस्ट Kotlin DSL में लिखे गए Gradle प्लगिन की संपूर्ण डिज़ाइन और परीक्षण (TDD) प्रक्रिया प्रस्तुत करती है। यह प्लगिन &amp;lt;strong&amp;gt;JBake&amp;lt;/strong&amp;gt; और &amp;lt;strong&amp;gt;JGit&amp;lt;/strong&amp;gt; के माध्यम से &amp;lt;strong&amp;gt;Git तैनाती&amp;lt;/strong&amp;gt; के साथ स्थिर साइटों की पीढ़ी को स्वचालित करता है, सब कुछ YAML कॉन्फ़िगरेशन फ़ाइल से।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_उद्देश्य&amp;quot;&amp;gt;उद्देश्य&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक Gradle प्लगइन बनाएँ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Kotlin DSL में कॉन्फ़िगरेबल ;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;सक्षम&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;JBake से एक स्थिर साइट उत्पन्न करें ;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;JGit का उपयोग करके दूरस्थ Git रिपॉजिटरी पर तैनात करें;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;CI/CD वर्कफ़्लो में एकीकृत करने योग्य ;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;TDD दृष्टिकोण के अनुसार परीक्षण किया गया।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_घोषणात्मक_विन्यास&amp;quot;&amp;gt;घोषणात्मक विन्यास&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ YAML कॉन्फ़िगरेशन का एक उदाहरण है जिसे हमारे DSL में मॉडेल किया जाना है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-yaml hljs&amp;quot; data-lang=&amp;quot;yaml&amp;quot;&amp;gt;bake:
  srcPath: &amp;quot;./site/jbake&amp;quot;
  destDirPath: &amp;quot;bake&amp;quot;
pushPage:
  from: &amp;quot;bake&amp;quot;
  to: &amp;quot;cvs&amp;quot;
  repo:
    name: &amp;quot;trainings&amp;quot;
    repository: &amp;quot;https://github.com/pages-content/trainings.git&amp;quot;
    credentials:
      username: &amp;quot;USERNAME&amp;quot;
      password: &amp;quot;SECRET_TOKEN&amp;quot;
  branch: &amp;quot;main&amp;quot;
  message: &amp;quot;cheroliv.com&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह कॉन्फ़िगरेशन Kotlin DSL में एक घोषणीय Gradle एक्सटेंशन के माध्यम से प्रतिनिधित्व की जाती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_प्लगइन_की_आर्किटेक्चर&amp;quot;&amp;gt;प्लगइन की आर्किटेक्चर&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/jbake-asciidoctor-class-diagram.png&amp;quot; alt=&amp;quot;jbake asciidoctor class diagram&amp;quot; width=&amp;quot;568&amp;quot; height=&amp;quot;261&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_dsl_एक्सटेंशन_की_परिभाषा&amp;quot;&amp;gt;DSL एक्सटेंशन की परिभाषा&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;open class WorkspaceEngineExtension {
    var outputDir: String = &amp;quot;build/site&amp;quot;
    var template: String = &amp;quot;freemarker&amp;quot;
    var repoUrl: String = &amp;quot;&amp;quot;
    var branch: String = &amp;quot;main&amp;quot;
    var message: String = &amp;quot;Generated by engine&amp;quot;
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_कस्टमाइज़्ड_कार्य_की_परिभाषा&amp;quot;&amp;gt;कस्टमाइज़्ड कार्य की परिभाषा&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;abstract class GenerateSiteTask : DefaultTask() {
    lateinit var gitAdapter: GitAdapter

    @get:Input abstract val repoUrl: Property&amp;amp;lt;String&amp;amp;gt;
    @get:InputDirectory abstract val outputDir: DirectoryProperty
    @get:Input abstract val branch: Property&amp;amp;lt;String&amp;amp;gt;
    @get:Input abstract val message: Property&amp;amp;lt;String&amp;amp;gt;

    @TaskAction
    fun run() {
        val repo = gitAdapter.cloneRepository(repoUrl.get(), outputDir.get().asFile)
        gitAdapter.commitAndPush(repo, branch.get(), message.get())
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_इंटरफ़ेस_gitadapter&amp;quot;&amp;gt;इंटरफ़ेस GitAdapter&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;interface GitAdapter {
    fun cloneRepository(uri: String, directory: File): Repository
    fun commitAndPush(repo: Repository, branch: String, message: String)
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_jgit_के_साथ_वास्तविक_कार्यान्वयन&amp;quot;&amp;gt;JGit के साथ वास्तविक कार्यान्वयन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;class JGitAdapter : GitAdapter {
    override fun cloneRepository(uri: String, directory: File): Repository {
        return Git.cloneRepository()
            .setURI(uri)
            .setDirectory(directory)
            .call()
            .repository
    }

    override fun commitAndPush(repo: Repository, branch: String, message: String) {
        Git(repo).use {
            it.add().addFilepattern(&amp;quot;.&amp;quot;).call()
            it.commit().setMessage(message).call()
            it.push().call()
        }
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_कॉन्फ़िगरेशन_dsl_कोटलिन&amp;quot;&amp;gt;कॉन्फ़िगरेशन DSL कोटलिन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;workspaceEngine {
    outputDir = &amp;quot;build/out&amp;quot;
    template = &amp;quot;freemarker&amp;quot;
    repoUrl = &amp;quot;https://github.com/cheroliv/trainings.git&amp;quot;
    branch = &amp;quot;main&amp;quot;
    message = &amp;quot;deploy from plugin&amp;quot;
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_मॉकिटो_के_साथ_यूनिट_टेस्ट&amp;quot;&amp;gt;मॉकिटो के साथ यूनिट टेस्ट&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_निर्भरताएँ&amp;quot;&amp;gt;निर्भरताएँ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;testImplementation(&amp;quot;org.mockito:mockito-core:5.12.0&amp;quot;)
testImplementation(&amp;quot;org.mockito.kotlin:mockito-kotlin:5.2.1&amp;quot;)
testImplementation(&amp;quot;org.junit.jupiter:junit-jupiter:5.10.0&amp;quot;)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_गिट_व्यवहार_का_परीक्षण&amp;quot;&amp;gt;गिट व्यवहार का परीक्षण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;class GenerateSiteTaskMockitoTest {

    @TempDir
    lateinit var tempDir: File

    @Test
    fun `task should call clone and commitAndPush`() {
        val project = ProjectBuilder.builder().build()
        val task = project.tasks.create(&amp;quot;generateSite&amp;quot;, GenerateSiteTask::class.java)

        val mockGitAdapter = mock&amp;amp;lt;GitAdapter&amp;amp;gt;()
        val mockRepo = mock&amp;amp;lt;Repository&amp;amp;gt;()

        whenever(mockGitAdapter.cloneRepository(any(), any())).thenReturn(mockRepo)

        task.gitAdapter = mockGitAdapter
        task.repoUrl.set(&amp;quot;https://github.com/cheroliv/test.git&amp;quot;)
        task.outputDir.set(project.layout.projectDirectory.dir(tempDir.name))
        task.branch.set(&amp;quot;main&amp;quot;)
        task.message.set(&amp;quot;test commit&amp;quot;)

        task.run()

        verify(mockGitAdapter).cloneRepository(eq(&amp;quot;https://github.com/cheroliv/test.git&amp;quot;), any())
        verify(mockGitAdapter).commitAndPush(eq(mockRepo), eq(&amp;quot;main&amp;quot;), eq(&amp;quot;test commit&amp;quot;))
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/jbake-asciidoctor-sequence-diagram.png&amp;quot; alt=&amp;quot;jbake asciidoctor sequence diagram&amp;quot; width=&amp;quot;794&amp;quot; height=&amp;quot;326&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;ज़िम्मेदारियों का पृथक्करण vía`GitAdapter`यह Gradle प्लगिन विकास में TDD को पूरी तरह से लागू करने की अनुमति देता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Git कॉल अमूर्त और परीक्षण योग्य हैं ;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;DSL कॉन्फ़िगरेशन साफ़ और स्पष्ट है ;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;प्लगिन वास्तविक कार्यान्वयन से निरपेक्ष रहता है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह दृष्टिकोण उच्च परीक्षणीयता और विस्तार क्षमता (GitHub API, GitLab, आदि की ओर) सुनिश्चित करता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_आगामी_कदम&amp;quot;&amp;gt;आगामी कदम&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;JBake जनरेशन को एक के रूप में एकीकृत करें`BakeAdapter`&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एकीकृत परीक्षण जोड़ें के साथ`GradleRunner`&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;फ़ाइलों की स्वचालित लोडिंग का समर्थन करें`site.yml`के माध्यम से SnakeYAML&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>AsciiDoc: प्रभावी दस्तावेज़ीकरण के लिए सिंटैक्स खोजें और महारत हासिल करें</title>
            <link >https://cheroliv.com/blog/2025/0077_asciidoc_syntaxe_post.html</link>
            <pubDate>Fri, 20 Jun 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0077_asciidoc_syntaxe_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_asciidoc_क्या_है&amp;quot;&amp;gt;AsciiDoc क्या है?&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_asciidoc_क्यों_चुनें&amp;quot;&amp;gt;AsciiDoc क्यों चुनें ?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_उपयोग_केस_आरेख_use_case&amp;quot;&amp;gt;उपयोग केस आरेख (Use Case)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_diagramme_mind_map&amp;quot;&amp;gt;Diagramme Mind Map&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_प्रवाह_आरेख_प्रवाह&amp;quot;&amp;gt;प्रवाह आरेख (प्रवाह)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_एक_asciidoc_फ़ाइल_की_बुनियादी_संरचना&amp;quot;&amp;gt;एक AsciiDoc फ़ाइल की बुनियादी संरचना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_मूलभूत_सिंटैक्स&amp;quot;&amp;gt;मूलभूत सिंटैक्स&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_शीर्षक_और_अनुभाग&amp;quot;&amp;gt;शीर्षक और अनुभाग&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_बोल्ड_इटैलिक_और_मोनोस्पेस_में_टेक्स्ट&amp;quot;&amp;gt;बोल्ड, इटैलिक और मोनोस्पेस में टेक्स्ट&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सूची_बिंदु_और_क्रमांकित&amp;quot;&amp;gt;सूची बिंदु और क्रमांकित&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_लिंक_और_चित्र&amp;quot;&amp;gt;लिंक और चित्र&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_कोड_ब्लॉकों&amp;quot;&amp;gt;कोड ब्लॉकों&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_तालिकाएँ&amp;quot;&amp;gt;तालिकाएँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_नोट्स_और_चेतावनियाँ&amp;quot;&amp;gt;नोट्स और चेतावनियाँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अट्रिब्यूट_और_चर_का_उपयोग&amp;quot;&amp;gt;अट्रिब्यूट और चर का उपयोग&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सामान्य_उपयोग_के_मामले&amp;quot;&amp;gt;सामान्य उपयोग के मामले&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अच्छे_अभ्यास&amp;quot;&amp;gt;अच्छे अभ्यास&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_आगे_बढ़ने_के_लिए&amp;quot;&amp;gt;आगे बढ़ने के लिए&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;&amp;lt;em&amp;gt;लक्षित दर्शक :&amp;lt;/em&amp;gt; विकासकर्ता, तकनीकी लेखक, और कोई भी व्यक्ति जो तकनीकी दस्तावेज़ या समृद्ध लेख लिखना चाहता है।&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;AsciiDoc एक हल्का मार्कअप भाषा है, जो संरचित तकनीकी दस्तावेज़, लेख, किताब या फिर प्रस्तुतियाँ तैयार करने के लिए डिज़ाइन किया गया है। यह अपनी पठनीयता, सिंटैक्टिक समृद्धि और विभिन्न प्रारूप (HTML, PDF, DocBook आदि) उत्पन्न करने की क्षमता से अलग होता है। इस लेख में, हम एससीआइडॉक का मूलभूत सिंटैक्स़ देखेंगे और तेज़ी से शुरू करने के लिए कुछ सुझाव देंगे।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_asciidoc_क्या_है&amp;quot;&amp;gt;AsciiDoc क्या है?&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;AsciiDoc दस्तावेज़ विवरण की एक भाषा है, जो Markdown के समान है लेकिन अधिक शक्तिशाली है। यह पाठ, शीर्षक, सूचियों, तालिकाओं, कोड ब्लॉक और कई अन्य चीज़ों को प्रभावी ढंग से संरचित करने की अनुमति देती है। इसकी बहुमुखी प्रतिभा के कारण, यह ओपन‑सोर्स परियोजनाओं के दस्तावेज़ीकरण, किताबों की लेखन और वेब प्रकाशन के लिए एक लोकप्रिय विकल्प है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_asciidoc_क्यों_चुनें&amp;quot;&amp;gt;AsciiDoc क्यों चुनें ?&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;सहज और पठनीय सिंटैक्स।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;जटिल संरचनाओं (तालिकाएँ, नोट्स, चेतावनियाँ, आदि) का प्राकृतिक समर्थन।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;मल्टी-फॉर्मैट उत्पादन (HTML, PDF, ePub, DocBook…)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;JBake या Antora जैसे स्थिर साइट जनरेटरों के साथ आसान इंटीग्रेशन।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;उन्नत अनुकूलन विशेषताओं और एक्सटेंशन के साथ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_उपयोग_केस_आरेख_use_case&amp;quot;&amp;gt;उपयोग केस आरेख (Use Case)&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक उपयोग केस डायग्राम उपयोगकर्ताओं और प्रणाली के बीच मुख्य इंटरैक्शन को प्रस्तुत करने की अनुमति देता है। यहाँ एक दस्तावेज़ीकरण प्रणाली के लिए एक सरल उदाहरण है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-381f40e6e0660c0c53433ff054330b76.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;423&amp;quot; height=&amp;quot;258&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_diagramme_mind_map&amp;quot;&amp;gt;Diagramme Mind Map&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;माइंड मैप (मानसिक मानचित्र) AsciiDoc से संबंधित अवधारणाओं और उनके संबंधों का पता लगाने के लिए आदर्श है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-e1560e9cc014158b6fbeed1e5ad8e138.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;394&amp;quot; height=&amp;quot;527&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_प्रवाह_आरेख_प्रवाह&amp;quot;&amp;gt;प्रवाह आरेख (प्रवाह)&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक फ्लो डायग्राम AsciiDoc दस्तावेज़ की उत्पादन प्रक्रिया का वर्णन करने की अनुमति देता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;diag-plantuml-md5-51318d77b9e18062d3a9b751587670ae.png&amp;quot; alt=&amp;quot;Diagram&amp;quot; width=&amp;quot;299&amp;quot; height=&amp;quot;361&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_एक_asciidoc_फ़ाइल_की_बुनियादी_संरचना&amp;quot;&amp;gt;एक AsciiDoc फ़ाइल की बुनियादी संरचना&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक AsciiDoc फ़ाइल सामान्यतः शीर्षक से शुरू होती है, वैकल्पिक विशेषताओं के बाद, फिर संरचित सामग्री। यहाँ एक न्यूनतम उदाहरण दिया गया है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;= Titre Principal
Auteur
2024-09-03
:toc:
:icons: font

Votre contenu commence ici...&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_मूलभूत_सिंटैक्स&amp;quot;&amp;gt;मूलभूत सिंटैक्स&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_शीर्षक_और_अनुभाग&amp;quot;&amp;gt;शीर्षक और अनुभाग&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;AsciiDoc कई स्तरों के शीर्षकों का समर्थन करता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;= Titre de niveau 1
== Titre de niveau 2
=== Titre de niveau 3
==== Titre de niveau 4&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_बोल्ड_इटैलिक_और_मोनोस्पेस_में_टेक्स्ट&amp;quot;&amp;gt;बोल्ड, इटैलिक और मोनोस्पेस में टेक्स्ट&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;*gras* _italique_ `monospace`&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सूची_बिंदु_और_क्रमांकित&amp;quot;&amp;gt;सूची बिंदु और क्रमांकित&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;* Élément 1
* Élément 2

. Premier
. Deuxième
. Troisième&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_लिंक_और_चित्र&amp;quot;&amp;gt;लिंक और चित्र&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;Lien standard : https://asciidoc.org[AsciiDoc]
Image : image::images/logo.png[AsciiDoc Logo]&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_कोड_ब्लॉकों&amp;quot;&amp;gt;कोड ब्लॉकों&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;[source,python]&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;def hello(): print(&amp;quot;नमस्ते AsciiDoc !&amp;quot;)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_तालिकाएँ&amp;quot;&amp;gt;तालिकाएँ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;|===
| Colonne 1 | Colonne 2

| Valeur A
| Valeur B

| Valeur C
| Valeur D
|===&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_नोट्स_और_चेतावनियाँ&amp;quot;&amp;gt;नोट्स और चेतावनियाँ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;AsciiDoc दृश्य सूचना ब्लॉक प्रस्तुत करता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;NOTE: Ceci est une note importante.
TIP: Conseil utile pour l’utilisateur.
WARNING: Attention à ce point.&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_अट्रिब्यूट_और_चर_का_उपयोग&amp;quot;&amp;gt;अट्रिब्यूट और चर का उपयोग&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;कस्टम विशेषताएँ मान पुनः उपयोग करने या व्यवहार को कॉन्फ़िगर करने की अनुमति देती हैं:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-asciidoc hljs&amp;quot; data-lang=&amp;quot;asciidoc&amp;quot;&amp;gt;:project-name: AsciiDoc Explorer

Le projet s’appelle {project-name}.&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_सामान्य_उपयोग_के_मामले&amp;quot;&amp;gt;सामान्य उपयोग के मामले&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;ओपन सोर्स प्रोजेक्ट दस्तावेज़ीकरण (README, तकनीकी मार्गदर्शिका) - पुस्तकें और ईबुक्स लेखन - स्थिर वेबसाइटों का स्वचालित उत्पादन (JBake, Antora) - तकनीकी प्रस्तुतियाँ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_अच्छे_अभ्यास&amp;quot;&amp;gt;अच्छे अभ्यास&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;संगत शीर्षकों का उपयोग करें और (:toc:) के साथ एक स्वचालित सारणी। - ध्यान आकर्षित करने के लिए मुख्य बिंदुओं पर अधिसूचनाओं को प्राथमिकता दें। अपनी फाइलों को व्यवस्थित रखें ताकि रखरखाव आसान हो। उदाहरण दिखाने के लिए एनोटेटेड कोड ब्लॉक्स का उपयोग करें।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;AsciiDoc एक शक्तिशाली और सुलभ उपकरण है जो तकनीकी दस्तावेज़ या संरचित लेख तैयार करने के लिए उपयोगी है। इसकी समृद्ध व्याकरण, बहु-प्रारूप उत्पादन के संयोजन से, यह विकसित करने वालों और मांग वाले लेखकों के लिए एक उत्कृष्ट साथी बन जाता है। अपने अगले प्रोजेक्ट में AsciiDoc आज़माइए और अंतर देखिए!&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_आगे_बढ़ने_के_लिए&amp;quot;&amp;gt;आगे बढ़ने के लिए&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आधिकारिक दस्तावेज़: &amp;lt;a href=&amp;quot;https://asciidoc.org&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://asciidoc.org&amp;lt;/a&amp;gt; - Asciidoctor : &amp;lt;a href=&amp;quot;https://asciidoctor.org&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://asciidoctor.org&amp;lt;/a&amp;gt; - JBake और AsciiDoc : &amp;lt;a href=&amp;quot;https://jbake.org/docs/2.6.4/#asciidoc_support&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://jbake.org/docs/2.6.4/#asciidoc_support&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपने अनुभव और युक्तियाँ टिप्पणी में साझा करें!&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Ubuntu से इंटरनेट पर एक स्थानीय सेवा उजागर करें : पोर्ट फ़ॉरवर्डिंग का पूर्ण गाइड</title>
            <link >https://cheroliv.com/blog/2025/0076_port_forwarding_post.html</link>
            <pubDate>Wed, 28 May 2025 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0076_port_forwarding_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_nat_और_निजी_पते&amp;quot;&amp;gt;समस्या: NAT और निजी पते&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_1_अपना_सार्वजनिक_ip_पता_पहचानें&amp;quot;&amp;gt;चरण 1: अपना सार्वजनिक IP पता पहचानें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_2_अपने_उबुन्टू_मशीन_का_स्थानीय_ip_पता_जानें&amp;quot;&amp;gt;चरण 2: अपने उबुन्टू मशीन का स्थानीय IP पता जानें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_3_अपने_बॉक्स_पर_पोर्ट_फॉरवर्डिंग_सेट_अप_करें&amp;quot;&amp;gt;चरण 3: अपने बॉक्स पर पोर्ट फॉरवर्डिंग सेट अप करें&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_प्रशासन_इंटरफ़ेस_तक_पहुँच&amp;quot;&amp;gt;प्रशासन इंटरफ़ेस तक पहुँच&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_रीडायरेक्शन_की_कॉन्फ़िगरेशन&amp;quot;&amp;gt;रीडायरेक्शन की कॉन्फ़िगरेशन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_4_ubuntu_पर_सेवा_की_कॉन्फ़िगरेशन&amp;quot;&amp;gt;चरण 4: Ubuntu पर सेवा की कॉन्फ़िगरेशन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_5_ubuntu_फ़ायरवॉल_कॉन्फ़िगरेशन&amp;quot;&amp;gt;चरण 5: Ubuntu फ़ायरवॉल कॉन्फ़िगरेशन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_चरण_6_परीक्षण_और_सत्यापन&amp;quot;&amp;gt;चरण 6 : परीक्षण और सत्यापन&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_स्थानीय_नेटवर्क_से_परीक्षण&amp;quot;&amp;gt;स्थानीय नेटवर्क से परीक्षण&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_बाहर_से_टेस्ट&amp;quot;&amp;gt;बाहर से टेस्ट&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अच्छी_प्रथाएँ_और_सुरक्षा&amp;quot;&amp;gt;अच्छी प्रथाएँ और सुरक्षा&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_मूल_सुरक्षा&amp;quot;&amp;gt;मूल सुरक्षा&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_कनेक्शन_मॉनिटरिंग&amp;quot;&amp;gt;कनेक्शन मॉनिटरिंग&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_रेवर्स_प्रॉक्सी_का_उपयोग&amp;quot;&amp;gt;रेवर्स प्रॉक्सी का उपयोग&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पोर्ट_फॉरवर्डिंग_के_विकल्प&amp;quot;&amp;gt;पोर्ट फॉरवर्डिंग के विकल्प&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_क्लाउड_समाधान&amp;quot;&amp;gt;क्लाउड समाधान&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_vps_और_रिवर्स_प्रॉक्सी&amp;quot;&amp;gt;VPS और रिवर्स प्रॉक्सी&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_निवारण&amp;quot;&amp;gt;समस्या निवारण&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सामान्य_समस्याएँ&amp;quot;&amp;gt;सामान्य समस्याएँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_नेटवर्क_डिबग&amp;quot;&amp;gt;नेटवर्क डिबग&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;लक्षित दर्शक : मध्यम&amp;lt;/div&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;अनुमानित पूर्वापेक्षाएँ&amp;lt;/strong&amp;gt; : Ubuntu का बुनियादी ज्ञान, टर्मिनल का बुनियादी ज्ञान, मूल नेटवर्क अवधारणाएँ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;तकनीकी अवधारणाएँ&amp;lt;/strong&amp;gt; : NAT, पोर्ट फ़ॉरवर्डिंग, फ़ायरवॉल, रिवर्स प्रॉक्सी&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;सिस्टम कमांडें&amp;lt;/strong&amp;gt; : टर्मिनल का उपयोग, नेटवर्क कॉन्फ़िगरेशन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;उन्नत अनुभाग&amp;lt;/strong&amp;gt; : निगरानी, सुरक्षा, क्लाउड विकल्प&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या_nat_और_निजी_पते&amp;quot;&amp;gt;समस्या: NAT और निजी पते&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;समस्या : क्या आप अपनी Ubuntu मशीन पर एक वेब एप्लिकेशन विकसित कर रहे हैं और अपने घरेलू नेटवर्क के बाहर से इसे सुलभ बनाना चाहते हैं ? आप सही जगह पर हैं ! इस लेख में, हम देखेंगे कि आप अपने बॉक्स इंटरनेट पर पोर्ट फ़ॉरवर्डिंग कॉन्फ़िगर करके एक स्थानीय सेवा (उदाहरण के लिए पोर्ट 8080 पर) को इंटरनेट तक कैसे प्रदर्शित कर सकते हैं।&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;डिफ़ॉल्ट रूप से, आपके इंटरनेट बॉक्स का NAT (Network Address Translation) का उपयोग करके आपके घरेलू नेटवर्क के सभी उपकरणों के बीच केवल एक सार्वजनिक IP पता साझा किया जाता है। आपकी स्थानीय मशीनें निजी IP पते (192.168.x.x, 10.x.x.x, आदि) का उपयोग करती हैं, जो इंटरनेट पर रूट करने योग्य नहीं हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जब आप अपनी Ubuntu मशीन पर कोई सेवा शुरू करते हैं (उदाहरण के लिए पोर्ट 8080 पर एक वेब सर्वर), तो वह केवल आपके स्थानीय नेटवर्क से ही सुलभ होता है। इसे इंटरनेट से सुलभ बनाने के लिए, हमें एक पोर्ट फ़ॉरवर्डिंग कॉन्फ़िगर करने की आवश्यकता होती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_चरण_1_अपना_सार्वजनिक_ip_पता_पहचानें&amp;quot;&amp;gt;चरण 1: अपना सार्वजनिक IP पता पहचानें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सबसे पहले, अपने इंटरनेट कनेक्शन का सार्वजनिक IP पता प्राप्त करें:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Plusieurs méthodes au choix
curl ifconfig.me
curl ipecho.net/plain
wget -qO- http://ipecho.net/plain

# Ou encore
curl -s checkip.amazonaws.com&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह IP पता वही है जिसका उपयोग इंटरनेट उपयोगकर्ता आपकी सेवा तक पहुँचने के लिए करेंगे।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_चरण_2_अपने_उबुन्टू_मशीन_का_स्थानीय_ip_पता_जानें&amp;quot;&amp;gt;चरण 2: अपने उबुन्टू मशीन का स्थानीय IP पता जानें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आपकी Ubuntu मशीन के पास आपके स्थानीय नेटवर्क पर एक निजी IP पता है। जानने के लिए:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Afficher toutes les interfaces réseau
ip addr show

# Ou plus spécifiquement pour l&amp;#39;interface principale
ip route get 1.1.1.1 | awk &amp;#39;{print $7; exit}&amp;#39;

# Alternative avec hostname
hostname -I | awk &amp;#39;{print $1}&amp;#39;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस पते को नोट करें (उदाहरण के लिए`192.168.1.100`), हमें इसे कॉन्फ़िगरेशन के लिए चाहिए होगा।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_चरण_3_अपने_बॉक्स_पर_पोर्ट_फॉरवर्डिंग_सेट_अप_करें&amp;quot;&amp;gt;चरण 3: अपने बॉक्स पर पोर्ट फॉरवर्डिंग सेट अप करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;कॉन्फ़िगरेशन आपके बॉक्स के मॉडल के अनुसार भिन्न होता है, लेकिन सिद्धांत समान रहता है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_प्रशासन_इंटरफ़ेस_तक_पहुँच&amp;quot;&amp;gt;प्रशासन इंटरफ़ेस तक पहुँच&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपने ब्राउज़र को खोलें और अपने बॉक्स के वेब इंटरफ़ेस पर जाएँ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;फ्रीबॉक्स&amp;lt;/strong&amp;gt;:`192.168.1.1` ou &amp;lt;code&amp;gt;mafreebox.freebox.fr&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;लाइवबॉक्स ऑरेंज&amp;lt;/strong&amp;gt;&amp;lt;code class=&amp;quot;No output&amp;quot;&amp;gt;192.168.1.1&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;SFR बॉक्स&amp;lt;/strong&amp;gt;(No output)&amp;lt;code&amp;gt;192.168.1.1&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Bbox Bouygues&amp;lt;/strong&amp;gt;(No output)&amp;lt;code&amp;gt;192.168.1.254&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_रीडायरेक्शन_की_कॉन्फ़िगरेशन&amp;quot;&amp;gt;रीडायरेक्शन की कॉन्फ़िगरेशन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पोर्ट फॉरवर्डिंग के लिए समर्पित खंड की तलाश करें (नाम भिन्न हो सकते हैं):&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;पोर्ट रीडायरेक्शन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;NAT/PAT&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;पोर्ट फॉरवर्डिंग&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;गेम सर्वर&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इन सेटिंग्स के साथ एक नया नियम बनाएँ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 25%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 75%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;क्षेत्र&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;मूल्य&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;नाम/विवरण&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Ubuntu वेब सेवा&amp;quot; (या कोई अन्य स्पष्ट नाम)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;बाहरी पोर्ट (या सार्वजनिक पोर्ट)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;8080&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;आंतरिक IP पता&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;आपकी Ubuntu मशीन का IP (उदाहरण: 192.168.1.100)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;आंतरिक पोर्ट (या निजी पोर्ट)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;8080&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;प्रोटोकॉल&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;TCP&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;राज्य&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;सक्रिय&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_चरण_4_ubuntu_पर_सेवा_की_कॉन्फ़िगरेशन&amp;quot;&amp;gt;चरण 4: Ubuntu पर सेवा की कॉन्फ़िगरेशन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सुनिश्चित करें कि आपका सेवा सभी इंटरफेस पर सुनता है, केवल localhost पर नहीं:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# ✅ Correct : écoute sur toutes les interfaces
python3 -m http.server 8080 --bind 0.0.0.0

# ❌ Incorrect : écoute seulement en local
python3 -m http.server 8080 --bind 127.0.0.1&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जाँचने के लिए कि आपका सेवा सही ढंग से सुन रहा है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Vérifier les ports en écoute
sudo netstat -tlnp | grep :8080
# ou avec ss (plus moderne)
sudo ss -tlnp | grep :8080&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आपको कुछ ऐसा देखना चाहिए`0.0.0.0:8080`और नहीं`127.0.0.1:8080`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_चरण_5_ubuntu_फ़ायरवॉल_कॉन्फ़िगरेशन&amp;quot;&amp;gt;चरण 5: Ubuntu फ़ायरवॉल कॉन्फ़िगरेशन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ubuntu डिफ़ॉल्ट रूप से UFW (Uncomplicated Firewall) का उपयोग करता है। स्थिति जाँचें और आवश्यकतानुसार पोर्ट की अनुमति दें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Vérifier le statut du pare-feu
sudo ufw status

# Si le pare-feu est actif, autoriser le port 8080
sudo ufw allow 8080/tcp

# Ou plus spécifiquement pour un service web
sudo ufw allow &amp;#39;Apache&amp;#39;  # si vous utilisez Apache
sudo ufw allow &amp;#39;Nginx Full&amp;#39;  # si vous utilisez Nginx&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_चरण_6_परीक्षण_और_सत्यापन&amp;quot;&amp;gt;चरण 6 : परीक्षण और सत्यापन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_स्थानीय_नेटवर्क_से_परीक्षण&amp;quot;&amp;gt;स्थानीय नेटवर्क से परीक्षण&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पहले, अपने स्थानीय नेटवर्क पर किसी अन्य मशीन से पहुँच का परीक्षण करें:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Remplacez par l&amp;#39;IP locale de votre machine Ubuntu
curl http://192.168.1.100:8080&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_बाहर_से_टेस्ट&amp;quot;&amp;gt;बाहर से टेस्ट&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अब, अपने सार्वजनिक IP का उपयोग करके इंटरनेट से परीक्षण करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Remplacez par votre IP publique
curl http://VOTRE_IP_PUBLIQUE:8080&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आप ऑनलाइन उपकरणों का भी उपयोग कर सकते हैं :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://www.yougetsignal.com/tools/open-ports/&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://www.yougetsignal.com/tools/open-ports/&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://canyouseeme.org/&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://canyouseeme.org/&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_अच्छी_प्रथाएँ_और_सुरक्षा&amp;quot;&amp;gt;अच्छी प्रथाएँ और सुरक्षा&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_मूल_सुरक्षा&amp;quot;&amp;gt;मूल सुरक्षा&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Configurer fail2ban pour protéger contre les attaques par force brute
sudo apt update &amp;amp;amp;&amp;amp;amp; sudo apt install fail2ban

# Limiter l&amp;#39;accès avec UFW (exemple : autoriser seulement certaines IP)
sudo ufw allow from 203.0.113.0/24 to any port 8080&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_कनेक्शन_मॉनिटरिंग&amp;quot;&amp;gt;कनेक्शन मॉनिटरिंग&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Surveiller les connexions en temps réel
sudo netstat -an | grep :8080

# Logs des connexions (selon votre application)
sudo tail -f /var/log/nginx/access.log  # pour Nginx
sudo journalctl -f -u your-service      # pour un service systemd&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_रेवर्स_प्रॉक्सी_का_उपयोग&amp;quot;&amp;gt;रेवर्स प्रॉक्सी का उपयोग&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;बेहतर सुरक्षा और लचीलापन के लिए, नginx जैसे रिवर्स प्रॉक्सी का उपयोग करने पर विचार करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-nginx&amp;quot; data-lang=&amp;quot;nginx&amp;quot;&amp;gt;server {
    listen 80;
    server_name votre-domaine.com;

    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_पोर्ट_फॉरवर्डिंग_के_विकल्प&amp;quot;&amp;gt;पोर्ट फॉरवर्डिंग के विकल्प&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_क्लाउड_समाधान&amp;quot;&amp;gt;क्लाउड समाधान&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;ngrok&amp;lt;/strong&amp;gt;: सुरक्षित अस्थायी सुरंग&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Cloudflare टनल&amp;lt;/strong&amp;gt;नि:शुल्क और सुरक्षित समाधान&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;serveo.net&amp;lt;/strong&amp;gt;: सरल SSH टनल&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Exemple avec ngrok
ngrok http 8080

# Exemple avec serveo
ssh -R 80:localhost:8080 serveo.net&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_vps_और_रिवर्स_प्रॉक्सी&amp;quot;&amp;gt;VPS और रिवर्स प्रॉक्सी&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पेशेवर उपयोग के लिए, VPN के माध्यम से आपके स्थानीय बुनियादी ढाँचे की ओर इशारा करते हुए एक रिवर्स प्रॉक्सी के साथ VPS का उपयोग करने पर विचार करें।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या_निवारण&amp;quot;&amp;gt;समस्या निवारण&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_सामान्य_समस्याएँ&amp;quot;&amp;gt;सामान्य समस्याएँ&amp;lt;/h3&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 40%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 60%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;thead&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;समस्या&amp;lt;/th&amp;gt;
&amp;lt;th class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;हल&amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;बाहर से सेवा असुलभ&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;पोर्ट फ़ॉरवर्डिंग कॉन्फ़िगरेशन की जाँच करें और सुनिश्चित करें कि सेवा 0.0.0.0 पर सुन रही है&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;कनेक्शन अस्वीकारित&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;सेवा शुरू नहीं हुई है या यह केवल 127.0.0.1 पर सुन रही है&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;कनेक्शन टाइमआउट&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;फ़ायरवॉल (बॉक्स या Ubuntu) की समस्या या पोर्ट फ़ॉरवर्डिंग का गलत कॉन्फ़िगरेशन&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;सार्वजनिक IP नियमित रूप से बदलता है&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक डायनामिक DNS (DynDNS, No-IP, आदि) कॉन्फ़िगर करें।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_नेटवर्क_डिबग&amp;quot;&amp;gt;नेटवर्क डिबग&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;# Tester la connectivité locale
telnet localhost 8080

# Tester depuis une autre machine du réseau
telnet 192.168.1.100 8080

# Vérifier les routes réseau
ip route show

# Analyser le trafic réseau
sudo tcpdump -i any port 8080&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इंटरनेट पर एक स्थानीय सेवा को उजागर करने के लिए पोर्ट फॉरवर्डिंग, सुरक्षा और निगरानी की सावधानीपूर्वक कॉन्फ़िगरेशन की आवश्यकता होती है। यद्यपि यह दृष्टिकोण विकास या व्यक्तिगत परियोजनाओं के लिए आदर्श है, उत्पादन उपयोग के लिए अधिक मज़बूत विकल्प (VPS, CDN, क्लाउड सेवाओं) पर विचार करें।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;महत्वपूर्ण है कि आप हमेशा सुरक्षा को ध्यान में रखें: मजबूत पासवर्ड उपयोग करें, अपने सिस्टम को नियमित रूप से अपडेट करें, और अपने उजागर सेवाओं तक पहुँच की निगरानी करें।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपने अनुभव और प्रश्न टिप्पणियों में साझा करने में संकोच न करें !&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>मॉकिटो डिबगिंग: &quot;Wanted but not invoked&quot; त्रुटि को प्लगइन Gradle के परीक्षणों में हल करें</title>
            <link >https://cheroliv.com/blog/2025/0099_debugging-mockito-gradle-plugin_post.html</link>
            <pubDate>Sun, 17 Nov 2024 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2025/0099_debugging-mockito-gradle-plugin_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Table des matières&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संदर्भ_प्लगइन_ग्रेडल_बेकरी&amp;quot;&amp;gt;संदर्भ: प्लगइन ग्रेडल बेकरी&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_1_खराब_मॉक_की_जाँच_करें&amp;quot;&amp;gt;समस्या #1: खराब मॉक की जाँच करें&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निदान&amp;quot;&amp;gt;निदान&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समाधान&amp;quot;&amp;gt;समाधान&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_2_सिलसिलेवार_unfinishedstubbingexception&amp;quot;&amp;gt;समस्या #2 : सिलसिलेवार UnfinishedStubbingException&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निदान_2&amp;quot;&amp;gt;निदान&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समाधान_2&amp;quot;&amp;gt;समाधान&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_3_कॉन्फ़िगरेशन_फ़ाइल_मौजूद_नहीं_है&amp;quot;&amp;gt;समस्या #3: कॉन्फ़िगरेशन फ़ाइल मौजूद नहीं है&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निदान_3&amp;quot;&amp;gt;निदान&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समाधान_3&amp;quot;&amp;gt;समाधान&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समस्या_4_afterevaluate_और_nullpointerexception&amp;quot;&amp;gt;समस्या #4 : afterEvaluate और NullPointerException&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निदान_4&amp;quot;&amp;gt;निदान&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_समाधान_4&amp;quot;&amp;gt;समाधान&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पूर्ण_समाधान&amp;quot;&amp;gt;पूर्ण समाधान&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सीखे_गए_सबक&amp;quot;&amp;gt;सीखे गए सबक&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_1_सही_मॉक_की_जाँच_करें&amp;quot;&amp;gt;1. सही मॉक की जाँच करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_2_नेस्टेड_मॉक_से_बचें&amp;quot;&amp;gt;2. नेस्टेड मॉक से बचें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_3_मूल्यांकन_कॉलबैक_को_मॉक_करें&amp;quot;&amp;gt;3. मूल्यांकन कॉलबैक को मॉक करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_4_पथों_के_समाधान_का_परीक्षण_करें&amp;quot;&amp;gt;4. पथों के समाधान का परीक्षण करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अंतिम_परीक्षण_आर्किटेक्चर&amp;quot;&amp;gt;अंतिम परीक्षण आर्किटेक्चर&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संसाधन&amp;quot;&amp;gt;संसाधन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Gradle प्लगइन के विकास के दौरान&amp;lt;strong&amp;gt;बेकरी&amp;lt;/strong&amp;gt;मेरे JBake ब्लॉग के लिए, मुझे एक स्पष्ट रूप से सरल समस्या का सामना करना पड़ा: एक इकाई परीक्षण जो त्रुटि के साथ विफल हो रहा था`Wanted but not invoked`. क्या दिख रहा था कि एक तुच्छ बग था, वह साबित हुआ Mockito और Kotlin के साथ मॉकिंग की सूक्ष्मताओं को समझने के लिए एक आदर्श केस स्टडी।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस लेख में, मैं आपको एक विधिपूर्वक डिबगिंग की यात्रा पर ले जाता हूँ, जहाँ प्रत्येक समाधान एक नई समस्या को उजागर करता है, अंतिम समाधान तक।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_संदर्भ_प्लगइन_ग्रेडल_बेकरी&amp;quot;&amp;gt;संदर्भ: प्लगइन ग्रेडल बेकरी&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Bakery प्लगिन JBake के चारों ओर एक रैपर है जो स्थिर साइटों के प्रकाशन को आसान बनाता है। इसकी सरलीकृत संरचना यहाँ है :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;class BakeryPlugin : Plugin&amp;amp;lt;Project&amp;amp;gt; {
    override fun apply(project: Project) {
        val extension = project.extensions.create(
            &amp;quot;bakery&amp;quot;,
            BakeryExtension::class.java
        )

        project.afterEvaluate {
            if (!project.layout.projectDirectory.asFile
                    .resolve(extension.configPath.get()).exists()) {
                println(&amp;quot;config file does not exists&amp;quot;)
            } else {
                // C&amp;#39;EST ICI QUE ÇA SE PASSE
                project.plugins.apply(JBakePlugin::class.java)

                val site = FileSystemManager.from(project, extension.configPath.get())
                // Configuration de JBake...
            }
        }
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;असफल होने वाला परीक्षण सरल था :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;@Test
fun `plugin applies jbake gradle plugin`() {
    val project = createMockProject()
    val plugin = BakeryPlugin()

    plugin.apply(project)

    verify(project.plugins).apply(JBakePlugin::class.java)
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;त्रुटि :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;Wanted but not invoked:
pluginContainer.apply(class org.jbake.gradle.JBakePlugin);
Actually, there were zero interactions with this mock.&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या_1_खराब_मॉक_की_जाँच_करें&amp;quot;&amp;gt;समस्या #1: खराब मॉक की जाँच करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_निदान&amp;quot;&amp;gt;निदान&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/mockito-problem-1.svg&amp;quot; alt=&amp;quot;mockito problem 1&amp;quot; width=&amp;quot;676&amp;quot; height=&amp;quot;521&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;समस्या: Mockito इंटरैक्शन को ट्रेस नहीं कर सकता`project.plugins`क्योंकि यह केवल एक गेटर है जो वास्तविक मॉक लौटाता है`mockPluginContainer`सत्यापन मॉक के इंस्टेंस पर सीधे किया जाना चाहिए।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_समाधान&amp;quot;&amp;gt;समाधान&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;संपादित`createMockProject()`दो ऑब्जेक्ट्स लौटाने के लिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;private fun createMockProject(): Pair&amp;amp;lt;Project, PluginContainer&amp;amp;gt; {
    val mockPluginContainer = mock&amp;amp;lt;PluginContainer&amp;amp;gt;()
    val mockProject = mock&amp;amp;lt;Project&amp;amp;gt; {
        on { plugins } doReturn mockPluginContainer
    }
    return Pair(mockProject, mockPluginContainer)
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;और परीक्षा को अनुकूलित करें:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;@Test
fun `plugin applies jbake gradle plugin`() {
    val (project, mockPluginContainer) = createMockProject()
    val plugin = BakeryPlugin()

    plugin.apply(project)

    // ✅ Vérification directe sur le bon mock
    verify(mockPluginContainer).apply(JBakePlugin::class.java)
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या_2_सिलसिलेवार_unfinishedstubbingexception&amp;quot;&amp;gt;समस्या #2 : सिलसिलेवार UnfinishedStubbingException&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_निदान_2&amp;quot;&amp;gt;निदान&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पहला सुधार लागू होने के बाद, एक नई त्रुटि सामने आई :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-text hljs&amp;quot; data-lang=&amp;quot;text&amp;quot;&amp;gt;UnfinishedStubbingException:
Unfinished stubbing detected here
Hints:
 3. you are stubbing the behaviour of another mock inside
    before &amp;#39;thenReturn&amp;#39; instruction is completed&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;समस्याग्रस्त कोड Mockito-Kotlin की DSL सिंटैक्स का उपयोग कर रहा था :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;val mockProject = mock&amp;amp;lt;Project&amp;amp;gt; {
    on { extensions } doReturn mockExtensionContainer
    on { plugins } doReturn mockPluginContainer
    on { logger } doReturn mock()  // ❌ PROBLÈME ICI !
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 4) ]

@startuml
participant &amp;quot;Mockito&amp;quot; as M
participant &amp;quot;मॉक बिल्डर&amp;quot; as MB
participant &amp;quot;python
^^^^^
 Syntax Error? (Assumed diagram type: sequence)

@startuml
participant &amp;quot;Mockito&amp;quot; as M
participant &amp;quot;मॉक बिल्डर&amp;quot; as MB
participant &amp;quot;python
इनलाइन मॉक&amp;quot; as IM

M -&amp;amp;gt; MB: mock&amp;amp;lt;Project&amp;amp;gt; { ... }
activate MB
MB -&amp;amp;gt; MB: on { logger } doReturn
MB -&amp;amp;gt; IM: mock()
activate IM
note right
  ❌ Création d&amp;#39;un nouveau mock
  PENDANT le stubbing en cours !

  Mockito perd le contexte
  du stubbing parent
end note
IM --&amp;amp;gt; MB: nouveau mock
deactivate IM
MB -x M: UnfinishedStubbingException
deactivate MB
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_समाधान_2&amp;quot;&amp;gt;समाधान&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;बनाना&amp;lt;strong&amp;gt;सभी&amp;lt;/strong&amp;gt;किसी भी स्टबिंग ब्लॉक के बाहर के मॉक, फिर उन्हेंconfigure करने के साथ`whenever()`(No output)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;private fun createMockProject(): Pair&amp;amp;lt;Project, PluginContainer&amp;amp;gt; {
    // 1️⃣ Créer TOUS les mocks d&amp;#39;abord
    val mockPluginContainer = mock&amp;amp;lt;PluginContainer&amp;amp;gt;()
    val mockExtensionContainer = mock&amp;amp;lt;ExtensionContainer&amp;amp;gt;()
    val mockLogger = mock&amp;amp;lt;org.gradle.api.logging.Logger&amp;amp;gt;()
    val mockProject = mock&amp;amp;lt;Project&amp;amp;gt;()

    // 2️⃣ Configurer les mocks séparément avec whenever()
    whenever(mockProject.plugins).thenReturn(mockPluginContainer)
    whenever(mockProject.extensions).thenReturn(mockExtensionContainer)
    whenever(mockProject.logger).thenReturn(mockLogger)

    return Pair(mockProject, mockPluginContainer)
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock tip&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-tip&amp;quot; title=&amp;quot;Tip&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;स्वर्ण नियम&amp;lt;/strong&amp;gt;कभी कॉल न करें`mock()`मॉक कॉन्फ़िगरेशन ब्लॉक के अंदर. हमेशा पहले मॉक बनाएं, फिर उन्हें कॉन्फ़िगर करें।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या_3_कॉन्फ़िगरेशन_फ़ाइल_मौजूद_नहीं_है&amp;quot;&amp;gt;समस्या #3: कॉन्फ़िगरेशन फ़ाइल मौजूद नहीं है&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_निदान_3&amp;quot;&amp;gt;निदान&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हालांकि सही मॉक के साथ, परीक्षण हमेशा विफल रहता था क्योंकि प्लगिन को कॉन्फ़िगरेशन फ़ाइल नहीं मिल रही थी :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// Dans BakeryPlugin.kt
if (!project.layout.projectDirectory.asFile
        .resolve(extension.configPath.get()).exists()) {
    println(&amp;quot;config file does not exists&amp;quot;)
    return@afterEvaluate  // ❌ Sort avant d&amp;#39;appliquer JBake !
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/mockito-problem-3.svg&amp;quot; alt=&amp;quot;mockito problem 3&amp;quot; width=&amp;quot;551&amp;quot; height=&amp;quot;373&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_समाधान_3&amp;quot;&amp;gt;समाधान&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पाथ रिज़ॉल्यूशन काम करने के लिए मॉक को कॉन्फ़िगर करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;private fun createMockProject(): Pair&amp;amp;lt;Project, PluginContainer&amp;amp;gt; {
    // ... autres mocks ...

    val configFile = File(&amp;quot;../../site.yml&amp;quot;).canonicalFile
    val projectDir = configFile.parentFile

    // Configuration cohérente des chemins
    whenever(mockConfigPathProperty.get()).thenReturn(&amp;quot;site.yml&amp;quot;)
    whenever(mockProjectDirectory.asFile).thenReturn(projectDir)

    // Maintenant : projectDir.resolve(&amp;quot;site.yml&amp;quot;) existe ! ✅
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/path-resolution.svg&amp;quot; alt=&amp;quot;path resolution&amp;quot; width=&amp;quot;1759&amp;quot; height=&amp;quot;5592&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समस्या_4_afterevaluate_और_nullpointerexception&amp;quot;&amp;gt;समस्या #4 : afterEvaluate और NullPointerException&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_निदान_4&amp;quot;&amp;gt;निदान&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;प्लगिन JBake को एक ब्लॉक में लागू करता है`afterEvaluate`, और पहुँचता है`buildDirectory.dir()`(No output)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;project.afterEvaluate {
    // ...
    project.tasks.withType(JBakeTask::class.java)
        .getByName(&amp;quot;bake&amp;quot;).apply {
            output = project.layout.buildDirectory
                .dir(site.bake.destDirPath)  // ❌ NPE ici !
                .get()
                .asFile
        }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मॉक का`buildDirectory.dir()&amp;lt;code&amp;gt;वह वापस आ रहा था`null&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_समाधान_4&amp;quot;&amp;gt;समाधान&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मॉकर`afterEvaluate`ताकि वह तुरंत चल सके, और पूरी तरह से कॉन्फ़िगर करें`buildDirectory`(no output)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;private fun createMockProject(): Pair&amp;amp;lt;Project, PluginContainer&amp;amp;gt; {
    // ... autres mocks ...

    val mockBuildDirectory = mock&amp;amp;lt;DirectoryProperty&amp;amp;gt;()
    val buildDir = File(projectDir, &amp;quot;build&amp;quot;)

    // Mocker dir() pour retourner un Provider valide
    whenever(mockBuildDirectory.dir(any&amp;amp;lt;String&amp;amp;gt;())).doAnswer { invocation -&amp;amp;gt;
        val path = invocation.arguments[0] as String
        val mockDirProvider = mock&amp;amp;lt;Provider&amp;amp;lt;Directory&amp;amp;gt;&amp;amp;gt;()
        val mockDir = mock&amp;amp;lt;Directory&amp;amp;gt;()

        whenever(mockDir.asFile).thenReturn(File(buildDir, path))
        whenever(mockDirProvider.get()).thenReturn(mockDir)

        mockDirProvider
    }

    // Mocker afterEvaluate pour exécution immédiate
    whenever(mockProject.afterEvaluate(any&amp;amp;lt;Action&amp;amp;lt;Project&amp;amp;gt;&amp;amp;gt;())).doAnswer { invocation -&amp;amp;gt;
        val action = invocation.arguments[0] as Action&amp;amp;lt;Project&amp;amp;gt;
        action.execute(mockProject)  // ✅ Exécution synchrone
        null
    }

    return Pair(mockProject, mockPluginContainer)
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/after-evaluate-flow.svg&amp;quot; alt=&amp;quot;after evaluate flow&amp;quot; width=&amp;quot;807&amp;quot; height=&amp;quot;357&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_पूर्ण_समाधान&amp;quot;&amp;gt;पूर्ण समाधान&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ फ़ंक्शन है`createMockProject()`अंतिम, जो सभी समस्याओं को हल करता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;private fun createMockProject(): Pair&amp;amp;lt;Project, PluginContainer&amp;amp;gt; {
    // 1️⃣ CRÉER tous les mocks (pas de nested mocks !)
    val mockPluginContainer = mock&amp;amp;lt;PluginContainer&amp;amp;gt;()
    val mockExtensionContainer = mock&amp;amp;lt;ExtensionContainer&amp;amp;gt;()
    val mockLogger = mock&amp;amp;lt;org.gradle.api.logging.Logger&amp;amp;gt;()
    val mockTaskContainer = mock&amp;amp;lt;TaskContainer&amp;amp;gt;()
    val mockConfigPathProperty = mock&amp;amp;lt;Property&amp;amp;lt;String&amp;amp;gt;&amp;amp;gt;()
    val mockBakeryExtension = mock&amp;amp;lt;BakeryExtension&amp;amp;gt;()
    val mockProjectDirectory = mock&amp;amp;lt;Directory&amp;amp;gt;()
    val mockBuildDirectory = mock&amp;amp;lt;DirectoryProperty&amp;amp;gt;()
    val mockProjectLayout = mock&amp;amp;lt;ProjectLayout&amp;amp;gt;()
    val mockProject = mock&amp;amp;lt;Project&amp;amp;gt;()

    // 2️⃣ CONFIGURER la résolution des chemins
    val configFile = File(&amp;quot;../../site.yml&amp;quot;).canonicalFile
    val projectDir = configFile.parentFile
    val buildDir = File(projectDir, &amp;quot;build&amp;quot;)

    whenever(mockConfigPathProperty.get()).thenReturn(&amp;quot;site.yml&amp;quot;)
    whenever(mockConfigPathProperty.isPresent).thenReturn(true)
    whenever(mockBakeryExtension.configPath).thenReturn(mockConfigPathProperty)
    whenever(mockProjectDirectory.asFile).thenReturn(projectDir)

    // 3️⃣ CONFIGURER buildDirectory avec dir()
    whenever(mockBuildDirectory.dir(any&amp;amp;lt;String&amp;amp;gt;())).doAnswer { invocation -&amp;amp;gt;
        val path = invocation.arguments[0] as String
        val mockDirProvider = mock&amp;amp;lt;Provider&amp;amp;lt;Directory&amp;amp;gt;&amp;amp;gt;()
        val mockDir = mock&amp;amp;lt;Directory&amp;amp;gt;()
        whenever(mockDir.asFile).thenReturn(File(buildDir, path))
        whenever(mockDirProvider.get()).thenReturn(mockDir)
        mockDirProvider
    }

    // 4️⃣ ASSEMBLER le projet
    whenever(mockProjectLayout.projectDirectory).thenReturn(mockProjectDirectory)
    whenever(mockProjectLayout.buildDirectory).thenReturn(mockBuildDirectory)

    whenever(mockExtensionContainer.create(&amp;quot;bakery&amp;quot;, BakeryExtension::class.java))
        .thenReturn(mockBakeryExtension)
    whenever(mockExtensionContainer.getByType(BakeryExtension::class.java))
        .thenReturn(mockBakeryExtension)

    whenever(mockProject.extensions).thenReturn(mockExtensionContainer)
    whenever(mockProject.plugins).thenReturn(mockPluginContainer)
    whenever(mockProject.tasks).thenReturn(mockTaskContainer)
    whenever(mockProject.layout).thenReturn(mockProjectLayout)
    whenever(mockProject.logger).thenReturn(mockLogger)
    whenever(mockProject.projectDir).thenReturn(projectDir)

    // 5️⃣ CONFIGURER afterEvaluate pour exécution immédiate
    whenever(mockProject.afterEvaluate(any&amp;amp;lt;Action&amp;amp;lt;Project&amp;amp;gt;&amp;amp;gt;())).doAnswer { invocation -&amp;amp;gt;
        val action = invocation.arguments[0] as Action&amp;amp;lt;Project&amp;amp;gt;
        action.execute(mockProject)
        null
    }

    return Pair(mockProject, mockPluginContainer)
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;और अंतिम परीक्षा जो पास होती है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;@Test
fun `plugin applies jbake gradle plugin`() {
    val (project, mockPluginContainer) = createMockProject()
    val plugin = BakeryPlugin()

    plugin.apply(project)

    verify(mockPluginContainer).apply(JBakePlugin::class.java) // ✅ SUCCÈS !
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_सीखे_गए_सबक&amp;quot;&amp;gt;सीखे गए सबक&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;./images/lessons-learned.svg&amp;quot; alt=&amp;quot;lessons learned&amp;quot; width=&amp;quot;748&amp;quot; height=&amp;quot;472&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_1_सही_मॉक_की_जाँच_करें&amp;quot;&amp;gt;1. सही मॉक की जाँच करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// ❌ FAUX
verify(project.plugins).apply(JBakePlugin::class.java)

// ✅ CORRECT
val (project, mockPluginContainer) = createMockProject()
verify(mockPluginContainer).apply(JBakePlugin::class.java)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_2_नेस्टेड_मॉक_से_बचें&amp;quot;&amp;gt;2. नेस्टेड मॉक से बचें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// ❌ FAUX - UnfinishedStubbingException
val mockProject = mock&amp;amp;lt;Project&amp;amp;gt; {
    on { logger } doReturn mock()  // Nested mock creation !
}

// ✅ CORRECT - Créer séparément
val mockLogger = mock&amp;amp;lt;org.gradle.api.logging.Logger&amp;amp;gt;()
val mockProject = mock&amp;amp;lt;Project&amp;amp;gt;()
whenever(mockProject.logger).thenReturn(mockLogger)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_3_मूल्यांकन_कॉलबैक_को_मॉक_करें&amp;quot;&amp;gt;3. मूल्यांकन कॉलबैक को मॉक करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// ✅ afterEvaluate doit s&amp;#39;exécuter pour les tests
whenever(mockProject.afterEvaluate(any())).doAnswer { invocation -&amp;amp;gt;
    val action = invocation.arguments[0] as Action&amp;amp;lt;Project&amp;amp;gt;
    action.execute(mockProject)
    null
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_4_पथों_के_समाधान_का_परीक्षण_करें&amp;quot;&amp;gt;4. पथों के समाधान का परीक्षण करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin hljs&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;// Toujours vérifier que les chemins se résolvent correctement
val extension = project.extensions.getByType(BakeryExtension::class.java)
val configPath = extension.configPath.get()
val projectDir = project.layout.projectDirectory.asFile
val resolvedConfig = projectDir.resolve(configPath)

println(&amp;quot;Resolved config: ${resolvedConfig.absolutePath}&amp;quot;)
println(&amp;quot;Exists: ${resolvedConfig.exists()}&amp;quot;)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_अंतिम_परीक्षण_आर्किटेक्चर&amp;quot;&amp;gt;अंतिम परीक्षण आर्किटेक्चर&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre&amp;gt;Failed to generate image: PlantUML preprocessing failed: [From &amp;amp;lt;input&amp;amp;gt; (line 20) ]

@startuml
package &amp;quot;परीक्षण परत&amp;quot; {
    [Test Class] --&amp;amp;gt; [createMockProject()]
}

package &amp;quot;मॉक सृजन&amp;quot; {
    [createMockProject()] --&amp;amp;gt; [Create All Mocks]
    [Create All Mocks] --&amp;amp;gt; [Configure Paths]
    [Configure Paths] --&amp;amp;gt; [Configure Callbacks]
    [Configure Callbacks] --&amp;amp;gt; [Assemble Project]
}

package &amp;quot;मॉक ऑब्जेक्ट्स&amp;quot; {
    [Assemble Project] --&amp;amp;gt; [Project Mock]
    [Assemble Project] --&amp;amp;gt; [PluginContainer Mock]
    [Assemble Project] --&amp;amp;gt; [Extension Mocks]
    [Assemble Project] --&amp;amp;gt; [Layout Mocks]
}

package &amp;quot;### ग्रेडल एकीकरण
^^^^^
 Syntax Error? (Assumed diagram type: component)

@startuml
package &amp;quot;परीक्षण परत&amp;quot; {
    [Test Class] --&amp;amp;gt; [createMockProject()]
}

package &amp;quot;मॉक सृजन&amp;quot; {
    [createMockProject()] --&amp;amp;gt; [Create All Mocks]
    [Create All Mocks] --&amp;amp;gt; [Configure Paths]
    [Configure Paths] --&amp;amp;gt; [Configure Callbacks]
    [Configure Callbacks] --&amp;amp;gt; [Assemble Project]
}

package &amp;quot;मॉक ऑब्जेक्ट्स&amp;quot; {
    [Assemble Project] --&amp;amp;gt; [Project Mock]
    [Assemble Project] --&amp;amp;gt; [PluginContainer Mock]
    [Assemble Project] --&amp;amp;gt; [Extension Mocks]
    [Assemble Project] --&amp;amp;gt; [Layout Mocks]
}

package &amp;quot;### ग्रेडल एकीकरण
JBake को JBake Gradle प्लगइन का उपयोग करके या JBake CLI को सीधे बुलाकर Gradle बिल्ड में एकीकृत किया जा सकता है:

```kotlin
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
}&amp;quot; {
    [Test Class] --&amp;amp;gt; [BakeryPlugin]
    [BakeryPlugin] --&amp;amp;gt; [Project Mock]
    [BakeryPlugin] --&amp;amp;gt; [PluginContainer Mock]
}

package &amp;quot;सत्यापन&amp;quot; {
    [Test Class] --&amp;amp;gt; [verify(mockPluginContainer)]
}
@enduml&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जो एक साधारण परीक्षण समस्या लग रहा था, वह एक उत्कृष्ट केस स्टडी का उदाहरण साबित हुआ :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Kotlin के साथ Mockito की सूक्ष्मताएँ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;सही वस्तुओं का मॉक करने का महत्व&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;परीक्षण में असिंक्रोनस कॉलबैक का प्रबंधन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Gradle प्लगिन में पथ समाधान&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;प्रणालीगत डिबगिंग, समस्या की प्रत्येक परत को समझते हुए, ने एक मजबूत और संधारणीय समाधान तक पहुँचने में सक्षम बना दिया।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;admonitionblock tip&amp;quot;&amp;gt;
&amp;lt;table&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;icon&amp;quot;&amp;gt;
&amp;lt;i class=&amp;quot;fa icon-tip&amp;quot; title=&amp;quot;Tip&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;सलाह आपके टेस्ट के लिए&amp;lt;/strong&amp;gt;यदि आप Mockito के साथ &amp;quot;Wanted but not invoked&amp;quot; का सामना करते हैं, तो हमेशा खुद से पूछें:
1. क्या मैं सही mock की जाँच कर रहा हूँ?
2. क्या मेरे सभी मॉक कॉन्फ़िगरेशन ब्लॉक के बाहर बनाए जाते हैं ?
3. क्या मेरे कॉलबैक वास्तव में निष्पादित होते हैं ?
4. क्या मेरे रास्ते सही तरीके से हल हो रहे हैं?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_संसाधन&amp;quot;&amp;gt;संसाधन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/mockito/mockito-kotlin&amp;quot;&amp;gt;Mockito-Kotlin दस्तावेज़&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://docs.gradle.org/current/userguide/custom_plugins.html&amp;quot;&amp;gt;Gradle Plugin Development Guide&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://jbake.org/&amp;quot;&amp;gt;JBake स्टेटिक साइट जनरेटर&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;क्या आपने अपने परीक्षणों में समान समस्याओं का सामना किया है? कृपया टिप्पणियों में अपने अनुभव को साझा करें!&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Kotlin Arrow : Either मोनाड में नेविगेशन में महारत हासिल करना</title>
            <link >https://cheroliv.com/blog/2024/0075_kotlin_arrow-traverse_right_and_left_post.html</link>
            <pubDate>Tue, 24 Sep 2024 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2024/0075_kotlin_arrow-traverse_right_and_left_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_इथर_मोनैड_क्या_है&amp;quot;&amp;gt;इथर मोनैड क्या है ?&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_either_का_उपयोग_क्यों_करें&amp;quot;&amp;gt;Either का उपयोग क्यों करें?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_संदर्भ&amp;quot;&amp;gt;संदर्भ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_विभिन्न_दृष्टिकोण&amp;quot;&amp;gt;विभिन्न दृष्टिकोण&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_पारंपरिक_पद्धति_के_साथ_when&amp;quot;&amp;gt;पारंपरिक पद्धति के साथ `when&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_fold_का_उपयोग_एक_अधिक_संक्षिप्त_दृष्टिकोण_के_लिए&amp;quot;&amp;gt;fold` का उपयोग एक अधिक संक्षिप्त दृष्टिकोण के लिए&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिवर्तन_map_और_mapleft_के_साथ&amp;quot;&amp;gt;परिवर्तन &amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; और &amp;lt;code&amp;gt;mapLeft&amp;lt;/code&amp;gt; के साथ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_त्रुटि_प्रबंधन_के_साथ_getorelse&amp;quot;&amp;gt;त्रुटि प्रबंधन के साथ `getOrElse&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_साइड_कार्रवाई_onleft_और_onright_के_साथ&amp;quot;&amp;gt;साइड कार्रवाई &amp;lt;code&amp;gt;onLeft&amp;lt;/code&amp;gt; और &amp;lt;code&amp;gt;onRight&amp;lt;/code&amp;gt; के साथ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ऑपरेशन_चेनिंग_flatmap_के_साथ&amp;quot;&amp;gt;ऑपरेशन चेनिंग &amp;lt;code&amp;gt;flatMap&amp;lt;/code&amp;gt; के साथ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_द्विदिशात्मक_परिवर्तन_के_साथ_bimap&amp;quot;&amp;gt;द्विदिशात्मक परिवर्तन के साथ `bimap&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_swap_के_साथ_किनारों_को_उलटना&amp;quot;&amp;gt;swap के साथ किनारों को उलटना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_tap_और_tapleft_का_उपयोग&amp;quot;&amp;gt;tap` और &amp;lt;code&amp;gt;tapLeft&amp;lt;/code&amp;gt; का उपयोग:&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_उपयोग_recover&amp;quot;&amp;gt;उपयोग &amp;lt;code&amp;gt;recover&amp;lt;/code&amp;gt; :&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_प्रायोगिक_उपयोग_के_मामले&amp;quot;&amp;gt;प्रायोगिक उपयोग के मामले&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_और_आगे_जाने_के_लिए&amp;quot;&amp;gt;और आगे जाने के लिए&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;&amp;lt;em&amp;gt;लक्षित दर्शक :&amp;lt;/em&amp;gt; मध्यम से उन्नत स्तर के कोटलिन डेवलपर्स&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Kotlin में कार्यात्मक प्रोग्रामिंग की दुनिया में, Arrow लाइब्रेरी शक्तिशाली उपकरण प्रदान करती है जो त्रुटियों और वैकल्पिक मामलों को संभालने के लिए हैं। इन उपकरणों में, मोनैड`Either`यह अपनी दो संभावित स्थितियों को दर्शाने की क्षमता के कारण विशेष है: सफलता (Right) या विफलता (Left)। लेकिन हम इन दो स्थितियों के बीच प्रभावी रूप से नेविगेट कैसे करें? ये हम इस लेख में खोजने वाले हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_इथर_मोनैड_क्या_है&amp;quot;&amp;gt;इथर मोनैड क्या है ?&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एकक`Either`यह दो आपस में अनन्य संभावनाओं का प्रतिनिधित्व करने वाला एक डेटा संरचना है। Kotlin में Arrow के साथ, यह अक्सर किसी ऑपरेशन की सफलता और विफलता के मामलों को प्रबंधित करने के लिए उपयोग की जाती है, पारंपरिक अपवादों का एक शानदार विकल्प प्रदान करती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_either_का_उपयोग_क्यों_करें&amp;quot;&amp;gt;Either का उपयोग क्यों करें?&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;स्पष्ट त्रुटि प्रबंधन : डेवलपर को असफलता के मामलों पर विचार करने के लिए बाध्य करता है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कार्यात्मक संयोजन: असफल हो सकने वाले ऑपरेशनों की श्रृंखलाकरण को सुविधा प्रदान करता है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;प्रकार‑सुरक्षा: त्रुटियाँ प्रकारबद्ध होती हैं, जिससे उनका अधिक सटीक प्रबंधन करना संभव होता है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Pas d&amp;amp;#8217;exceptions : Évite les effets de bord et les interruptions inattendues du flux d&amp;amp;#8217;exécution.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_संदर्भ&amp;quot;&amp;gt;संदर्भ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मान लीजिए कि आप एक REST API विकसित कर रहे हैंhttps://spring.io/projects/spring-boot/[Spring Boot,विंडोज़=पढ़ें बाद में] et &amp;lt;a href=&amp;quot;https://kotlinlang.org/&amp;quot;&amp;gt;Kotlin&amp;lt;/a&amp;gt;, पुस्तकालय का उपयोग करकेhttps://arrow-kt.io/[तीर,विंडोज़=पढ़ें-बाद में]. आपके पास एक फ़ंक्शन है`findOneUserByEmail`जो एक लौटाता है`Either&amp;amp;lt;Throwable, User&amp;amp;gt;`आप इस परिणाम को शालीन और कार्यात्मक ढंग से कैसे संभाल सकते हैं?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हमारे पास एक User क्लास है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;@file:Suppress(
    &amp;quot;RemoveRedundantQualifierName&amp;quot;,
    &amp;quot;MemberVisibilityCanBePrivate&amp;quot;,
    &amp;quot;SqlNoDataSourceInspection&amp;quot;
)

package webapp.users

import arrow.core.Either
import arrow.core.left
import arrow.core.right
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.databind.ObjectMapper
import jakarta.validation.constraints.NotNull
import jakarta.validation.constraints.Pattern
import jakarta.validation.constraints.Size
import org.springframework.beans.factory.getBean
import org.springframework.context.ApplicationContext
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate
import org.springframework.r2dbc.core.DatabaseClient
import org.springframework.r2dbc.core.awaitOne
import org.springframework.r2dbc.core.awaitRowsUpdated
import webapp.core.property.ANONYMOUS_USER
import webapp.core.property.EMPTY_STRING
import webapp.core.utils.AppUtils.cleanField
import webapp.users.EntityModel.Companion.ID_MEMBER
import webapp.users.User.UserDao.Attributes.EMAIL_ATTR
import webapp.users.User.UserDao.Attributes.ID_ATTR
import webapp.users.User.UserDao.Attributes.LANG_KEY_ATTR
import webapp.users.User.UserDao.Attributes.LOGIN_ATTR
import webapp.users.User.UserDao.Attributes.PASSWORD_ATTR
import webapp.users.User.UserDao.Attributes.VERSION_ATTR
import webapp.users.User.UserDao.Constraints.LOGIN_REGEX
import webapp.users.User.UserDao.Fields.EMAIL_FIELD
import webapp.users.User.UserDao.Fields.ID_FIELD
import webapp.users.User.UserDao.Fields.LANG_KEY_FIELD
import webapp.users.User.UserDao.Fields.LOGIN_FIELD
import webapp.users.User.UserDao.Fields.PASSWORD_FIELD
import webapp.users.User.UserDao.Fields.VERSION_FIELD
import webapp.users.User.UserDao.Relations.INSERT
import webapp.users.security.Role
import webapp.users.security.Role.RoleDao
import webapp.users.security.UserRole.UserRoleDao
import java.util.*
import jakarta.validation.constraints.Email as EmailConstraint

data class User(
    override val id: UUID? = null,

    @field:NotNull
    @field:Pattern(regexp = LOGIN_REGEX)
    @field:Size(min = 1, max = 50)
    val login: String,

    @JsonIgnore
    @field:NotNull
    @field:Size(min = 60, max = 60)
    val password: String = EMPTY_STRING,

    @field:EmailConstraint
    @field:Size(min = 5, max = 254)
    val email: String = EMPTY_STRING,

    @JsonIgnore
    val roles: MutableSet&amp;amp;lt;Role&amp;amp;gt; = mutableSetOf(Role(ANONYMOUS_USER)),

    @field:Size(min = 2, max = 10)
    val langKey: String = EMPTY_STRING,

    @JsonIgnore
    val version: Long = -1,
) : EntityModel&amp;amp;lt;UUID&amp;amp;gt;() {

    companion object {
        @JvmStatic
        fun main(args: Array&amp;amp;lt;String&amp;amp;gt;) = println(UserDao.Relations.sqlScript)
    }

    object UserDao {
        object Constraints {
            // Regex for acceptable logins
            const val LOGIN_REGEX =
                &amp;quot;^(?&amp;amp;gt;[a-zA-Z0-9!$&amp;amp;amp;*+=?^_`{|}~.-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)|(?&amp;amp;gt;[_.@A-Za-z0-9-]+)$&amp;quot;
            const val PASSWORD_MIN: Int = 4
            const val PASSWORD_MAX: Int = 16
            const val IMAGE_URL_DEFAULT = &amp;quot;https://placehold.it/50x50&amp;quot;
            const val PHONE_REGEX = &amp;quot;^(\\+|00)?[1-9]\\d{0,49}\$&amp;quot;
        }

        object Members {
            const val PASSWORD_MEMBER = &amp;quot;password&amp;quot;
            const val ROLES_MEMBER = &amp;quot;roles&amp;quot;
        }

        object Fields {
            const val ID_FIELD = &amp;quot;`id`&amp;quot;
            const val LOGIN_FIELD = &amp;quot;`login`&amp;quot;
            const val PASSWORD_FIELD = &amp;quot;`password`&amp;quot;
            const val EMAIL_FIELD = &amp;quot;`email`&amp;quot;
            const val LANG_KEY_FIELD = &amp;quot;`lang_key`&amp;quot;
            const val VERSION_FIELD = &amp;quot;`version`&amp;quot;
        }

        object Attributes {
            val ID_ATTR = ID_FIELD.cleanField()
            val LOGIN_ATTR = LOGIN_FIELD.cleanField()
            val PASSWORD_ATTR = PASSWORD_FIELD.cleanField()
            val EMAIL_ATTR = EMAIL_FIELD.cleanField()
            const val LANG_KEY_ATTR = &amp;quot;langKey&amp;quot;
            val VERSION_ATTR = VERSION_FIELD.cleanField()
        }

        object Relations {
            const val TABLE_NAME = &amp;quot;`user`&amp;quot;
            const val SQL_SCRIPT = &amp;quot;&amp;quot;&amp;quot;
            CREATE TABLE IF NOT EXISTS $TABLE_NAME (
                $ID_FIELD                     UUID default random_uuid() PRIMARY KEY,
                $LOGIN_FIELD                  VARCHAR,
                $PASSWORD_FIELD               VARCHAR,
                $EMAIL_FIELD                  VARCHAR,
                $LANG_KEY_FIELD               VARCHAR,
                $VERSION_FIELD                bigint
            );
            CREATE UNIQUE INDEX IF NOT EXISTS `uniq_idx_user_login`
            ON $TABLE_NAME ($LOGIN_FIELD);
            CREATE UNIQUE INDEX IF NOT EXISTS `uniq_idx_user_email`
            ON $TABLE_NAME ($EMAIL_FIELD);
&amp;quot;&amp;quot;&amp;quot;

            @Suppress(&amp;quot;SqlDialectInspection&amp;quot;)
            const val INSERT = &amp;quot;&amp;quot;&amp;quot;
            insert into $TABLE_NAME (
                $LOGIN_FIELD, $EMAIL_FIELD,
                $PASSWORD_FIELD, $LANG_KEY_FIELD,
                $VERSION_FIELD
            ) values ( :login, :email, :password, :langKey, :version)&amp;quot;&amp;quot;&amp;quot;

            @JvmStatic
            val sqlScript: String
                get() = setOf(
                    UserDao.Relations.SQL_SCRIPT,
                    RoleDao.Relations.SQL_SCRIPT,
                    UserRoleDao.Relations.SQL_SCRIPT
                ).joinToString(&amp;quot;&amp;quot;)
                    .trimMargin()
        }

        object Dao {
            val Pair&amp;amp;lt;User, ApplicationContext&amp;amp;gt;.toJson: String
                get() = second.getBean&amp;amp;lt;ObjectMapper&amp;amp;gt;().writeValueAsString(first)

            suspend fun Pair&amp;amp;lt;User, ApplicationContext&amp;amp;gt;.save(): Either&amp;amp;lt;Throwable, Long&amp;amp;gt; = try {
                second.getBean&amp;amp;lt;R2dbcEntityTemplate&amp;amp;gt;()
                    .databaseClient
                    .sql(INSERT)
                    .bind(LOGIN_ATTR, first.login)
                    .bind(EMAIL_ATTR, first.email)
                    .bind(PASSWORD_ATTR, first.password)
                    .bind(LANG_KEY_ATTR, first.langKey)
                    .bind(VERSION_ATTR, first.version)
                    .fetch()
                    .awaitRowsUpdated()
                    .right()
            } catch (e: Throwable) {
                e.left()
            }


            suspend fun ApplicationContext.findOneUserByEmail(
                email: String
            ): Either&amp;amp;lt;Throwable, User&amp;amp;gt; = try {
                getBean&amp;amp;lt;DatabaseClient&amp;amp;gt;()
                    .sql(&amp;quot;SELECT * FROM `user` WHERE LOWER(email) = LOWER(:email)&amp;quot;)
                    .bind(&amp;quot;email&amp;quot;, email)
                    .fetch()
                    .awaitOne()
                    .let { row -&amp;amp;gt;
                        User(
                            id = row[ID_ATTR] as UUID?,
                            login = row[LOGIN_ATTR] as String,
                            password = row[PASSWORD_ATTR] as String,
                            email = row[EMAIL_ATTR] as String,
                            langKey = row[LANG_KEY_ATTR] as String,
                            version = row[VERSION_ATTR] as Long
                        )
                    }.right()
            } catch (e: Throwable) {
                e.left()
            }
        }
    }

    /** Account REST API URIs */
    object UserRestApis {
        const val API_AUTHORITY = &amp;quot;/api/authorities&amp;quot;
        const val API_USERS = &amp;quot;/api/users&amp;quot;
        const val API_SIGNUP = &amp;quot;/signup&amp;quot;
        const val API_SIGNUP_PATH = &amp;quot;$API_USERS$API_SIGNUP&amp;quot;
        const val API_ACTIVATE = &amp;quot;/activate&amp;quot;
        const val API_ACTIVATE_PATH = &amp;quot;$API_USERS$API_ACTIVATE?key=&amp;quot;
        const val API_ACTIVATE_PARAM = &amp;quot;{activationKey}&amp;quot;
        const val API_ACTIVATE_KEY = &amp;quot;key&amp;quot;
        const val API_RESET_INIT = &amp;quot;/reset-password/init&amp;quot;
        const val API_RESET_FINISH = &amp;quot;/reset-password/finish&amp;quot;
        const val API_CHANGE = &amp;quot;/change-password&amp;quot;
        const val API_CHANGE_PATH = &amp;quot;$API_USERS$API_CHANGE&amp;quot;
    }
}

// Abstract entity model with Generic ID, which can be of any type
abstract class EntityModel&amp;amp;lt;T&amp;amp;gt;(
    open val id: T? = null
) {
    companion object {
        const val ID_MEMBER = &amp;quot;id&amp;quot;
    }
}

// Generic extension function that allows the ID to be applied to any EntityModel type
inline fun &amp;amp;lt;reified T : EntityModel&amp;amp;lt;ID&amp;amp;gt;, ID&amp;amp;gt; T.withId(id: ID): T {
    // Use reflection to create a copy with the passed ID
    return this::class.constructors.first { it.parameters.any { param -&amp;amp;gt; param.name == ID_MEMBER } }
        .call(id, *this::class.constructors.first().parameters.drop(1).map { param -&amp;amp;gt;
            this::class.members.first { member -&amp;amp;gt; member.name == param.name }.call(this)
        }.toTypedArray())
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_विभिन्न_दृष्टिकोण&amp;quot;&amp;gt;विभिन्न दृष्टिकोण&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_पारंपरिक_पद्धति_के_साथ_when&amp;quot;&amp;gt;पारंपरिक पद्धति के साथ `when&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;val user: User by lazy { userFactory(USER) }

val result: Either&amp;amp;lt;Throwable, User&amp;amp;gt; = context.findOneUserByEmail(user.email)

when (result) {
    is Either.Left -&amp;amp;gt; {
        val error = result.value
        println(&amp;quot;Erreur : ${error.message}&amp;quot;)
    }
    is Either.Right -&amp;amp;gt; {
        val user = result.value
        println(&amp;quot;Utilisateur trouvé : ${user.login}&amp;quot;)
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;हालांकि यह विधि सरल और पठनीय है, यह तीर की कार्यात्मक क्षमताओं का पूरी तरह से उपयोग नहीं करती।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_fold_का_उपयोग_एक_अधिक_संक्षिप्त_दृष्टिकोण_के_लिए&amp;quot;&amp;gt;fold` का उपयोग एक अधिक संक्षिप्त दृष्टिकोण के लिए&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;result.fold(
{ error -&amp;amp;gt; println(&amp;quot;Erreur : ${error.message}&amp;quot;) },
{ user -&amp;amp;gt; println(&amp;quot;Utilisateur trouvé : ${user.login}&amp;quot;) }
)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;`fold`यह Left और Right दोनों मामलों के लिए कार्यों को परिभाषित करने की अनुमति देता है, संक्षिप्त और शालीन तरीके से।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_परिवर्तन_map_और_mapleft_के_साथ&amp;quot;&amp;gt;परिवर्तन &amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; और &amp;lt;code&amp;gt;mapLeft&amp;lt;/code&amp;gt; के साथ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;val processedResult = result
    .map { user -&amp;amp;gt; &amp;quot;Utilisateur trouvé : ${user.login}&amp;quot; }
    .mapLeft { error -&amp;amp;gt; &amp;quot;Erreur : ${error.message}&amp;quot; }

println(processedResult.merge())&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह दृष्टिकोण Either में निहित मान को बदलने की अनुमति देता है जबकि उसकी संरचना को संरक्षित रखता है, जो अधिक जटिल प्रक्रिया श्रृंखलाओं के लिए आदर्श है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_त्रुटि_प्रबंधन_के_साथ_getorelse&amp;quot;&amp;gt;त्रुटि प्रबंधन के साथ `getOrElse&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;val user = result.getOrElse { error -&amp;amp;gt;
    println(&amp;quot;Erreur : ${error.message}&amp;quot;)
    User(login = &amp;quot;default&amp;quot;, email = &amp;quot;default@example.com&amp;quot;) // utilisateur par défaut
}
println(&amp;quot;Login : ${user.login}&amp;quot;)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;`getOrElse`यह एक शानदार त्रुटि प्रबंधन प्रदान करता है क्योंकि यह एक डिफ़ॉल्ट मान प्रदान करने की अनुमति देता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_साइड_कार्रवाई_onleft_और_onright_के_साथ&amp;quot;&amp;gt;साइड कार्रवाई &amp;lt;code&amp;gt;onLeft&amp;lt;/code&amp;gt; और &amp;lt;code&amp;gt;onRight&amp;lt;/code&amp;gt; के साथ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;result.onLeft { error -&amp;amp;gt; println(&amp;quot;Erreur : ${error.message}&amp;quot;) }
.onRight { user -&amp;amp;gt; println(&amp;quot;Utilisateur trouvé : ${user.login}&amp;quot;) }&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;ये तरीके किसी भी तरफ कार्रवाई करने की अनुमति देते हैं, Either को संशोधित किए बिना, लॉगिंग या हल्के दुष्प्रभाव के लिए उपयुक्त।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ऑपरेशन_चेनिंग_flatmap_के_साथ&amp;quot;&amp;gt;ऑपरेशन चेनिंग &amp;lt;code&amp;gt;flatMap&amp;lt;/code&amp;gt; के साथ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;fun findUser(email: String): Either&amp;amp;lt;Throwable, User&amp;amp;gt; = // ... implémentation

fun getUserPermissions(user: User): Either&amp;amp;lt;Throwable, List&amp;amp;lt;String&amp;amp;gt;&amp;amp;gt; = // ... implémentation

val userPermissions = findUser(&amp;quot;user@example.com&amp;quot;)
    .flatMap { user -&amp;amp;gt; getUserPermissions(user) }&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;flatMap`यह ऐसे कार्यों को क्रम में जोड़ने के लिए उपयोगी है जो स्वयं लौटाते हैं`Either&amp;lt;/code&amp;gt;, इस प्रकार बचते हुए`Either`संलग्न.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_द्विदिशात्मक_परिवर्तन_के_साथ_bimap&amp;quot;&amp;gt;द्विदिशात्मक परिवर्तन के साथ `bimap&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;val result: Either&amp;amp;lt;Throwable, User&amp;amp;gt; = // ... obtention du résultat
val processedResult = result.bimap(
    { error -&amp;amp;gt; &amp;quot;Erreur: ${error.message}&amp;quot; },
    { user -&amp;amp;gt; &amp;quot;Utilisateur: ${user.login}&amp;quot; }
)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;`bimap`बायें और दायें दोनों पक्षों को एक ही ऑपरेशन में बदलने की अनुमति देता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_swap_के_साथ_किनारों_को_उलटना&amp;quot;&amp;gt;swap के साथ किनारों को उलटना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;val result: Either&amp;amp;lt;Throwable, User&amp;amp;gt; = // ... obtention du résultat
val swapped = result.swap()&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;swap`यह उपयोगी है जब आप एक पक्ष को उलटना चाहते हैं`Either&amp;lt;/code&amp;gt;, उदाहरण के लिए एक फ़ंक्शन के इंटरफ़ेस को दूसरे इंटरफ़ेस के अनुसार अनुकूलित करने के लिए.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_tap_और_tapleft_का_उपयोग&amp;quot;&amp;gt;tap` और &amp;lt;code&amp;gt;tapLeft&amp;lt;/code&amp;gt; का उपयोग:&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;result.tap { user -&amp;amp;gt; println(&amp;quot;Utilisateur trouvé : ${user.login}&amp;quot;) }
.tapLeft { error -&amp;amp;gt; println(&amp;quot;Erreur : ${error.message}&amp;quot;) }&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जैसे`onLeft` et &amp;lt;code&amp;gt;onRight&amp;lt;/code&amp;gt;, लेकिन इन विधियों में मूल Either लौटाया जाता है, जो संचालन की श्रृंखला के लिए उपयोगी है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_उपयोग_recover&amp;quot;&amp;gt;उपयोग &amp;lt;code&amp;gt;recover&amp;lt;/code&amp;gt; :&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;val recoveredUser = result.recover { error -&amp;amp;gt;
    println(&amp;quot;Erreur récupérée : ${error.message}&amp;quot;)
    User(login = &amp;quot;recovered&amp;quot;, email = &amp;quot;recovered@example.com&amp;quot;)
}
println(&amp;quot;Login : ${recoveredUser.login}&amp;quot;)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह विधि एक प्रतिस्थापन मान प्रदान करके Either.Left को Either.Right में बदलने की अनुमति देती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_प्रायोगिक_उपयोग_के_मामले&amp;quot;&amp;gt;प्रायोगिक उपयोग के मामले&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;उपयोग करें`fold`सरल संचालन के लिए जो प्रत्येक मामले के लिए प्रसंस्करण की आवश्यकता होती है। - आप प्राथमिकता दें`map` et &amp;lt;code&amp;gt;mapLeft`डेटा परिवर्तनों के लिए बिना संरचना बदले de l&amp;#39;`Either&amp;lt;/code&amp;gt;. चुनें`flatMap`चेनिंग के दौरान विफल हो सकने वाले संचालन के दौरान उपयोग करें`recover`त्रुटि के मामले में एक डिफ़ॉल्ट मान प्रदान करने के लिए - चुनें`onLeft` et &amp;lt;code&amp;gt;onRight&amp;lt;/code&amp;gt; (ou &amp;lt;code&amp;gt;tap&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;tapLeft&amp;lt;/code&amp;gt;) साइड इफ़ेक्ट्स जैसे लॉगिंग के लिए. - उपयोग करें`bimap`दोनों पक्षों को एक ही ऑपरेशन में बदलने के लिए - लागू करें`swap`जब आपको किसी फ़ंक्शन के इंटरफ़ेस को दूसरे से अनुकूलित करने की आवश्यकता होती है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इनमें से प्रत्येक दृष्टिकोण के अपने फायदे होते हैं उपयोग के संदर्भ के अनुसार। तरीके जैसे`fold`, &amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt;(No output)&amp;lt;code&amp;gt;mapLeft&amp;lt;/code&amp;gt;, et `recover`वे विशेष रूप से उपयोगी होते हैं जब आप कई ऑपरेशन को क्रम में रखना चाहते हैं या डेटा को कार्यात्मक रूप से बदलना चाहते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मोनैड`Either`d&amp;amp;#8217;Arrow कोट्लिन एप्लिकेशनों में सफलता और त्रुटि के मामलों को संभालने के लिए उल्लेखनीय लचीलापन प्रदान करता है। इन विभिन्न दृष्टिकोनों को समझने पर, आप अधिक मजबूत, पढ़ने में आसान और अधिक कार्यात्मक कोड लिख पाएँगे।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अपने अगले प्रोजेक्ट में, इन तकनीकों का अन्वेषण करने में संकोच न करें ताकि आप कोटलिन और एरो के साथ कार्यात्मक प्रोग्रामिंग से अधिकतम लाभ उठा सकें !&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_और_आगे_जाने_के_लिए&amp;quot;&amp;gt;और आगे जाने के लिए&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एरो की आधिकारिक दस्तावेज़:https://arrow-kt.io/docs/apidocs/arrow-core/arrow.core/-either/[तीर या] &amp;lt;mark&amp;gt;#&amp;lt;/mark&amp;gt; Gradle एकीकरण JBake को JBake Gradle प्लगिन का उपयोग करके या JBake CLI को सीधे बुलाकर Gradle बिल्ड में एकीकृत किया जा सकता है:&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;----
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
}https://arrow-kt.io/docs/fx/[तीर Fx कोरूटीन]

अपने अनुभव और पसंदीदा तकनीकें साझा करना न भूलें साथ में काम करने के लिए`Either`नीचे दिए गए टिप्पणियों में !
----&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>व्यावहारिक मार्गदर्शक : लिनक्स में फ़ाइलों की खोज</title>
            <link >https://cheroliv.com/blog/2024/0074_seach_file_linux_post.html</link>
            <pubDate>Mon, 23 Sep 2024 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2024/0074_seach_file_linux_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_कमांड_का_उपयोग_find&amp;quot;&amp;gt;कमांड का उपयोग `find&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अतिरिक्त_विकल्प_के_लिए_find&amp;quot;&amp;gt;अतिरिक्त विकल्प के लिए `find&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_कमांड_locate_का_उपयोग&amp;quot;&amp;gt;कमांड &amp;lt;code&amp;gt;locate&amp;lt;/code&amp;gt; का उपयोग&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_फ़ाइलों_में_टेक्स्ट_खोजने_के_लिए_grep_कमांड_का_उपयोग&amp;quot;&amp;gt;फ़ाइलों में टेक्स्ट खोजने के लिए &amp;lt;code&amp;gt;grep&amp;lt;/code&amp;gt; कमांड का उपयोग&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;समस्या : एक लिनक्स ऑपरेटिंग सिस्टम में टर्मिनल के माध्यम से फ़ाइलों की खोज करें।&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;इस लेख में, हम बताएँगे कि Ubuntu में Zsh टर्मिनल का उपयोग करके फ़ाइल कैसे खोजी जाए। Zsh (Z शेल) एक शक्तिशाली और व्यापक रूप से प्रयोग किए जाने वाले कमांड इंटरप्रेटर है, जो अपनी लचीलापन और उन्नत विशेषताओं के लिए प्रसिद्ध है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ubuntu, एक लोकप्रिय लिनक्स वितरण, कमांड लाइन में कई उपकरण प्रदान करता है जिनका उपयोग फ़ाइलों को खोजने के लिए किया जाता है। हम देखेंगे कि कैसे ऐसे कमांड का उपयोग किया जाता है, जैसे कि`find`, &amp;lt;code&amp;gt;locate&amp;lt;/code&amp;gt; et `grep`टर्मिनल में फ़ाइलों को तेज़ी से और प्रभावी ढंग से खोजने के लिए&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_कमांड_का_उपयोग_find&amp;quot;&amp;gt;कमांड का उपयोग `find&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आदेश`find`यह किसी विशिष्ट निर्देशिका और उसके उप-निर्देशिकाओं में फ़ाइलों की खोज करने की अनुमति देता है। इसका मूल वाक्य विन्यास निम्नलिखित है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;find [chemin] -name [nom_du_fichier]&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ एक व्यावहारिक उदाहरण है जहाँ हम एक नामित फ़ाइल की तलाश कर रहे हैं`example.txt`निर्देशिका में`/home`[Translation: The fragment to translate is empty, so the output is empty.]&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;find /home -name &amp;quot;example.txt&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह कमांड सभी उप-निर्देशिकाओं का अन्वेषण करेगी`/home`और यदि फ़ाइल मिलती है तो उसका पूर्ण पथ दिखाएँ&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;कमांड का ऑनलाइन मैनुअल&amp;lt;/strong&amp;gt;&amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt;:https://man.archlinux.org/man/find.1.fr/[man find,windows=read-later]*&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_अतिरिक्त_विकल्प_के_लिए_find&amp;quot;&amp;gt;अतिरिक्त विकल्प के लिए `find&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आदेश`find`यह बहुत शक्तिशाली है और कई विकल्प प्रदान करता है। यहाँ कुछ उपयोगी उदाहरण हैं :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;फ़ाइल प्रकार द्वारा खोजें&amp;lt;/strong&amp;gt;: केवल फ़ाइलों की खोज करने के लिए, उपयोग करें`-type f`, और निर्देशिकाएँ, खोजने के लिए उपयोग करें`-type d`. - &amp;lt;strong&amp;gt;आकार द्वारा खोजें&amp;lt;/strong&amp;gt;आप आकार के आधार पर फ़ाइलों को फ़िल्टर भी कर सकते हैं विकल्प का उपयोग करके`-size`. Par exemple, pour rechercher des fichiers de plus de 100 Mo, utilisez :&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;find /home -size +100M&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_कमांड_locate_का_उपयोग&amp;quot;&amp;gt;कमांड &amp;lt;code&amp;gt;locate&amp;lt;/code&amp;gt; का उपयोग&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आदेश`locate`ज्यादा तेज़ है`find`car यह प्रणाली पर मौजूद फ़ाइलों की पूर्व-इंडेक्स की गई डेटाबेस का उपयोग करती है। आपको इस डेटाबेस को अपडेट करने के लिए पहले निम्नलिखित कमांड का उपयोग करना होगा :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;sudo updatedb&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फिर, आप इस तरह एक फ़ाइल खोज सकते हैं :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;locate example.txt&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मैं उपयोग कर रहा हूँhttps://fr.wikipedia.org/wiki/Z_Shell[zsh]साथhttps://github.com/ohmyzsh/ohmyzsh/wiki[oh-my-zsh], यह पता चलता है कि आदेश`locate`इसे एक्सेस नहीं किया जा सकता`zsh`लेकिन निश्चित रूप से संभव से`bash`, इस बात से निपटने के लिए, तर्क`-c`आदेश का`bash`एक कमांड चलाने की अनुमति देता है`bash`दूसरे प्रकार के टर्मिनल से।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ मैं उन फाइलों की तलाश कर रहा हूँ जो इस पैटर्न से समाप्त होती हैं`001.pdf`उपयोगकर्ता निर्देशिका में&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;bash -c &amp;quot;locate ~/*001.pdf&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;कमांड का ऑनलाइन मैनुअल`locate`:https://man.archlinux.org/man/locate.1.fr/[आदमी स्थान निर्धारित,windows=read-later]&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_फ़ाइलों_में_टेक्स्ट_खोजने_के_लिए_grep_कमांड_का_उपयोग&amp;quot;&amp;gt;फ़ाइलों में टेक्स्ट खोजने के लिए &amp;lt;code&amp;gt;grep&amp;lt;/code&amp;gt; कमांड का उपयोग&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यदि आप फ़ाइल के भीतर किसी विशिष्ट पाठ को खोजना चाहते हैं, तो आप उपयोग कर सकते हैं`grep`. उदाहरण के लिए, &amp;quot;Ubuntu&amp;quot; शब्द की घटना खोजने के लिए सभी फ़ाइलों में`.txt`वर्तमान निर्देशिका में, उपयोग करें:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;grep &amp;quot;Ubuntu&amp;quot; *.txt&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Ubuntu के तहत Zsh टर्मिनल के माध्यम से फ़ाइलों की खोज कई शक्तिशाली टूल्स के उपयोग से की जा सकती है।`find`लचीला है और बहुत सारे विकल्प प्रदान करता है, जबकि`locate`यह त्वरित खोज की अनुमति देता है पहले से निर्मित डेटाबेस का उपयोग करके। अंत में,`grep`फ़ाइलों के भीतर पाठ के उदाहरण खोजने की अनुमति देता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इन कमांडों से आपको फ़ाइलों की खोज को अधिक प्रभावी और आपकी आवश्यकताओं के अनुरूप बनाने के लिए टूल की पूरी श्रृंखला मिलती है, और इनमें से प्रत्येक कमांड के साथ एक मैनुअल दिखाई देता है।&amp;lt;code&amp;gt;man&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>लिनक्स मेमो</title>
            <link >https://cheroliv.com/blog/2021/0030_memo_linux_post.html</link>
            <pubDate>Mon, 23 Sep 2024 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2021/0030_memo_linux_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_कीबोर्ड&amp;quot;&amp;gt;कीबोर्ड :&amp;lt;/a&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel2&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_ctrl_कुंजी&amp;quot;&amp;gt;&amp;lt;em&amp;gt;&amp;amp;lt;Ctrl&amp;amp;gt; कुंजी&amp;lt;/em&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अनुमतिप्राधिकरण&amp;quot;&amp;gt;अनुमति(प्राधिकरण)&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_फाइल_खोज&amp;quot;&amp;gt;फाइल खोज&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_कीबोर्ड&amp;quot;&amp;gt;कीबोर्ड :&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_ctrl_कुंजी&amp;quot;&amp;gt;&amp;lt;em&amp;gt;&amp;amp;lt;Ctrl&amp;amp;gt; कुंजी&amp;lt;/em&amp;gt;&amp;lt;/h3&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://korben.info/les-raccourcis-clavier-pour-bash-terminal-linux-et-macos.html&amp;quot;&amp;gt;लिंक&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;a href=&amp;quot;https://blogmotion.fr/systeme/astuces-bash-linux-16175&amp;quot;&amp;gt;अन्य लिंक&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_अनुमतिप्राधिकरण&amp;quot;&amp;gt;अनुमति(प्राधिकरण)&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;CHMOD का उपयोग फ़ाइल की अनुमतियाँ बदलने के लिए किया जाता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अनुमति      आदेश&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;U   G   W rwx rwx rwx     chmod 777 फ़ाइल नाम rwx rwx r-x     chmod 775 filename rwx r-x r-x     chmod 755 फ़ाइल का नाम rw- rw- r--     chmod 664 filename rw- r-- r--     chmod 644 फ़ाइल नाम&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;U = उपयोगकर्ता G = समूह W = दुनिया&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;r = पढ़ने योग्य w = लेखन योग्य x = निष्पादन योग्य - = अनुमति नहीं&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अनुमतियों को देखने का एक और तरीका:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;400     मालिक द्वारा पढ़ा गया 040     समूह द्वारा पढ़ा गया 004     कोई भी द्वारा पढ़ा गया (अन्य) 200 मालिक द्वारा लिखा गया 020     समूह द्वारा लिखें 002     write by anybody 100     मालिक द्वारा निष्पादित 010     समूह द्वारा निष्पादित किसी भी द्वारा निष्पादित&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक संयोजन प्राप्त करने के लिए, बस उन्हें जोड़ दें।&amp;lt;br&amp;gt;
उदाहरण के लिए, इसे पढ़ा, लिखा, निष्पादित करने के लिए स्वामी द्वारा,&amp;lt;br&amp;gt;
पढ़ा, निष्पादित, समूह द्वारा और कोई भी द्वारा निष्पादित,&amp;lt;br&amp;gt;
आप 400+200+100+040+010+001 जोड़ेंगे जिससे 751 प्राप्त होगा।&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_फाइल_खोज&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;/blog/2024/0074_seach_file_linux_post.html&amp;quot;&amp;gt;फाइल खोज&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>विंडोज़ होस्ट के लिए लिनक्स सबसिस्टम पोर्ट को उजागर करें</title>
            <link >https://cheroliv.com/blog/2024/0072_Exposer_un_port_linux_subsystem_post.adoc.html</link>
            <pubDate>Thu, 1 Feb 2024 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2024/0072_Exposer_un_port_linux_subsystem_post.adoc.html</guid>
            <description>&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;&amp;lt;em&amp;gt;पढ़ने का समय : 10 सेकंड&amp;lt;/em&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;समस्या : Ubuntu सबसिस्टम का होस्ट Windows होने पर पोर्ट 8820 को कैसे उजागर करें? Ubuntu को कमांड से बूट किया जाता है`wsl --install`.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>पांडोक स्थापित करें</title>
            <link >https://cheroliv.com/blog/2024/0070_installer_pandoc_post.html</link>
            <pubDate>Tue, 30 Jan 2024 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2024/0070_installer_pandoc_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;&amp;lt;em&amp;gt;पढ़ने का समय : 3 मिनट&amp;lt;/em&amp;gt; Pandoc एक सार्वभौमिक दस्तावेज़ कंवर्टर&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Pandoc एक ओपन सोर्स टेक्स्ट प्रोसेसिंग सॉफ़्टवेयर है जो विभिन्न प्रारूपों के बीच दस्तावेज़ों को बदलने के लिए प्रयोग किया जा सकता है। पैंडोक को स्थापित करने के कई तरीके हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_डाउनलोड_पेज_से_इंस्टॉलेशन&amp;quot;&amp;gt;डाउनलोड पेज से इंस्टॉलेशन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Pandoc को डाउनलोड पेज से इंस्टॉल करने के लिए, निम्नलिखित चरणों का पालन करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;पंडॉक डाउनलोड पेज पर जाएँ:https://pandoc.org/installing.html/[&amp;lt;a href=&amp;quot;https://pandoc.org/installing.html&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://pandoc.org/installing.html&amp;lt;/a&amp;gt;]&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;अपने ऑपरेटिंग सिस्टम के लिए पैकेज इंस्टॉलर डाउनलोड करें।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Pandoc स्थापित करने के लिए इंस्टॉलर चलाएँ।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;ज़िप फ़ाइल से इंस्टॉलेशन&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक zip फ़ाइल से Pandoc स्थापित करने के लिए, निम्नलिखित चरणों का पालन करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;पांडॉक बाइनरीज़ और दस्तावेज़ रखने वाली ज़िप फ़ाइल डाउनलोड करें।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;ज़िप फ़ाइल को निकालें।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;बाइनरी को अपनी पसंद की निर्देशिका में ले जाएँ।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Chocolatey की मदद से स्थापना&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पंडॉक को Chocolatey के माध्यम से स्थापित करने के लिए, निम्नलिखित चरणों का पालन करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कमांड प्रॉम्प्ट खोलें।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;आगामी कमांड को निष्पादित करें :&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-powershell&amp;quot; data-lang=&amp;quot;powershell&amp;quot;&amp;gt;choco install pandoc&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;winget का उपयोग करके स्थापना&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;winget का उपयोग करके Pandoc स्थापित करने के लिए, इन चरणों का पालन करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एक कमांड प्रॉम्प्ट खोलें।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;निम्नलिखित कमांड को निष्पादित करें :&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-powershell&amp;quot; data-lang=&amp;quot;powershell&amp;quot;&amp;gt;winget install --source winget --exact --id JohnMacFarlane.Pandoc&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;सिफ़ारिशें&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;डिफ़ॉल्ट रूप से, Pandoc LaTeX का उपयोग करके PDF फ़ाइलें बनाता है। LaTeX को MiKTeX के माध्यम से स्थापित करने की सिफारिश की जाती है। विकल्प के साथ`--pdf-engine`हालांकि आप इस कार्य के लिए अन्य कार्यक्रम भी निर्दिष्ट कर सकते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;चेतावनी&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;कई इंस्टॉलेशन विधियों का उपयोग करने से Pandoc की दो अलग-अलग इंस्टॉलेशन हो सकती हैं। अनुशंसा की जाती है कि वैकल्पिक इंस्टॉलेशन विधि में बदलने से पहले Pandoc को सही तरीके से अनइंस्टॉल कर दिया जाए।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;WSL के माध्यम से Linux पर स्थापना&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पैकेज प्रबंधक में pandoc के संस्करण की जाँच करें कि क्या यह पुराना नहीं है। Pandoc Debian, Ubuntu, Slackware, Arch, Fedora, NixOS, openSUSE, gentoo और Void के रिपॉजिटरी में उपलब्ध है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;नवीनतम संस्करण प्राप्त करने के लिए, हम amd64 आर्किटेक्चर के लिए बाइनरी पैकेज डाउनलोड पृष्ठ पर प्रदान करते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;निष्पादन योग्य फ़ाइल स्थैतिक रूप से लिंक की गई है और इसमें कोई गतिशील निर्भरता नहीं है, साथ ही कोई बाहरी डेटा फ़ाइलों पर निर्भरता भी नहीं है। नोट: स्थैतिक लिंकिंग के कारण, इस पैकेज का pandoc बाइनरी ऐसे lua फ़िल्टर का उपयोग नहीं कर सकता है जिनमें C में लिखे गए बाहरी lua मॉड्यूल की आवश्यकता होती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक tarball और एक deb इंस्टॉलर प्रदान किया जाता है। deb को स्थापित करने के लिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;sudo dpkg -i $DEB&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;लेखन के समय उदाहरण :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;wget https://github.com/jgm/pandoc/releases/download/3.1.11.1/pandoc-3.1.11.1-1-amd64.deb&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;sudo dpkg -i pandoc-3.1.11.1-1-amd64.deb&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;où `$DEB`यह डाउनलोड किए गए deb तक जाने का पथ है। यह एक्सीक्यूटेबल इंस्टॉल करेगा`pandoc`और मैनुअल पृष्ठ&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यदि आप RPM-आधारित वितरण का उपयोग कर रहे हैं, तो आप संभवतः हमारे डाउनलोड पृष्ठ से .deb को एलीन का उपयोग करके स्थापित कर सकते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;कोई भी वितरण पर, आप tarball से इंस्टॉल कर सकते हैं`$DEST`(उदाहरण के लिए,&amp;lt;code&amp;gt;/usr/local/&amp;lt;/code&amp;gt; ou &amp;lt;code&amp;gt;$HOME/.local&amp;lt;/code&amp;gt;) करते हुए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;tar xvzf $TGZ --strip-components 1 -C $DEST&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;où `$TGZ`यह डाउनलोड किए गए ज़िप्ड टारबॉल का पथ है। पांडोक के 2.0 से पहले के संस्करणों के लिए, जो टारबॉल प्रदान नहीं करते हैं, इसके बजाय प्रयास करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;ar p $DEB data.tar.gz | tar xvz --strip-components 2 -C $DEST&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;आप स्रोत से भी इंस्टॉल कर सकते हैं, नीचे दिए गए निर्देशों का उपयोग करके`Compilation à partir de la source`. ध्यान दें कि अधिकांश वितरणों में उनके पैकेज रिपॉज़िटरी में हास्केल प्लेटफ़ॉर्म उपलब्ध है। उदाहरण के लिए, Debian/Ubuntu पर, आप इसे स्थापित कर सकते हैं&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;apt-get install haskell-platform&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;डिफ़ॉल्ट रूप से, Pandoc LaTeX का उपयोग करके PDFs बनाता है। हम आपको अपने पैकेज मैनेजर के माध्यम से TeX Live स्थापित करने की सिफारिश करते हैं। (डेबियन/उबंटू पर,&amp;lt;code&amp;gt;apt-get install texlive&amp;lt;/code&amp;gt;). विकल्प के साथ`--pdf-engine`, आप हालांकि इस कार्य के लिए अन्य प्रोग्राम निर्दिष्ट कर सकते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Kotlin.Triple का JavaScript, TypeScript और Python में कार्यान्वयन</title>
            <link >https://cheroliv.com/blog/2023/0069_triple_python_js_ts_post.html</link>
            <pubDate>Mon, 25 Dec 2023 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2023/0069_triple_python_js_ts_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;&amp;lt;em&amp;gt;पढ़ने का समय: 2 मिनट&amp;lt;/em&amp;gt; JavaScript, TypeScript और Python में kotlin.Triple क्लास का पूर्ण कार्यान्वयन कार्यात्मक प्रोग्रामिंग का उपयोग करके बनाएं।&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;नोट :&amp;lt;/strong&amp;gt;प्रकार`Maybe`, &amp;lt;code&amp;gt;Either&amp;lt;/code&amp;gt;, `Result`वे जावास्क्रिप्ट या टाइपस्क्रिप्ट के मूल भाषा के हिस्सा नहीं हैं, इसलिए हमें उन्हें खुद लागू करना होगा।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_जावास्क्रिप्ट&amp;quot;&amp;gt;जावास्क्रिप्ट&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;//javascript
// Maybe type
const Maybe = (value) =&amp;amp;gt; ({
  map: (fn) =&amp;amp;gt; (value !== null &amp;amp;amp;&amp;amp;amp; value !== undefined ? Maybe(fn(value)) : Maybe(null)),
  flatMap: (fn) =&amp;amp;gt; (value !== null &amp;amp;amp;&amp;amp;amp; value !== undefined ? fn(value) : Maybe(null)),
  getOrElse: (defaultValue) =&amp;amp;gt; (value !== null &amp;amp;amp;&amp;amp;amp; value !== undefined ? value : defaultValue),
});

// Either type
const Either = {
  Left: (value) =&amp;amp;gt; ({
    map: (fn) =&amp;amp;gt; Either.Left(value),
    flatMap: (fn) =&amp;amp;gt; Either.Left(value),
    getOrElse: (defaultValue) =&amp;amp;gt; defaultValue,
    isLeft: true,
    isRight: false,
  }),
  Right: (value) =&amp;amp;gt; ({
    map: (fn) =&amp;amp;gt; Either.Right(fn(value)),
    flatMap: (fn) =&amp;amp;gt; fn(value),
    getOrElse: (defaultValue) =&amp;amp;gt; value,
    isLeft: false,
    isRight: true,
  }),
};

// Triple class
class Triple {
  constructor(a, b, c) {
    this.a = a;
    this.b = b;
    this.c = c;
  }

  map(fn) {
    return new Triple(fn(this.a), fn(this.b), fn(this.c));
  }

  static of(a, b, c) {
    return new Triple(a, b, c);
  }

  // Example method using Maybe and Either
  divideBy(other) {
    return Maybe(this.b)
      .flatMap((numerator) =&amp;amp;gt;
        Maybe(other)
          .flatMap((denominator) =&amp;amp;gt;
            denominator !== 0
              ? Either.Right(numerator / denominator)
              : Either.Left(&amp;#39;Division by zero&amp;#39;)
          )
      )
      .getOrElse(Either.Left(&amp;#39;Invalid input&amp;#39;));
  }
}

// Example usage
const triple = Triple.of(1, 2, 3);
const result = triple.map((x) =&amp;amp;gt; x * 2);
console.log(result); // Triple { a: 2, b: 4, c: 6 }

const divisionResult = triple.divideBy(2);
console.log(divisionResult); // Either.Right { value: 1 }

const invalidDivisionResult = triple.divideBy(0);
console.log(invalidDivisionResult); // Either.Left { value: &amp;#39;Division by zero&amp;#39; }&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_typescript&amp;quot;&amp;gt;TypeScript&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-typescript&amp;quot; data-lang=&amp;quot;typescript&amp;quot;&amp;gt;//Typescript
// Maybe type
// noinspection JSAnnotator

type Maybe&amp;amp;lt;T&amp;amp;gt; = {
  map&amp;amp;lt;U&amp;amp;gt;(fn: (value: T) =&amp;amp;gt; U): Maybe&amp;amp;lt;U&amp;amp;gt;;
  flatMap&amp;amp;lt;U&amp;amp;gt;(fn: (value: T) =&amp;amp;gt; Maybe&amp;amp;lt;U&amp;amp;gt;): Maybe&amp;amp;lt;U&amp;amp;gt;;
  getOrElse(defaultValue: T): T;
};

const just = &amp;amp;lt;T&amp;amp;gt;(value: T): Maybe&amp;amp;lt;T&amp;amp;gt; =&amp;amp;gt; ({
  map: &amp;amp;lt;U&amp;amp;gt;(fn: (value: T) =&amp;amp;gt; U) =&amp;amp;gt; just(fn(value)),
  flatMap: &amp;amp;lt;U&amp;amp;gt;(fn: (value: T) =&amp;amp;gt; Maybe&amp;amp;lt;U&amp;amp;gt;) =&amp;amp;gt; fn(value),
  getOrElse: (_: T) =&amp;amp;gt; value,
});

const nothing = &amp;amp;lt;T&amp;amp;gt;(): Maybe&amp;amp;lt;T&amp;amp;gt; =&amp;amp;gt; ({
  map: &amp;amp;lt;U&amp;amp;gt;(_: (value: T) =&amp;amp;gt; U) =&amp;amp;gt; nothing&amp;amp;lt;U&amp;amp;gt;(),
  flatMap: &amp;amp;lt;U&amp;amp;gt;(_: (value: T) =&amp;amp;gt; Maybe&amp;amp;lt;U&amp;amp;gt;) =&amp;amp;gt; nothing&amp;amp;lt;U&amp;amp;gt;(),
  getOrElse: (defaultValue: T) =&amp;amp;gt; defaultValue,
});

// Either type
type Either&amp;amp;lt;L, R&amp;amp;gt; = {
  map&amp;amp;lt;U&amp;amp;gt;(fn: (value: R) =&amp;amp;gt; U): Either&amp;amp;lt;L, U&amp;amp;gt;;
  flatMap&amp;amp;lt;U&amp;amp;gt;(fn: (value: R) =&amp;amp;gt; Either&amp;amp;lt;L, U&amp;amp;gt;): Either&amp;amp;lt;L, U&amp;amp;gt;;
  getOrElse(defaultValue: R): R;
  isLeft: boolean;
  isRight: boolean;
};

const left = &amp;amp;lt;L, R&amp;amp;gt;(value: L): Either&amp;amp;lt;L, R&amp;amp;gt; =&amp;amp;gt; ({
  map: &amp;amp;lt;U&amp;amp;gt;(_: (value: R) =&amp;amp;gt; U) =&amp;amp;gt; left&amp;amp;lt;L, U&amp;amp;gt;(value),
  flatMap: &amp;amp;lt;U&amp;amp;gt;(_: (value: R) =&amp;amp;gt; Either&amp;amp;lt;L, U&amp;amp;gt;) =&amp;amp;gt; left&amp;amp;lt;L, U&amp;amp;gt;(value),
  getOrElse: (defaultValue: R) =&amp;amp;gt; defaultValue,
  isLeft: true,
  isRight: false,
});

const right = &amp;amp;lt;L, R&amp;amp;gt;(value: R): Either&amp;amp;lt;L, R&amp;amp;gt; =&amp;amp;gt; ({
  map: &amp;amp;lt;U&amp;amp;gt;(fn: (value: R) =&amp;amp;gt; U) =&amp;amp;gt; right&amp;amp;lt;L, U&amp;amp;gt;(fn(value)),
  flatMap: &amp;amp;lt;U&amp;amp;gt;(fn: (value: R) =&amp;amp;gt; Either&amp;amp;lt;L, U&amp;amp;gt;) =&amp;amp;gt; fn(value),
  getOrElse: (_: R) =&amp;amp;gt; value,
  isLeft: false,
  isRight: true,
});

// Triple class
class Triple&amp;amp;lt;T&amp;amp;gt; {
  constructor(public a: T, public b: T, public c: T) {}

  map&amp;amp;lt;U&amp;amp;gt;(fn: (value: T) =&amp;amp;gt; U): Triple&amp;amp;lt;U&amp;amp;gt; {
    return new Triple&amp;amp;lt;U&amp;amp;gt;(fn(this.a), fn(this.b), fn(this.c));
  }

  static of&amp;amp;lt;T&amp;amp;gt;(a: T, b: T, c: T): Triple&amp;amp;lt;T&amp;amp;gt; {
    return new Triple&amp;amp;lt;T&amp;amp;gt;(a, b, c);
  }

  // Example method using Maybe and Either
  divideBy(other: T): Either&amp;amp;lt;string, number&amp;amp;gt; {
    return just(this.b)
      .flatMap((numerator) =&amp;amp;gt;
        just(other)
          .flatMap((denominator) =&amp;amp;gt;
            denominator !== 0 ? right(numerator / denominator) : left(&amp;#39;Division by zero&amp;#39;)
          )
      )
      .getOrElse(left(&amp;#39;Invalid input&amp;#39;));
  }
}

// Example usage
const triple = Triple.of(1, 2, 3);
const result = triple.map((x) =&amp;amp;gt; x * 2);
console.log(result); // Triple { a: 2, b: 4, c: 6 }

const divisionResult = triple.divideBy(2);
console.log(divisionResult); // Either.Right { value: 1 }

const invalidDivisionResult = triple.divideBy(0);
console.log(invalidDivisionResult); // Either.Left { value: &amp;#39;Division by zero&amp;#39; }&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_python_pydantic_pymonad&amp;quot;&amp;gt;Python, pydantic, pymonad&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Python में एक कार्यान्वयन बनाने के लिए उपयोग करके`pydantic`प्रकारों की पुष्टि के लिए और`pymonad`मोनाड्स के लिए :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;निर्भरताएँ स्थापित करें :&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;pip install pydantic pymonad&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-python&amp;quot; data-lang=&amp;quot;python&amp;quot;&amp;gt;from pymonad.either import Either, Left, Right
from pydantic import BaseModel, ValidationError, validator

# Définition de la classe Triple avec Pydantic
class Triple(BaseModel):
    a: int
    b: int
    c: int

    @validator(&amp;#39;b&amp;#39;)
    def validate_b(cls, b, values):
        if b == 0:
            raise ValueError(&amp;#39;Division by zero is not allowed&amp;#39;)
        return b

    # Méthode utilisant Either pour la gestion des erreurs
    def divide_by(self, other):
        def division(numerator, denominator):
            return Right(numerator / denominator)

        def handle_error(error):
            return Left(str(error))

        return Either(lambda: division(self.b, other)).or_else(handle_error)

# Exemple d&amp;#39;utilisation
try:
    triple = Triple(a=1, b=2, c=3)
    result = triple.divide_by(2)

    if result.is_right:
        print(f&amp;#39;Division result: {result.value}&amp;#39;)
    else:
        print(f&amp;#39;Error: {result.value}&amp;#39;)

except ValidationError as e:
    print(f&amp;#39;Validation Error: {e}&amp;#39;)
except Exception as e:
    print(f&amp;#39;An unexpected error occurred: {e}&amp;#39;)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;इस उदाहरण में :&amp;lt;/div&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;pydantic`क्लास को परिभाषित करने के लिए`Triple`टाइप्ड फ़ील्ड के साथ. विधि`divide_by`मोनाड का उपयोग करता है`Either&amp;lt;/code&amp;gt; de `pymonad`शून्य से विभाजन के परिणामस्वरूप होने वाली संभावित त्रुटियों को संभालने के लिए - व्यक्तिगत सत्यापन यह सुनिश्चित करने के लिए कि मान का`b`यह शून्य के बराबर नहीं है। यदि यह शून्य के बराबर है, तो एक अपवाद उठाया जाता है, और`pymonad`इसे परिणाम लौटाने के लिए इस अपवाद को पकड़ें`Left`त्रुटि दर्शाते हुए.&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Google Apps Script का परिचय</title>
            <link >https://cheroliv.com/blog/2023/0068_introduction_google_apps_script_post.html</link>
            <pubDate>Fri, 22 Dec 2023 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2023/0068_introduction_google_apps_script_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_विषय_सूची&amp;quot;&amp;gt;विषय-सूची&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;पढ़ने का समय : 30 मिनट&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#परिचय&amp;quot;&amp;gt;[परिचय]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Google Apps Script में बुनियादी संरचना&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#गूगल एप्स स्क्रिप्ट में प्रकार और चर&amp;quot;&amp;gt;[गूगल एप्स स्क्रिप्ट में प्रकार और चर]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#स्थिरांक&amp;quot;&amp;gt;चर, और Google Apps Script में अक्षर&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Google Apps Script में संचालन और ऑपरेटर&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Var, Let और Const Google Apps Script में&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Google Apps Script में नियंत्रण संरचनाएँ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#_google_apps_script_में_लूप&amp;quot;&amp;gt;Google Apps Script में लूप&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#गूगल ऐप्स स्क्रिप्ट में वस्तुएँ&amp;quot;&amp;gt;[गूगल ऐप्स स्क्रिप्ट में वस्तुएँ]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#फ़ंक्शन Google Apps Script में&amp;quot;&amp;gt;[फ़ंक्शन Google Apps Script में]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#पैरामीटर और स्कोप में Google Apps Script&amp;quot;&amp;gt;[पैरामीटर और स्कोप में Google Apps Script]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#Google Apps Script में रेस्ट और स्प्रेड ऑपरेटर&amp;quot;&amp;gt;[Google Apps Script में रेस्ट और स्प्रेड ऑपरेटर]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#Google Apps Script में विघटन द्वारा आवंटन&amp;quot;&amp;gt;[Google Apps Script में विघटन द्वारा आवंटन]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#कलेक्शन और घोषणात्मक प्रोग्रामिंग Google Apps Script में&amp;quot;&amp;gt;[कलेक्शन और घोषणात्मक प्रोग्रामिंग Google Apps Script में]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परिचय&amp;quot;&amp;gt;परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Google Apps Script (GAS) Google सेवाओं जैसे Google Sheets, Google Docs और Google Forms से जुड़ी एक स्क्रिप्ट विकास प्लेटफ़ॉर्म है। यह कार्यों को स्वचालित करने, कस्टम फ़ंक्शन जोड़ने और Google सेवाओं को एकीकृत करने की अनुमति देती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस ज्ञापन में, हम ठोस उदाहरणों के आधार पर Google Apps Script के मुख्य अवधारणाओं का पता लगाएंगे। हम चर, लूप, फ़ंक्शन जैसी अवधारणाओं के साथ-साथ अन्य कई चीज़ों को GAS के विशिष्ट संदर्भ में अनुकूलित करके देखेंगे।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_google_apps_script_में_मूल_संरचना&amp;quot;&amp;gt;Google Apps Script में मूल संरचना&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;शुरू करने से पहले, आइए Google Apps स्क्रिप्ट की मूल संरचना की जाँच करें।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Structure de base en Google Apps Script
 */
function exempleStructureGAS() {
    // Votre code ici
    Logger.log(&amp;quot;Hello, Google Apps Script!&amp;quot;);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_प्रकार_और_चर_google_apps_script_में&amp;quot;&amp;gt;प्रकार और चर Google Apps Script में&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Google Apps Script को प्रोग्रामिंग भाषा के रूप में JavaScript का उपयोग करता है। डेटा प्रकार और चर मानक JavaScript की तरह काम करते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Types et Variables en Google Apps Script
 */
function exempleTypesVariablesGAS() {
    // Votre code ici
    var nombre = 42;
    var texte = &amp;quot;Bonjour, Google Apps Script!&amp;quot;;
    Logger.log(nombre);
    Logger.log(texte);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_गूगल_ऐप्स_स्क्रिप्ट_में_संचालन_और_संचालक&amp;quot;&amp;gt;गूगल ऐप्स स्क्रिप्ट में संचालन और संचालक&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Google Apps Script में ऑपरेशन और ऑपरेटर JavaScript के समान होते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Opérations et Opérateurs en Google Apps Script
 */
function exempleOperationsGAS() {
    // Votre code ici
    var x = 10;
    var y = 5;
    var resultat = x + y;
    Logger.log(resultat);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_var_let_और_const_google_apps_script_में&amp;quot;&amp;gt;Var, Let और Const Google Apps Script में&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;GAS में, अवधारणाओं का`var`, &amp;lt;code&amp;gt;let&amp;lt;/code&amp;gt;, et `const`इन्हें चर को घोषित करने के लिए उपयोग किया जाता है। हालाँकि, उनके अंतर और उनके निहितार्थ को समझना आवश्यक है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Var, Let et Const en Google Apps Script
 */
function exempleVarLetConstGAS() {
    // Votre code ici
    // Utilisation de var
    var x = 10;
    if (true) {
        var x = 20; // La variable x est modifiée globalement
    }
    Logger.log(x);

    // Utilisation de let
    let y = 30;
    if (true) {
        let y = 40; // La variable y est limitée au bloc if
    }
    Logger.log(y);

    // Utilisation de const
    const z = 50;
    // z = 60; // Impossible de réassigner une constante
    Logger.log(z);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_नियंत्रण_संरचनाएँ_google_apps_script_में&amp;quot;&amp;gt;नियंत्रण संरचनाएँ Google Apps Script में&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;नियंत्रण संरचनाएँ जैसे`if`, &amp;lt;code&amp;gt;else&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;while&amp;lt;/code&amp;gt; et `for`इन्हें Google Apps Script में निष्पादन प्रवाह को प्रबंधित करने के लिए प्रयोग किया जाता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Structures de Contrôle en Google Apps Script
 */
function exempleStructuresControleGAS() {
    // Votre code ici
    var condition = true;

    if (condition) {
        Logger.log(&amp;quot;La condition est vraie.&amp;quot;);
    } else {
        Logger.log(&amp;quot;La condition est fausse.&amp;quot;);
    }

    var compteur = 0;
    while (compteur &amp;amp;lt; 5) {
        Logger.log(compteur);
        compteur++;
    }

    for (var i = 0; i &amp;amp;lt; 3; i++) {
        Logger.log(i);
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_पैरामीटर_और_स्कोप्स_google_apps_script_में&amp;quot;&amp;gt;पैरामीटर और स्कोप्स Google Apps Script में&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पैरामीटर और स्कोप GAS में स्क्रिप्ट विकास में एक महत्वपूर्ण भूमिका निभाते हैं। समझें कि वे कैसे काम करते हैं ताकि अप्रत्याशित व्यवहार से बचा जा सके।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Paramètres et Scopes en Google Apps Script
 */
function exempleParametresScopesGAS(parametre) {
    // Votre code ici
    var variableGlobale = &amp;quot;Je suis global&amp;quot;;

    function afficherParametre() {
        Logger.log(parametre);
    }

    afficherParametre();
    Logger.log(variableGlobale);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_google_apps_script_में_स्थिरांक_चर_और_अक्षर&amp;quot;&amp;gt;Google Apps Script में स्थिरांक, चर, और अक्षर&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अंतर को समझना`const`, &amp;lt;code&amp;gt;var&amp;lt;/code&amp;gt;, et `let`यह Google Apps Script में चर के प्रभावी उपयोग के लिए आवश्यक है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Constantes, Variables, et Lettres en Google Apps Script
 */
function exempleConstantesVariablesLettresGAS() {
    // Votre code ici
    const constante = &amp;quot;Je ne change pas&amp;quot;;
    Logger.log(constante);

    var variable = &amp;quot;Je peux changer&amp;quot;;
    Logger.log(variable);

    let lettre = &amp;quot;Je peux aussi changer, mais seulement dans mon bloc&amp;quot;;
    Logger.log(lettre);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_google_apps_script_में_लूप&amp;quot;&amp;gt;Google Apps Script में लूप&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;लूप, जैसे`for` et &amp;lt;code&amp;gt;while&amp;lt;/code&amp;gt;, तत्वों पर इटरेट करने और दोहराव वाले संचालन करने के लिए आवश्यक हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Boucles en Google Apps Script
 */
function exempleBouclesGAS() {
    // Votre code ici
    for (var i = 0; i &amp;amp;lt; 3; i++) {
        Logger.log(i);
    }

    var condition = true;
    var compteur = 0;

    while (condition) {
        Logger.log(&amp;quot;Tour de boucle&amp;quot;);
        compteur++;
        if (compteur === 3) {
            condition = false;
        }
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_गूगल_एप्स_स्क्रिप्ट_में_वस्तुएँ&amp;quot;&amp;gt;गूगल एप्स स्क्रिप्ट में वस्तुएँ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;वस्तुओं का उपयोग डेटा को संरचित करने के लिए किया जाता है। GAS में, कई अंतर्निहित वस्तुएं Google सेवाओं के साथ इंटरैक्शन को सुगम बनाती हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Objets en Google Apps Script
 */
function exempleObjetsGAS() {
    // Votre code ici
    var feuille = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
    var cellule = feuille.getRange(&amp;quot;A1&amp;quot;);
    cellule.setValue(&amp;quot;Nouvelle valeur&amp;quot;);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_google_apps_script_में_स्थिरांक_चर_और_अक्षर_2&amp;quot;&amp;gt;Google Apps Script में स्थिरांक, चर और अक्षर&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अंतर को समझना`const`, &amp;lt;code&amp;gt;var&amp;lt;/code&amp;gt;, et `let`यह आवश्यक है Google Apps Script में चरों के प्रभावी उपयोग के लिए।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Constantes, Variables, et Lettres en Google Apps Script
 */
function exempleConstantesVariablesLettresGAS() {
    // Votre code ici
    const constante = &amp;quot;Je ne change pas&amp;quot;;
    Logger.log(constante);

    var variable = &amp;quot;Je peux changer&amp;quot;;
    Logger.log(variable);

    let lettre = &amp;quot;Je peux aussi changer, mais seulement dans mon bloc&amp;quot;;
    Logger.log(lettre);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_google_apps_script_में_फ़ंक्शन&amp;quot;&amp;gt;Google Apps Script में फ़ंक्शन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फ़ंक्शन प्रोग्रामिंग में मूलभूत तत्व होते हैं। GAS में, उन्हें विभिन्न तरीकों से घोषित और कॉल किया जा सकता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Fonctions en Google Apps Script
 */
function exempleFonctionsGAS() {
    // Votre code ici
    function additionner(a, b) {
        return a + b;
    }

    var resultat = additionner(2, 3);
    Logger.log(resultat);

    // Fonction anonyme
    var multiplier = function (x, y) {
        return x * y;
    };

    Logger.log(multiplier(4, 5));
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_गूगल_एप्स_स्क्रिप्ट_में_आराम_और_प्रसार_ऑपरेटर&amp;quot;&amp;gt;गूगल एप्स स्क्रिप्ट में आराम और प्रसार ऑपरेटर&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;विराम संचालक (&amp;lt;code&amp;gt;&amp;amp;#8230;&amp;amp;#8203;&amp;lt;/code&amp;gt;) और प्रसार की (&amp;lt;code&amp;gt;&amp;amp;#8230;&amp;amp;#8203;&amp;lt;/code&amp;gt;) ये एरे (या सरणी) और ऑब्जेक्ट को संक्षिप्त रूप से नियंत्रित करने में उपयोगी हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Opérateurs de Repos et de Propagation en Google Apps Script
 */
function exempleOperateursReposPropagationGAS() {
    // Votre code ici
    // Opérateur de repos (...) pour les tableaux
    var nombres = [1, 2, 3, 4, 5];
    var [...copieNombres] = nombres;
    Logger.log(copieNombres);

    // Opérateur de propagation (...) pour les objets
    var objOriginal = { x: 1, y: 2 };
    var objClone = { ...objOriginal, z: 3 };
    Logger.log(objClone);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_google_apps_script_में_विघटन_द्वारा_असाइनमेंट&amp;quot;&amp;gt;Google Apps Script में विघटन द्वारा असाइनमेंट&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;विनियोजन द्वारा विघटन एक शक्तिशाली विशेषता है जो वस्तुओं और ऐरे से मान को संक्षिप्त रूप में निकालने की अनुमति देती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Affectation par Décomposition en Google Apps Script
 */
function exempleAffectationDecompositionGAS() {
    // Votre code ici
    var coordonnees = [3, 4];
    var [x, y] = coordonnees;
    Logger.log(x);
    Logger.log(y);

    var utilisateur = { nom: &amp;quot;John&amp;quot;, age: 30 };
    var { nom, age } = utilisateur;
    Logger.log(nom);
    Logger.log(age);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_collections_et_programmation_déclarative_en_google_apps_script&amp;quot;&amp;gt;Collections et Programmation Déclarative en Google Apps Script&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Google Apps Script डेटा संरचनाओं जैसे कि एरे का समर्थन करता है, और कार्यात्मक प्रोग्रामिंग तथा घोषित इटरेशन की अवधारणाओं (&amp;amp;gt;&amp;amp;lt;आदेशात्मक) जैसे कि`map`, &amp;lt;code&amp;gt;reduce&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;forEach&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Collections et Programmation Déclarative en Google Apps Script
 */
function exempleCollectionsFonctionnelleGAS() {
    // Votre code ici
    // Exemple de tableau (collection)
    var nombres = [1, 2, 3, 4, 5];

    // Utilisation de forEach
    nombres.forEach(function (nombre) {
        Logger.log(nombre);
    });

    // Utilisation de map
    var carresNombres = nombres.map(function (nombre) {
        return nombre * nombre;
    });
    Logger.log(carresNombres);

    // Utilisation de reduce
    var somme = nombres.reduce(function (acc, nombre) {
        return acc + nombre;
    }, 0);
    Logger.log(somme);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_निष्कर्ष&amp;quot;&amp;gt;निष्कर्ष&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस मेमो ने Google Apps Script के मूलभूत अवधारणाओं को ठोस कोड उदाहरणों के माध्यम से समझाते हुए कवर किया। आप इस ज्ञान का उपयोग करके अपने दैनिक कार्यों को स्वचालित कर सकते हैं, अपने दस्तावेज़ों को वैयक्तिकृत कर सकते हैं और Google Apps Script की सभी सुविधाओं का पूर्ण उपयोग कर सकते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Google Form स्क्रिप्ट और स्वचालन पर एक्सप्रेस प्रशिक्षण</title>
            <link >https://cheroliv.com/blog/2023/0067_formation_express_sur_google_forms_script_post.html</link>
            <pubDate>Wed, 20 Dec 2023 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2023/0067_formation_express_sur_google_forms_script_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अवधि: 30 मिनट&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_उद्देश्य&amp;quot;&amp;gt;उद्देश्य&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Forms में Google Apps Script के मूल सिद्धांत समझें - स्क्रिप्ट एडिटर तक पहुँचना सीखें और ट्रिगर पर एक निर्देश निष्पादित करें&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_समय_खींचना&amp;quot;&amp;gt;समय खींचना&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;गूगल फ़ॉर्म स्क्रिप्ट का परिचय&amp;lt;/strong&amp;gt;(5 मिनट)&amp;lt;/p&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Google Form Script का त्वरित अवलोकन - मुख्य विशेषताओं की प्रस्तुति&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;एक Google फ़ॉर्म और एक संबंधित स्क्रिप्ट का निर्माण&amp;lt;/strong&amp;gt;(5 मिनट)&amp;lt;/p&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;गूगल फ़ॉर्म्स के साथ एक सरल फ़ॉर्म बनाना - संलग्न स्क्रिप्ट संपादक का परिचय&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;निर्देश निष्पादित करें&amp;lt;/strong&amp;gt;(10 मिनट)&amp;lt;/p&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;ऑन स्टार्ट ट्रिगर की कॉन्फ़िगरेशन &amp;quot;on start - ट्रिगर की कॉन्फ़िगरेशन \&amp;quot;on submit\ एक निर्देश चलाने के लिए एक स्क्रिप्ट लिखना - त्वरित परीक्षण जर्नल में सही काम करने की जाँच करने के लिए&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;परिणामों का विश्लेषण और सर्वोत्तम प्रथाएँ&amp;lt;/strong&amp;gt;(10 मिनट)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;निर्देश के निष्पादन के परिणामों की पुष्टि - स्क्रिप्ट के एक उदाहरण पर चर्चा और कैसे स्वचालन समय बचा सकता है&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_पूर्वशर्त&amp;quot;&amp;gt;पूर्वशर्त&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;एक Google खाता और Google Forms और Google Sheets तक पहुँच होना&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_सामग्री&amp;quot;&amp;gt;सामग्री&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कंप्यूटर के साथ एक वेब ब्राउज़र और एक इंटरनेट कनेक्शन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_टिप्पणी&amp;quot;&amp;gt;टिप्पणी&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह एक्सप्रेस प्रशिक्षण Google Form Script के साथ स्वचालन का त्वरित परिचय देता है। एक गहरी समझ के लिए, लंबी अवधि के प्रशिक्षण की सिफ़ारिश की जाती है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_1_google_form_स्क्रिप्ट_का_परिचय&amp;quot;&amp;gt;1 - Google Form स्क्रिप्ट का परिचय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_slide_1_google_form_script_का_त्वरित_अवलोकन&amp;quot;&amp;gt;Slide 1: Google Form Script का त्वरित अवलोकन&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Google Form Script एक Google Forms में एम्बेडेड स्क्रिप्टिंग प्लेटफ़ॉर्म है। - यह कस्टम फ़ीचर जोड़ने और कार्यों को स्वचालित करने की अनुमति देता है।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_स्लाइड_2_मुख्य_सुविधाओं_का_परिचय&amp;quot;&amp;gt;स्लाइड 2: मुख्य सुविधाओं का परिचय&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;Script Editor : इंटीग्रेटेड स्क्रिप्ट एडिटर Google Apps Script स्क्रिप्ट लिखने के लिए - ट्रिगर : &amp;#39;on submit&amp;#39; जैसी घटनाएँ जो स्क्रिप्ट के निष्पादन को सक्रिय करती हैं।&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_slide_3_google_फ़ॉर्म_स्क्रिप्ट_के_उपयोग_के_लाभ&amp;quot;&amp;gt;Slide 3: Google फ़ॉर्म स्क्रिप्ट के उपयोग के लाभ&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;कस्टमाइज़ेशन: अद्वितीय सुविधाओं के साथ कस्टम फ़ॉर्म बनाएँ। - ऑटोमेशन: फ़ॉर्म प्रतिक्रियाओं के जवाब में कार्यों को स्वचालित करें. - इंटीग्रेशन : अन्य Google सेवाओं के साथ स्क्रिप्ट को एकीकृत करें एक समृद्ध अनुभव के लिए।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_प्रस्तुतकर्ता_के_लिए_नोट&amp;quot;&amp;gt;प्रस्तुतकर्ता के लिए नोट:&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;ये सुविधाएँ फ़ॉर्म को अनुकूलित और स्वचालित करने के लिए बहुत अधिक क्षमता प्रदान करती हैं। इस प्रशिक्षण के अगले भाग में स्क्रिप्ट और विशिष्ट ऑटोमेशन के निर्माण का विस्तृत अन्वेषण किया जाएगा।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://developers.google.com/apps-script/add-ons/editors/forms?hl=fr&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://developers.google.com/apps-script/add-ons/editors/forms?hl=fr&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://developers.google.com/apps-script/reference/forms?hl=fr&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://developers.google.com/apps-script/reference/forms?hl=fr&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://developers.google.com/apps-script/reference/forms/form-app?hl=fr&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://developers.google.com/apps-script/reference/forms/form-app?hl=fr&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_गूगल_फ़ॉर्म_और_संबंधित_स्क्रिप्ट_बनाना_5_मिनट&amp;quot;&amp;gt;गूगल फ़ॉर्म और संबंधित स्क्रिप्ट बनाना (5 मिनट)&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>पायथन मेमो</title>
            <link >https://cheroliv.com/blog/2023/0066_memo_python_post.html</link>
            <pubDate>Sun, 19 Nov 2023 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2023/0066_memo_python_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_विंडोज़_पर_पायथन_इंस्टॉल_करें&amp;quot;&amp;gt;विंडोज़ पर पायथन इंस्टॉल करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://ninite.com/pythonx3/&amp;quot;&amp;gt;विंडोज़ पर पायथन&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://python-docs.readthedocs.io/en/latest/starting/install3/win.html&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://python-docs.readthedocs.io/en/latest/starting/install3/win.html&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://python-docs.readthedocs.io/en/latest/dev/virtualenvs.html#virtualenvironments-ref&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://python-docs.readthedocs.io/en/latest/dev/virtualenvs.html#virtualenvironments-ref&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_पायथन_चल_रहा_है&amp;quot;&amp;gt;पायथन चल रहा है&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;संदर्भ :&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;cd mon_projet

python -m venv mon_venv

source mon_venv/bin/activate

# Sur windows
mon_venv\Scripts\activate

deactivate&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_इंस्टॉल_आवश्यकता&amp;quot;&amp;gt;इंस्टॉल आवश्यकता&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;pip install -r requirements.txt&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_प्रारंभ&amp;quot;&amp;gt;प्रारंभ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://python.doctor/page-apprendre-programmation-orientee-objet-poo-classes-python-cours-debutants&amp;quot;&amp;gt;python वस्तु-उन्मुख प्रोग्रामिंग&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_gof_के_डिज़ाइन_पैटर्न_python_में&amp;quot;&amp;gt;GoF के डिज़ाइन पैटर्न Python में&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/whikwon/python-patterns/&amp;quot;&amp;gt;कार्यान्वयन 1&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/Sean-Bradley/Design-Patterns-In-Python&amp;quot;&amp;gt;कार्यान्वयन 2&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://sbcode.net/python/&amp;quot;&amp;gt;पूरी किताब&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;GoF के डिज़ाइन पैटर्न 23 डिज़ाइन पैटर्न का एक सेट हैं जिन्हें पुस्तक &amp;quot;Design Patterns: Elements of Reusable Object-Oriented Software&amp;quot; में वर्णित किया गया है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;।यहाँ GoF डिज़ाइन पैटर्न की सूची है&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0833%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 2.0849%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;नाम&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Description&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;फ़ैक्टरी मेथड&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;सटीक क्लास निर्दिष्ट किए बिना वस्तुएँ बनाएँ।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;अब्स्ट्रैक्ट फ़ैक्टरी&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;सम्बद्ध या आश्रित वस्तुओं के परिवार बनाएँ बिना उनके वास्तविक वर्ग को निर्दिष्ट किए।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Builder&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;जटिल वस्तु के निर्माण को उसके प्रतिनिधित्व से अलग करें ताकि समान निर्माण प्रक्रिया विभिन्न प्रतिनिधित्व बना सके।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;प्रोटोटाइप&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;मौजूदा प्रोटोटाइप को कॉपी करके नई वस्तुएँ बनाएँ।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;एकल&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक वर्ग के इंस्टेंशिएशन को एक ही ऑब्जेक्ट तक सीमित करता है।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;अडैप्टर&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;क्लास की इंटरफ़ेस को क्लाइंट की अपेक्षित दूसरी इंटरफ़ेस में बदल देता है&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;पुल&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक अब्सट्रैक्शन को इसके कार्यान्वयन से अलग करें ताकि दोनों स्वतंत्र रूप से भिन्न हो सकें।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;संयुक्त&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;पेड़ संरचनाओं में वस्तुओं को संयोजित करके भाग-पूर्ण पदानुक्रम का प्रतिनिधित्व करें।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;सजावटकार&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक वस्तु पर गतिशील रूप से अतिरिक्त जिम्मेदारियाँ संलग्न करें।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;फ़ैसेड&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक सबसिस्टम में इंटरफ़ेस के एक सेट के लिए एक एकीकृत इंटरफ़ेस प्रदान करता है।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;फ्लाइवेट&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;हल्के वस्तुओं के निर्माण और उपयोग की लागत कम करता है।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;प्रॉक्सी&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;दूसरे वस्तु के लिए एक विकल्प या स्थानापन्न प्रदान करता है ताकि उसके&amp;amp;#8217;accès को नियंत्रित किया जा सके।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;जिम्मेदारी की श्रृंखला&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक से अधिक ऑब्जेक्ट को एक अनुरोध को प्रोसेस करने की अनुमति देता है।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;आदेश&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक वस्तु में एक अनुरोध को संलग्न करके, विभिन्न अनुरोधों, कतारों या लॉग के साथ क्लाइंट्स को पैरामीट्रिकृत करने की सुविधा मिलती है, और अनुलटनीय संचालन का समर्थन किया जा सकता है।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;अनुवादक&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक भाषा की व्याकरण का एक प्रतिनिधित्व प्रदान करें और इस प्रतिनिधित्व का उपयोग उस भाषा में वाक्यों का अर्थ निकालने के लिए करें।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;इटरेटर&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक संग्रहीत ऑब्जेक्ट के तत्वों को अनुक्रमिक रूप से पार करने का एक तरीका प्रदान करता है, बिना इसके अंतर्निहित प्रतिनिधित्व को उजागर किए।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;मध्यस्थ&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;वस्तुओं के बीच जटिल निर्भरताओं को कम करने की अनुमति देता है, उन्हें केवल एक माध्यमक वस्तु के माध्यम से संवाद करने के लिए बनाकर।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;यादगार&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;यह एक वस्तु को उसकी पूर्व स्थिति में पुनर्स्थापित करने की क्षमता प्रदान करता है (संलग्नता का उल्लंघन किए बिना).&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;प्रेक्षक&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक-से-बहुत संबंध परिभाषित करता है वस्तुओं के बीच ताकि जब कोई वस्तु अपनी स्थिति बदलती है, तो सभी उसके आश्रित स्वचालित रूप से सूचित और अपडेट किए जाते हैं।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;राज्य&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक वस्तु को अपने व्यवहार को बदलने की अनुमति देता है जब उसका आंतरिक स्थिति बदलता है।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;रणनीति&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;यह एक एल्गोरिदम के परिवार को परिभाषित करता है, प्रत्येक को संलग्न करता है और उन्हें विनिमेय बनाता है।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;टेम्प्लेट पद्धति&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक पद्धति में एक एल्गोरिदम का ढाँचा परिभाषित करता है, कुछ चरणों को उपवर्गों को सौंप देता है।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;आगंतुक&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;यह एक वस्तु संरचना पर एक नई ऑपरेशन करने के लिए परिभाषित करने की अनुमति देता है, वस्तुओं की कक्षाओं को बदले बिना जिन पर यह संचालित होती है।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_कार्यात्मक_प्रोग्रामिंग&amp;quot;&amp;gt;कार्यात्मक प्रोग्रामिंग&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 16.6666%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 27.7777%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 55.5557%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;पुस्तकालय&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;URL&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Description&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;PyMonad&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/jasondelaat/pymonad&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://github.com/jasondelaat/pymonad&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;PyMonad एक कार्यान्वयन है मोनाडिक डेटा संरचनाओं का पायथन में, हास्केल और एफ़# जैसे प्रोग्रामिंग भाषाओं पर आधारित, जिसमें फलनीय प्रोग्रामिंग में सबसे अधिक प्रयोग किए जाने वाले मोनाड प्रकारों के लिए कार्यान्वयन हैं।https://www.miguelfarrajota.com/2021/06/monads-in-python-with-pymonad/[article]&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;PyFunctional&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/EntilZha/PyFunctional/&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://github.com/EntilZha/PyFunctional/&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;PyFunctional` एक Python लाइब्रेरी है कार्यात्मक प्रोग्रामिंग के लिए जो शुद्ध कार्यों और इटरेबल के साथ काम करने के लिए उपकरण प्रदान करती है।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;टूल्ज़&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://toolz.readthedocs.io/en/latest/&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://toolz.readthedocs.io/en/latest/&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Toolz एक Python लाइब्रेरी है जो कार्यात्मक प्रोग्रामिंग के लिए उपकरण प्रदान करती है जो शुद्ध फ़ंक्शन और इटरेबल के साथ काम करने के लिए टूल देती है।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;फ़ंक्शन.py&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/kachayev/fn.py&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://github.com/kachayev/fn.py&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;Fn.py` एक Python लाइब्रेरी है फंक्शनल प्रोग्रामिंग के लिए जो शुद्ध कार्यों और इटरेबल्स के साथ काम करने के लिए उपकरण प्रदान करती है।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;नारियल&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://coconut-lang.org/&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://coconut-lang.org/&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;कोकोनट पायथन में कई कार्यात्मक सुविधाएँ जोड़ता है, जिसमें पैटर्न मेलिंग भी शामिल है।https://stackoverflow.com/questions/11909681/are-there-pattern-matching-functions-in-python-like-this[संवाद sof]&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_दुष्प्रभाव&amp;quot;&amp;gt;दुष्प्रभाव&amp;lt;/h3&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_लूप्स&amp;quot;&amp;gt;लूप्स&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-python&amp;quot; data-lang=&amp;quot;python&amp;quot;&amp;gt;# impérative way
result = []
for i in inputs:
    x = f(g(i))
    result.append(x)

# idiomatic way
result = map(comp(f,g), inputs)&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>वेब डेव</title>
            <link >https://cheroliv.com/blog/2023/0065_training_web_dev_post.html</link>
            <pubDate>Thu, 24 Aug 2023 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2023/0065_training_web_dev_post.html</guid>
            <description></description>
        </item><item>
            <title>ट्रेडिंग कार्ड गेम्स (TCGs)</title>
            <link >https://cheroliv.com/blog/2023/0064_training_trading_card_games_post.html</link>
            <pubDate>Mon, 21 Aug 2023 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2023/0064_training_trading_card_games_post.html</guid>
            <description></description>
        </item><item>
            <title>नोट Typescript</title>
            <link >https://cheroliv.com/blog/2023/0063_memo_ts_post.html</link>
            <pubDate>Sat, 19 Aug 2023 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2023/0063_memo_ts_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;गिटहब रिपॉज़िटरी:https://github.com/cheroliv/ts-codebase[ts-codebase, window=&amp;quot;_blank]&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;toc_ts&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय टाइप्स्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;(No content to translate)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#फ़ंक्शन&amp;quot;&amp;gt;फ़ंक्शन&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#data_struct&amp;quot;&amp;gt;डेटा संरचना&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#enums_tuples&amp;quot;&amp;gt;एनम्स और ट्यूपल&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#void_never&amp;quot;&amp;gt;Void और Never&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#class_interface&amp;quot;&amp;gt;क्लासेज़ और इंटरफ़ेस&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#tsconfig&amp;quot;&amp;gt;फ़ाइल tsconfig.json&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#modules&amp;quot;&amp;gt;मॉड्यूल्स&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#वादे&amp;quot;&amp;gt;[वादे]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#async-await&amp;quot;&amp;gt;async/await&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;जेनेरिक&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;index.html&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;!DOCTYPE html&amp;amp;gt;
&amp;amp;lt;html lang=&amp;quot;fr&amp;quot;&amp;amp;gt;

&amp;amp;lt;head&amp;amp;gt;
    &amp;amp;lt;meta charset=&amp;quot;UTF-8&amp;quot;&amp;amp;gt;
    &amp;amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;meta http-equiv=&amp;quot;X-UA-Compatible&amp;quot; content=&amp;quot;ie=edge&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;title&amp;amp;gt;Document&amp;amp;lt;/title&amp;amp;gt;
&amp;amp;lt;/head&amp;amp;gt;

&amp;amp;lt;body&amp;amp;gt;
    Intro typescript
    &amp;amp;lt;script src=&amp;quot;01_types.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
    &amp;amp;lt;script src=&amp;quot;02_data_structure.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
    &amp;amp;lt;script src=&amp;quot;03_enums_tuples.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
&amp;amp;lt;/body&amp;amp;gt;

&amp;amp;lt;/html&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;ts_types&amp;quot;&amp;gt;टाइप्सक्रिप्ट में प्रकार&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;01_types.ts&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-typescript&amp;quot; data-lang=&amp;quot;typescript&amp;quot;&amp;gt;/**
 * Les types en typescript
 */

//quand le type n&amp;#39;est pas defini des le debut,
// alors il est réassignable
// c&amp;#39;est le type Any qui est attribué par défaut
let my_var;
my_var = &amp;quot;username&amp;quot;;
console.assert(my_var === &amp;quot;username&amp;quot;);
my_var = 11;
console.assert(my_var === 11);
my_var = true;
console.assert(my_var === true);

let age = 1;
console.assert(age === 1);
age = 2;
// age=&amp;quot;trois&amp;quot; c&amp;#39;est impossible
// car l&amp;#39;inference de type a attribué le type number
console.assert(age === 2);

// Déclaration explicite de type
let pi: Number = 3.14;
console.assert(typeof pi === &amp;quot;number&amp;quot;);&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_ts&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय टाइप्स्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;फ़ंक्शन&amp;quot;&amp;gt;फ़ंक्शन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फ़ंक्शन पुन: प्रयुक्त कोड के ब्लॉक हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;रेटिंग का उदाहरण:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-typescript&amp;quot; data-lang=&amp;quot;typescript&amp;quot;&amp;gt;const add = (a: number, b: number): number =&amp;amp;gt; a + b;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_ts&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय टाइप्स्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;data_struct&amp;quot;&amp;gt;डेटा संरचना&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;02_data_structure.ts&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-typescript&amp;quot; data-lang=&amp;quot;typescript&amp;quot;&amp;gt;/***
 * Structure de données:
 * Avec le type any on peut changer
 * le type de la variable à tout instruction
 * Lorsque l&amp;#39;on fixe le type
 * alors il n&amp;#39;est plus possible de le changer
 * lors d&amp;#39;une assignation
 */

// Arrays
let buddies: any[] = [
    &amp;quot;cheroliv&amp;quot;,
    &amp;quot;imrandeh&amp;quot;,
    &amp;quot;issoudeh&amp;quot;,
    &amp;quot;soumi92&amp;quot;
]

console.assert(buddies[0] === &amp;quot;cheroliv&amp;quot;);
console.assert(buddies[1] === &amp;quot;imrandeh&amp;quot;);
console.assert(buddies[2] === &amp;quot;issoudeh&amp;quot;);
console.assert(buddies[3] === &amp;quot;soumi92&amp;quot;);
// Déclaré en type any, l&amp;#39;inference de type
// a bien réaligné en type string
console.assert(typeof buddies[0] === &amp;quot;string&amp;quot;);
console.assert(typeof buddies[1] === &amp;quot;string&amp;quot;);
console.assert(typeof buddies[2] === &amp;quot;string&amp;quot;);
console.assert(typeof buddies[3] === &amp;quot;string&amp;quot;);



let writers: (String | String | String | Number)[][] = [
    [&amp;quot;Chrétien&amp;quot;, &amp;quot;de Troyes&amp;quot;, &amp;quot;fr&amp;quot;, 12],
    [&amp;quot;François&amp;quot;, &amp;quot;Rabelais&amp;quot;, &amp;quot;fr&amp;quot;, 16],
    [&amp;quot;René&amp;quot;, &amp;quot;Descartes&amp;quot;, &amp;quot;fr&amp;quot;, 17],
    [&amp;quot;Jean-Jacques&amp;quot;, &amp;quot;Rousseau&amp;quot;, &amp;quot;fr&amp;quot;, 18],
    [&amp;quot;Georg&amp;quot;, &amp;quot;Hegel&amp;quot;, &amp;quot;de&amp;quot;, 19],
    [&amp;quot;Karl&amp;quot;, &amp;quot;Marx&amp;quot;, &amp;quot;de&amp;quot;, 19],
    [&amp;quot;Friedrich&amp;quot;, &amp;quot;Engels&amp;quot;, &amp;quot;de&amp;quot;, 19],
    [&amp;quot;Victor&amp;quot;, &amp;quot;Hugo&amp;quot;, &amp;quot;fr&amp;quot;, 19],
    [&amp;quot;Paul&amp;quot;, &amp;quot;Verlaine&amp;quot;, &amp;quot;fr&amp;quot;, 19],
    [&amp;quot;Arthur&amp;quot;, &amp;quot;Rimbaud&amp;quot;, &amp;quot;fr&amp;quot;, 19],
    [&amp;quot;Gérard&amp;quot;, &amp;quot;de Nerval&amp;quot;, &amp;quot;fr&amp;quot;, 19],
    [&amp;quot;Georg&amp;quot;, &amp;quot;Lukacs&amp;quot;, &amp;quot;hu&amp;quot;, 20],
    [&amp;quot;Franz&amp;quot;, &amp;quot;Kafka&amp;quot;, &amp;quot;hu&amp;quot;, 20],
    [&amp;quot;Antonio&amp;quot;, &amp;quot;Gramsci&amp;quot;, &amp;quot;it&amp;quot;, 20],
    [&amp;quot;Domenico&amp;quot;,&amp;quot;Losurdo&amp;quot;,&amp;quot;it&amp;quot;,20],
];

// console.table(writers);


// Objects
let author: {
    first_name: String,
    last_name: String,
    lang: String,
    century: Number
} = {
    // slice(-1) renvoie le dernier élèment
    first_name: writers.slice(-1)[0][0] as String,
    last_name: writers.slice(-1)[0][1] as String,
    lang: writers.slice(-1)[0][2] as String,
    century: writers.slice(-1)[0][3] as Number,
}


// assertion sur la valeur en accés par encapsulation(dot)
console.assert(author.first_name === &amp;quot;Antonio&amp;quot;)
console.assert(author.last_name === &amp;quot;Gramsci&amp;quot;)
console.assert(author.lang === &amp;quot;it&amp;quot;)
console.assert(author.century === 20);

// assertion sur le type en accès par index
console.assert(typeof author[&amp;quot;first_name&amp;quot;] === &amp;quot;string&amp;quot;)
console.assert(typeof author[&amp;quot;last_name&amp;quot;] === &amp;quot;string&amp;quot;)
console.assert(typeof author[&amp;quot;lang&amp;quot;] === &amp;quot;string&amp;quot;)
console.assert(typeof author[&amp;quot;century&amp;quot;] === &amp;quot;number&amp;quot;);&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_ts&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय टाइप्स्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;enums_tuples&amp;quot;&amp;gt;एनम्स और ट्यूपल&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;03_सूची_टुपल.ts&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-typescript&amp;quot; data-lang=&amp;quot;typescript&amp;quot;&amp;gt;/**
 * Enums et Tuples
 *
 * Enum: il existe les enums numérique
 * et les enums chaine de caracteres.
 *
 * Tuple: similaire aux arrays mais ne peut
 * contenir qu&amp;#39;une valeur de type spécifié.
 *
 */

//Enum numérique
// l&amp;#39;index par de debut défaut est 0
// ici on le place a 1
enum Week {
    Monday = 1,
    Tuesday = 2,
    Wednesday = 3,
    Thursday = 4,
    Friday = 5,
    Saturday = 6,
    Sunday = 7,
};

console.assert(Week.Monday == 1);
console.assert(Week.Tuesday == 2);
console.assert(Week.Wednesday == 3);
console.assert(Week.Thursday == 4);
console.assert(Week.Friday == 5);
console.assert(Week.Saturday == 6);
console.assert(Week.Sunday == 7);

console.assert(Week[1] === &amp;quot;Monday&amp;quot;);
console.assert(Week[2] === &amp;quot;Tuesday&amp;quot;);
console.assert(Week[3] === &amp;quot;Wednesday&amp;quot;);
console.assert(Week[4] === &amp;quot;Thursday&amp;quot;);
console.assert(Week[5] === &amp;quot;Friday&amp;quot;);
console.assert(Week[6] === &amp;quot;Saturday&amp;quot;);
console.assert(Week[7] === &amp;quot;Sunday&amp;quot;);

let motd_arr_fr: String[] = [
    &amp;quot;Associé à la Lune&amp;quot;,
    &amp;quot;Du dieu Tiw, associé à Mars&amp;quot;,
    &amp;quot;Du dieu germanique Odin&amp;quot;,
    &amp;quot;Du dieu germanique du tonnerre Thor&amp;quot;,
    &amp;quot;De la déesse germanique Frigga associée à Vénus&amp;quot;,
    &amp;quot;Associé à Saturne&amp;quot;,
    &amp;quot;Associé au Soleil&amp;quot;,
];

let motd_arr_en: String[] = [
    &amp;quot;associated with the Moon&amp;quot;,
    &amp;quot;from the god Tiw, associated with Mars&amp;quot;,
    &amp;quot;from Germanic god Odin&amp;quot;,
    &amp;quot;from Germanic god of thunder Thor&amp;quot;,
    &amp;quot;from Germanic goddess Frigga associated with Venus&amp;quot;,
    &amp;quot;associated with Saturn&amp;quot;,
    &amp;quot;associated with the Sun&amp;quot;,
];

// Un tuple (triple)
let monday_triple_fr: [
    Number,
    String,
    String
] = [
        Week.Monday,
        Week[Week.Monday],
        motd_arr_fr[0],
    ];


console.assert(monday_triple_fr[0] === 1);
console.assert(monday_triple_fr[1] === &amp;quot;Monday&amp;quot;);
console.assert(monday_triple_fr[2] === &amp;quot;Associé à la Lune&amp;quot;);


let monday_triple_en: [
    Number,
    String,
    String
] = [
        Week.Monday,
        Week[Week.Monday],
        motd_arr_en[0],
    ];

console.assert(monday_triple_en[0] === 1);
console.assert(monday_triple_en[1] === &amp;quot;Monday&amp;quot;);
console.assert(monday_triple_en[2] === &amp;quot;associated with the Moon&amp;quot;);


// On se fait un type pour ajouter le nom de la langue
type Meaning_of_the_day = {
    lang: String,
    meaning: (Week | String)[][],
};

//fonction d&amp;#39;affichage du type Meaning_of_the_day
const display_motd = (motd: Meaning_of_the_day) =&amp;amp;gt; {
    motd.meaning.forEach(day =&amp;amp;gt;
        console.table(`${Week[day[0] as Week]}: ${day[1]}.(${motd.lang})`)
    )
};

//fonction d&amp;#39;assertion sur le type Meaning_of_the_day
// afin de verifier la concordance du contenu avec
// motd_arr_#lang#
const test_motd = (
    motd: Meaning_of_the_day,
    motd_arr: String[]
) =&amp;amp;gt; {
    console.assert(motd.lang.length === 2)
    for (const [i, value] of motd.meaning.entries()) {
        console.assert(value[1] === motd_arr[i]);
    }
};


let motd_fr: Meaning_of_the_day = {
    lang: &amp;quot;fr&amp;quot;,
    meaning: [
        [Week.Monday, motd_arr_fr[0]],
        [Week.Tuesday, motd_arr_fr[1]],
        [Week.Wednesday, motd_arr_fr[2]],
        [Week.Thursday, motd_arr_fr[3]],
        [Week.Friday, motd_arr_fr[4]],
        [Week.Saturday, motd_arr_fr[5]],
        [Week.Sunday, motd_arr_fr[6]],
    ],
}

console.log(&amp;quot;---------&amp;quot;);
console.log(&amp;quot;display_motd(motd_fr):&amp;quot;);
display_motd(motd_fr);
test_motd(motd_fr, motd_arr_fr)


let motd_en: Meaning_of_the_day = {
    lang: &amp;quot;en&amp;quot;,
    meaning: [
        [Week.Monday, motd_arr_en[0]],
        [Week.Tuesday, motd_arr_en[1]],
        [Week.Wednesday, motd_arr_en[2]],
        [Week.Thursday, motd_arr_en[3]],
        [Week.Friday, motd_arr_en[4]],
        [Week.Saturday, motd_arr_en[5]],
        [Week.Sunday, motd_arr_en[6]],
    ],
}

console.log(&amp;quot;---------&amp;quot;);
console.log(&amp;quot;display_motd(motd_en):&amp;quot;);
display_motd(motd_en);
console.log(&amp;quot;---------&amp;quot;);
test_motd(motd_en, motd_arr_en);

// Un tuple (triple) utilisant le type
// Meaning_of_the_day pour peupler le meaning
let motd_triple: [
    Number,
    String,
    String
] = [
        Week.Monday,
        Week[Week.Monday],
        motd_fr.meaning[0][1] as String
    ];

console.assert(motd_triple[0] === 1);
console.assert(motd_triple[1] === &amp;quot;Monday&amp;quot;);
console.assert(motd_triple[2] === &amp;quot;Associé à la Lune&amp;quot;);&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_ts&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय टाइप्स्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;void_never&amp;quot;&amp;gt;Void और Never&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;04_void_never_types.ts&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-typescript&amp;quot; data-lang=&amp;quot;typescript&amp;quot;&amp;gt;// Le type void est l&amp;#39;opposé du type any
// c&amp;#39;est l&amp;#39;absence de type.
function verify_writers_length(): void {
    console.assert(writers.length &amp;amp;gt; 0);
}

verify_writers_length();

const verify_writers_length_arrow = (): void =&amp;amp;gt;
    console.assert(writers.length &amp;amp;gt; 0);

verify_writers_length_arrow();

//Type of et never
let value = 30;
console.assert(typeof value === &amp;quot;number&amp;quot;);

//never: qqchs qui n&amp;#39;arrive jamais
function foo(x: String | Number): Boolean {
    if (typeof x === &amp;quot;string&amp;quot;) {
        return true;
    } else if (typeof x === &amp;quot;number&amp;quot;) {
        return false;
    }
    return fail(&amp;quot;Error!&amp;quot;)
}

function fail(message: String): never {
    throw new Error(message as string);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_ts&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय टाइप्स्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;class_interface&amp;quot;&amp;gt;क्लासेज़ और इंटरफ़ेस&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;04_void_never_types.ts&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-typescript&amp;quot; data-lang=&amp;quot;typescript&amp;quot;&amp;gt;/**
 * Les classes:
 * members,
 * visibility,
 * nommage,
 * accesseurs
 * scope identifier: static,private,protected
 *
 * convention de nommage :
 * Les membres private sont préfixés avec un _ *
 */

class Member {
    username: String = &amp;quot;&amp;quot;;
    email: String = &amp;quot;&amp;quot;;
    private _password: String = &amp;quot;&amp;quot;;
    readonly signup_date: Date = new Date(Date.now());

    constructor(username: String, email: String) {
        this.username = username;
        this.email = email;
    }

    get password(): String {
        return this._password;
    }

    set password(new_password: String) {
        this._password = new_password;
    }

    /**
     * Une fonction static qui initilise un member,
     * à partir d&amp;#39;un author
     */
    static fromAuthor(author: {
        first_name: String,
        last_name: String,
        lang: String,
        century: Number
    }): Member {
        return new Member(
            `${author.first_name}.${author.last_name}`,
            `${author.first_name}.${author.last_name}@acme.com`,
        );
    }
};


let domenico = Member.fromAuthor(author);
domenico.password = &amp;quot;test&amp;quot;;

console.assert(domenico.email === &amp;quot;Domenico.Losurdo@acme.com&amp;quot;);
console.assert(domenico.password === &amp;quot;test&amp;quot;);


// Héritage
enum Forms {
    Undefined = 0,
    Polygones = 1,
    Circle = 2,
    Straight = 3,
    Segment = 4,
};

class Form {
    type: Forms = Forms.Undefined;
};

class Rectangle extends Form {
    h: Number = 0;
    w: Number = 0;
};

class Square extends Rectangle {
    side: Number = 0;
};


/**
 * Interface donne un contrat à un type.
 * Les interfaces permettent de définir la structure d&amp;#39;un objet.
 */

interface IPerson {
    username: String;
    email: String;
    readonly signup_date: Date;
}

const user1: IPerson = {
    username: Member.fromAuthor(author)[&amp;quot;username&amp;quot;],
    email: Member.fromAuthor(author)[&amp;quot;email&amp;quot;],
    signup_date: Member.fromAuthor(author)[&amp;quot;signup_date&amp;quot;],
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_ts&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय टाइप्स्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;tsconfig&amp;quot;&amp;gt;फ़ाइल tsconfig.json&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;tsconfig.json&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-json&amp;quot; data-lang=&amp;quot;json&amp;quot;&amp;gt;{
  /* Visit https://aka.ms/tsconfig to read more about this file */
  &amp;quot;compileOnSave&amp;quot;: true,

  &amp;quot;compilerOptions&amp;quot;: {
    &amp;quot;target&amp;quot;: &amp;quot;es2016&amp;quot;,
    &amp;quot;module&amp;quot;: &amp;quot;CommonJS&amp;quot;,
    &amp;quot;noEmitOnError&amp;quot;: true,
    &amp;quot;strict&amp;quot;: true,
    &amp;quot;noImplicitAny&amp;quot;: true,
    &amp;quot;esModuleInterop&amp;quot;: true
  }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_ts&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय टाइप्स्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;modules&amp;quot;&amp;gt;मॉड्यूल्स&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मॉड्यूल से कोड को कई फ़ाइलों में व्यवस्थित किया जा सकता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;उदाहरण रेटिंग :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-typescript&amp;quot; data-lang=&amp;quot;typescript&amp;quot;&amp;gt;// Dans un fichier math.ts
export const add = (a: number, b: number): number =&amp;amp;gt; a + b;

// Dans un autre fichier
import { add } from &amp;#39;./math&amp;#39;;
let result = add(2, 3);&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_ts&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय टाइप्स्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;वायदे&amp;quot;&amp;gt;वायदे&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;प्रॉमिस का उपयोग असिंक्रोनस ऑपरेशन्स करने के लिए किया जाता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;उदाहरण रेटिंग :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-typescript&amp;quot; data-lang=&amp;quot;typescript&amp;quot;&amp;gt;const promise = new Promise&amp;amp;lt;string&amp;amp;gt;((resolve) =&amp;amp;gt; {
    // Code asynchrone ici
    resolve(&amp;quot;Succès&amp;quot;);
});

promise.then((result) =&amp;amp;gt; {
    console.log(result);
});&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_ts&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय टाइप्स्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;async-await&amp;quot;&amp;gt;async/await&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;async/await वादों के प्रबंधन को सरल बना देता है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;उदाहरण अंक :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-typescript&amp;quot; data-lang=&amp;quot;typescript&amp;quot;&amp;gt;const fetchData = async (): Promise&amp;amp;lt;void&amp;amp;gt; =&amp;amp;gt; {
    const result = await someAsyncFunction();
    console.log(result);
};&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_ts&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय टाइप्स्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;generiques&amp;quot;&amp;gt;जेनेरिक&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जनरिक्स पुन: प्रयोज्य घटकों को गतिशील प्रकारों के साथ बनाने की अनुमति देते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;उदाहरण रेटिंग :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-typescript&amp;quot; data-lang=&amp;quot;typescript&amp;quot;&amp;gt;const identity = &amp;amp;lt;T&amp;amp;gt;(arg: T): T =&amp;amp;gt; arg;

const output = identity&amp;amp;lt;string&amp;amp;gt;(&amp;quot;hello&amp;quot;);
console.log(output);&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>CSS नोट</title>
            <link >https://cheroliv.com/blog/2023/0062_memo_css_post.html</link>
            <pubDate>Mon, 14 Aug 2023 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2023/0062_memo_css_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;toc&amp;quot;&amp;gt;सामग्री की तालिका&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#good_links&amp;quot;&amp;gt;अच्छे लिंक&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#repo&amp;quot;&amp;gt;संग्रहालय और कोड नमूना&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_शुरू&amp;quot;&amp;gt;[toc_शुरू]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;good_links&amp;quot;&amp;gt;अच्छे लिंक&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc&amp;quot;&amp;gt;सामग्री की तालिका&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;repo&amp;quot;&amp;gt;संग्रहालय और कोड नमूना&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;गिटहब रिपॉज़िटरी:https://github.com/cheroliv/css-codebase[css-codebase, window = &amp;quot;_blank]&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;toc_début&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;शुरुआत CSS&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#शुरुआत_परिचय&amp;quot;&amp;gt;[शुरुआत_परिचय]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;(No content provided to translate)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#शुरुआत_background&amp;quot;&amp;gt;[शुरुआत_background]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;(No output)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#शुरू_flexbox&amp;quot;&amp;gt;[शुरू_flexbox]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#शुरू_ग्रिड&amp;quot;&amp;gt;ग्रिड&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#début_abs_pos&amp;quot;&amp;gt;[début_abs_pos]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;शुरुआत_responsive&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#शुरू निष्कर्ष&amp;quot;&amp;gt;[शुरू निष्कर्ष]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc&amp;quot;&amp;gt;सामग्री की तालिका&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;début_intro&amp;quot;&amp;gt;परिचय &amp;amp;amp; सेटअप&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस वीडियो के आधार पर परिचय:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;videoblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;iframe src=&amp;quot;https://www.youtube.com/embed/iSWjmVcfQGg?rel=0&amp;quot; frameborder=&amp;quot;0&amp;quot; allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;गिटहब रिपॉजिटरी:https://github.com/cheroliv/css-codebase/début_css/[शुरू CSS, window = &amp;quot;_blank]&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;नोट स्रोत:&amp;lt;br&amp;gt;
index.html&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;!DOCTYPE html&amp;amp;gt;
&amp;amp;lt;html lang=&amp;quot;fr&amp;quot;&amp;amp;gt;
  &amp;amp;lt;head&amp;amp;gt;
    &amp;amp;lt;meta charset=&amp;quot;UTF-8&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;meta http-equiv=&amp;quot;X-UA-Compatible&amp;quot; content=&amp;quot;IE=edge&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;title&amp;amp;gt;Cours CSS&amp;amp;lt;/title&amp;amp;gt;

    &amp;amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;style.css&amp;quot; /&amp;amp;gt;
  &amp;amp;lt;/head&amp;amp;gt;
  &amp;amp;lt;body&amp;amp;gt;
    &amp;amp;lt;header&amp;amp;gt;
      &amp;amp;lt;h1&amp;amp;gt;Les bases de CSS&amp;amp;lt;/h1&amp;amp;gt;
    &amp;amp;lt;/header&amp;amp;gt;

    &amp;amp;lt;main&amp;amp;gt;
      &amp;amp;lt;div class=&amp;quot;flexbox&amp;quot;&amp;amp;gt;
        &amp;amp;lt;h2&amp;amp;gt;Flexbox&amp;amp;lt;/h2&amp;amp;gt;
        &amp;amp;lt;ul&amp;amp;gt;
          &amp;amp;lt;li&amp;amp;gt;boite 1&amp;amp;lt;/li&amp;amp;gt;
          &amp;amp;lt;li&amp;amp;gt;boite 2&amp;amp;lt;/li&amp;amp;gt;
          &amp;amp;lt;li&amp;amp;gt;boite 3&amp;amp;lt;/li&amp;amp;gt;
        &amp;amp;lt;/ul&amp;amp;gt;
      &amp;amp;lt;/div&amp;amp;gt;

      &amp;amp;lt;div class=&amp;quot;grid&amp;quot;&amp;amp;gt;
        &amp;amp;lt;h2&amp;amp;gt;Grid&amp;amp;lt;/h2&amp;amp;gt;
        &amp;amp;lt;div class=&amp;quot;grid-container&amp;quot;&amp;amp;gt;
          &amp;amp;lt;img src=&amp;quot;./assets/img/css-logo.png&amp;quot; alt=&amp;quot;logo css&amp;quot; /&amp;amp;gt;

          &amp;amp;lt;form action=&amp;quot;&amp;quot;&amp;amp;gt;
            &amp;amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;firstname&amp;quot; placeholder=&amp;quot;Prénom&amp;quot; /&amp;amp;gt;
            &amp;amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;surname&amp;quot; placeholder=&amp;quot;Nom&amp;quot; /&amp;amp;gt;
            &amp;amp;lt;textarea
              cols=&amp;quot;30&amp;quot;
              rows=&amp;quot;10&amp;quot;
              placeholder=&amp;quot;Ici votre message&amp;quot;
            &amp;amp;gt;&amp;amp;lt;/textarea&amp;amp;gt;
            &amp;amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Valider&amp;quot; id=&amp;quot;btn-submit&amp;quot; /&amp;amp;gt;
          &amp;amp;lt;/form&amp;amp;gt;
        &amp;amp;lt;/div&amp;amp;gt;
      &amp;amp;lt;/div&amp;amp;gt;

      &amp;amp;lt;div class=&amp;quot;absolute&amp;quot;&amp;amp;gt;
        &amp;amp;lt;h2&amp;amp;gt;Absolute&amp;amp;lt;/h2&amp;amp;gt;
        &amp;amp;lt;span id=&amp;quot;circle1&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;
        &amp;amp;lt;span id=&amp;quot;circle2&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;
      &amp;amp;lt;/div&amp;amp;gt;
    &amp;amp;lt;/main&amp;amp;gt;
  &amp;amp;lt;/body&amp;amp;gt;
&amp;amp;lt;/html&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;स्टाइल.css फ़ाइल को HTML पृष्ठ से जोड़ें:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;/head&amp;amp;gt;
  &amp;amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;style.css&amp;quot; /&amp;amp;gt;
&amp;amp;lt;/head&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_शुरुआत&amp;quot;&amp;gt;[toc_शुरुआत]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;début_texts&amp;quot;&amp;gt;Les textes&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-css&amp;quot; data-lang=&amp;quot;css&amp;quot;&amp;gt;/* import remote de font sur l&amp;#39;ensemble de la feuille*/
@import url(&amp;quot;https://fonts.googleapis.com/css2?family=Oswald:wght@500&amp;amp;amp;display=swap&amp;quot;);

/* import local de font */
@font-face {
  font-family: &amp;quot;DMSerif&amp;quot;;
  src: url(./assets/fonts/DMSerifDisplay-Regular.ttf);
}

/*
body est le parent de toutes les balises,
qu&amp;#39;il contient, donc je le déclare avant,
pour la logique de précédence de parent
*/
body {
  /* si DMSerif n&amp;#39;est pas trouvé alors il se rabat sur Verdana*/
  font-family: &amp;quot;DMSerif&amp;quot;, Verdana;
}

/* va styliser toutes les balises h1,
celles de body sont surchargés,
par la déclaration présente */
h1 {
  text-transform: uppercase;
  /* espacement entre les lettres en pixel*/
  letter-spacing: 3px;
  /* alignement du texte*/
  text-align: center;
  /* Les tailles de polices doivent être en REM  (rem = root em).
  Le REM se base pas sur l&amp;#39;élément parent pour obtenir sa taille mais sur l&amp;#39;élément racine. Ainsi 1rem prendra sa valeur de la font-size de votre document (body ou html).*/
  font-size: 2.5rem;
  /* ombrage du texte */
  text-shadow:
  3px /* offset-x */
  3px /* offset-y */
  8px /* blur-radius */
  #00000042/* color */;
  /* couleur du texte */
  color: #ab0ef4;
  /*attibuer les polices(font): liste, ordonnée par priorité, de polices à utiliser pour mettre en forme le texte de l&amp;#39;élément ciblé.*/
  font-family: &amp;quot;Oswald&amp;quot;, sans-serif;
  /* surligner le text*/
  text-decoration: underline;
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_début&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;शुरुआत CSS&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;début_background&amp;quot;&amp;gt;पृष्ठभूमि&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-css&amp;quot; data-lang=&amp;quot;css&amp;quot;&amp;gt;@import url(&amp;quot;https://fonts.googleapis.com/css2?family=Oswald:wght@500&amp;amp;amp;display=swap&amp;quot;);

@font-face {
  font-family: &amp;quot;DMSerif&amp;quot;;
  src: url(./assets/fonts/DMSerifDisplay-Regular.ttf);
}

body {
  font-family: &amp;quot;DMSerif&amp;quot;, Verdana;
  /* image comme background*/
  background: url(./assets/img/bg.jpg) center/cover;
  /* 100VH = 100% de la taille de l&amp;#39;écran (viewport height)
  min afin de ne pas bloquer la possibilité d&amp;#39;avoir un plus grand */
  min-height: 100vh;
}

h1 {
  text-transform: uppercase;
  letter-spacing: 3px;
  text-align: center;
  font-size: 2.5rem;
  text-shadow: 3px 3px 8px #00000042;
  color: #ab0ef4;
  font-family: &amp;quot;Oswald&amp;quot;, sans-serif;
  text-decoration: underline;
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_début&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;शुरुआत CSS&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;début_boxes&amp;quot;&amp;gt;बॉक्सेस (boxes)&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-css&amp;quot; data-lang=&amp;quot;css&amp;quot;&amp;gt;@import url(&amp;quot;https://fonts.googleapis.com/css2?family=Oswald:wght@500&amp;amp;amp;display=swap&amp;quot;);

@font-face {
  font-family: &amp;quot;DMSerif&amp;quot;;
  src: url(./assets/fonts/DMSerifDisplay-Regular.ttf);
}

/* *: létoile donne du style a tous les éléments.
Ensuite remettre un à un les parametres par defaut afin d&amp;#39;eviter les stylisation inattendu.*/
* {
  /* surcharge de base tous les elements à padding 0*/
  margin: 0;
  /* surcharge de base tous les elements à padding 0*/
  padding: 0;
}

body {
  font-family: &amp;quot;DMSerif&amp;quot;, Verdana;
  /* image comme background*/
  background: url(./assets/img/bg.jpg) center/cover;
  min-height: 100vh;
}

h1 {
  text-transform: uppercase;
  letter-spacing: 3px;
  text-align: center;
  font-size: 2.5rem;
  text-shadow: 3px 3px 8px #00000042;
  color: #ab0ef4;
  font-family: &amp;quot;Oswald&amp;quot;, sans-serif;
  text-decoration: underline;
}

main {
  background: rgba(245, 245, 245, 0.9);
  min-height: 500px;
  /* quelque soit la taille de l&amp;#39;écran,
  la boite fait toujours 90% de la taille de la page,
  les 10% restant sont une marge à droite,
  pour avoir 5% de chaque coté on ajoute une margin, tel que [0, auto]*/
  width: 90%;
  /* haut bas prend 0, et  gauche droite prend auto(center cad meme de chaque cotés)*/
  margin: 0 auto;
  /* on ajoute des bords a notre boite*/
  border: 2px solid rgb(0, 140, 255);
  /* on arrondis les coins de la boite*/
  border-radius: 20px 20px 0 0;
  /* ombrage sur la boite*/
  box-shadow: 0px 0px 20px 4px #81cfc6;
  /* marge interrieure de la boite sur tous les cotés*/
  padding: 15px;
}

h2 {
  /* afin de recuprer le comportement par defaut qui a ete surchargé par l&amp;#39;operateur étoile*/
  margin: 0;
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;!DOCTYPE html&amp;amp;gt;
&amp;amp;lt;html lang=&amp;quot;fr&amp;quot;&amp;amp;gt;
  &amp;amp;lt;head&amp;amp;gt;
    &amp;amp;lt;meta charset=&amp;quot;UTF-8&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;meta http-equiv=&amp;quot;X-UA-Compatible&amp;quot; content=&amp;quot;IE=edge&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;title&amp;amp;gt;Cours CSS&amp;amp;lt;/title&amp;amp;gt;

    &amp;amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;style.css&amp;quot; /&amp;amp;gt;
  &amp;amp;lt;/head&amp;amp;gt;
  &amp;amp;lt;body&amp;amp;gt;
    &amp;amp;lt;header&amp;amp;gt;
      &amp;amp;lt;h1&amp;amp;gt;Les bases de CSS&amp;amp;lt;/h1&amp;amp;gt;
    &amp;amp;lt;/header&amp;amp;gt;

    &amp;amp;lt;main&amp;amp;gt;
      &amp;amp;lt;div class=&amp;quot;flexbox&amp;quot;&amp;amp;gt;
        &amp;amp;lt;h2&amp;amp;gt;Flexbox&amp;amp;lt;/h2&amp;amp;gt;
        &amp;amp;lt;ul&amp;amp;gt;
          &amp;amp;lt;li&amp;amp;gt;boite 1&amp;amp;lt;/li&amp;amp;gt;
          &amp;amp;lt;li&amp;amp;gt;boite 2&amp;amp;lt;/li&amp;amp;gt;
          &amp;amp;lt;li&amp;amp;gt;boite 3&amp;amp;lt;/li&amp;amp;gt;
        &amp;amp;lt;/ul&amp;amp;gt;
      &amp;amp;lt;/div&amp;amp;gt;
    &amp;amp;lt;/main&amp;amp;gt;
  &amp;amp;lt;/body&amp;amp;gt;
&amp;amp;lt;/html&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_शुरुआत&amp;quot;&amp;gt;[toc_शुरुआत]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;शुरुआत_flexbox&amp;quot;&amp;gt;Flexbox&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-css&amp;quot; data-lang=&amp;quot;css&amp;quot;&amp;gt;@import url(&amp;quot;https://fonts.googleapis.com/css2?family=Oswald:wght@500&amp;amp;amp;display=swap&amp;quot;);

@font-face {
  font-family: &amp;quot;DMSerif&amp;quot;;
  src: url(./assets/fonts/DMSerifDisplay-Regular.ttf);
}

body {
  font-family: &amp;quot;DMSerif&amp;quot;, Verdana;
  background: url(./assets/img/bg.jpg) center/cover;
  min-height: 100vh;
}

h1 {
  text-transform: uppercase;
  letter-spacing: 3px;
  text-align: center;
  font-size: 2.5rem;
  text-shadow: 3px 3px 8px #00000042;
  color: #ab0ef4;
  font-family: &amp;quot;Oswald&amp;quot;, sans-serif;
  text-decoration: underline;
}

main {
  background: rgba(245, 245, 245, 0.9);
  min-height: 500px;
  width: 90%;
  margin: 0 auto;
  border: 2px solid rgb(0, 140, 255);
  border-radius: 20px 20px 0 0;
  box-shadow: 0px 0px 20px 4px #81cfc6;
  padding: 15px;
}

h2 {
  margin: 0;
}

/* le point permet d&amp;#39;acceder à la classe d&amp;#39;un composant*/
.flexbox {
  border: 2px solid skyblue;
  border-radius: 10px;
  padding: 10px;
  margin-top: 20px;
  min-height: 150px;
}

/* FLEXBOX */
/* Sert à répartir équitablement des éléments sur la page */
.flexbox ul {
  padding: 0;
  /* aligne les éléments enfants de ul(les li)*/
  display: flex;
  /* reparti convenablement(équitablement les li sur la page) */
  justify-content: space-around;
}
/* ce style concerne les li de la classe,
flexbox des balises qui y font referencent*/
.flexbox li {
  /* suprime les boules des éléments de la list li*/
  list-style: none;
  height: 160px;
  width: 160px;
  margin: 10px;
  background: turquoise;
  /* Centrer un unique élément verticalement et horizontalement */
  display: flex;
  justify-content: center;
  align-items: center;
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;!DOCTYPE html&amp;amp;gt;
&amp;amp;lt;html lang=&amp;quot;fr&amp;quot;&amp;amp;gt;
  &amp;amp;lt;head&amp;amp;gt;
    &amp;amp;lt;meta charset=&amp;quot;UTF-8&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;meta http-equiv=&amp;quot;X-UA-Compatible&amp;quot; content=&amp;quot;IE=edge&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;title&amp;amp;gt;Cours CSS&amp;amp;lt;/title&amp;amp;gt;

    &amp;amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;style.css&amp;quot; /&amp;amp;gt;
  &amp;amp;lt;/head&amp;amp;gt;
  &amp;amp;lt;body&amp;amp;gt;
    &amp;amp;lt;header&amp;amp;gt;
      &amp;amp;lt;h1&amp;amp;gt;Les bases de CSS&amp;amp;lt;/h1&amp;amp;gt;
    &amp;amp;lt;/header&amp;amp;gt;

    &amp;amp;lt;main&amp;amp;gt;
      &amp;amp;lt;div class=&amp;quot;flexbox&amp;quot;&amp;amp;gt;
        &amp;amp;lt;h2&amp;amp;gt;Flexbox&amp;amp;lt;/h2&amp;amp;gt;
        &amp;amp;lt;ul&amp;amp;gt;
          &amp;amp;lt;li&amp;amp;gt;boite 1&amp;amp;lt;/li&amp;amp;gt;
          &amp;amp;lt;li&amp;amp;gt;boite 2&amp;amp;lt;/li&amp;amp;gt;
          &amp;amp;lt;li&amp;amp;gt;boite 3&amp;amp;lt;/li&amp;amp;gt;
        &amp;amp;lt;/ul&amp;amp;gt;
      &amp;amp;lt;/div&amp;amp;gt;
    &amp;amp;lt;/main&amp;amp;gt;
  &amp;amp;lt;/body&amp;amp;gt;
&amp;amp;lt;/html&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_शुरुआत&amp;quot;&amp;gt;[toc_शुरुआत]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;शुरू_ग्रिड&amp;quot;&amp;gt;ग्रिड&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फ़्लेक्सबॉक्स की तुलना में थोड़ा अधिक जटिल तरीके से तत्वों को वितरित करने के लिए, ग्रिड सिस्टम आदि के साथ।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-css&amp;quot; data-lang=&amp;quot;css&amp;quot;&amp;gt;@import url(&amp;quot;https://fonts.googleapis.com/css2?family=Oswald:wght@500&amp;amp;amp;display=swap&amp;quot;);

@font-face {
  font-family: &amp;quot;DMSerif&amp;quot;;
  src: url(./assets/fonts/DMSerifDisplay-Regular.ttf);
}

body {
  font-family: &amp;quot;DMSerif&amp;quot;, Verdana;
  background: url(./assets/img/bg.jpg) center/cover;
  min-height: 100vh;
}

h1 {
  text-transform: uppercase;
  letter-spacing: 3px;
  text-align: center;
  font-size: 2.5rem;
  text-shadow: 3px 3px 8px #00000042;
  color: #ab0ef4;
  font-family: &amp;quot;Oswald&amp;quot;, sans-serif;
  text-decoration: underline;
}

main {
  background: rgba(245, 245, 245, 0.9);
  min-height: 500px;
  width: 90%;
  margin: 0 auto;
  border: 2px solid rgb(0, 140, 255);
  border-radius: 20px 20px 0 0;
  box-shadow: 0px 0px 20px 4px #81cfc6;
  padding: 15px;
}

h2 {
  margin: 0;
}

.flexbox,
.grid {
  border: 2px solid skyblue;
  border-radius: 10px;
  padding: 10px;
  margin-top: 20px;
  min-height: 150px;
}

.flexbox ul {
  padding: 0;
  display: flex;
  justify-content: space-around;
}

.flexbox li {
  list-style: none;
  height: 160px;
  width: 160px;
  margin: 10px;
  background: turquoise;
  display: flex;
  justify-content: center;
  align-items: center;
}

/* GRID */
.grid-container {
  display: grid;
  /* séparatuion de la grille en deux(à ses deux enfants),
  avec à gauche 30% pour l&amp;#39;image
  et à droite 70% pour le formulaire*/
  grid-template-columns: 30% 70%;
}

/* sizing de l&amp;#39;image css-logo
contenu dans la classe grid
qui est dans le parent grid-container*/
.grid img {
  /* l&amp;#39;image remplt 80% de part de grille*/
  width: 80%;
  margin: 20px auto;
  display: block;
}

form {
  display: grid;
  /* deux colonnes de chacune 1 fraction*/
  grid-template-columns: 1fr 1fr;
  /* trois rangés de chacune 1 fraction*/
    grid-template-rows: 1fr 1fr 1fr;
    /* structuration sous forme de template
    de notre repartition des composants
    enfants de la forme*/
  grid-template-areas:
    &amp;quot;i1 i2&amp;quot;/* i1: input1, i2:input2*/
    &amp;quot;ta ta&amp;quot;/*ta: text area */
    &amp;quot;vi bt&amp;quot;/*vi:, bt: bouton */;
}

/* on donne du style sur deux éléments
en meme temps en les listant
avant les parentheses*/
input,
textarea {
  margin: 5px;
  border: 1px solid darkblue;
  padding: 10px;
  font-size: 1.1rem;
  font-family: &amp;quot;DMSerif&amp;quot;;
  border-radius: 5px;
}

/* donner du style uniquement la textearea*/
textarea {
  /* renseigner le nommage pour le grid template area*/
  grid-area: ta;
  height: 40px;
  /* empeche le cassage du style de la page
  en empechant le resizing de la textarea
  du formulaire*/
  resize: none;
}
/* pour pointer un id d&amp;#39;élément html
on utilise la notation préfixe # */
#btn-submit {
  /* renseigner le nommage*/
  grid-area: bt;
  /* change le le symbole de curseur
  souris quand il survole sur le bouton*/
  cursor: pointer;
  background: cyan;
  transition: 0.2s;
}

/* au survole(hover) de la souris
le bouton change de comportement*/
#btn-submit:hover {
  background: darkblue;
  /* couleur de text du bouton devient blanc*/
  color: white;
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;!DOCTYPE html&amp;amp;gt;
&amp;amp;lt;html lang=&amp;quot;fr&amp;quot;&amp;amp;gt;

&amp;amp;lt;head&amp;amp;gt;
    &amp;amp;lt;meta charset=&amp;quot;UTF-8&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;meta http-equiv=&amp;quot;X-UA-Compatible&amp;quot; content=&amp;quot;IE=edge&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;title&amp;amp;gt;Cours CSS&amp;amp;lt;/title&amp;amp;gt;

    &amp;amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;style.css&amp;quot; /&amp;amp;gt;
&amp;amp;lt;/head&amp;amp;gt;

&amp;amp;lt;body&amp;amp;gt;
    &amp;amp;lt;header&amp;amp;gt;
        &amp;amp;lt;h1&amp;amp;gt;Les bases de CSS&amp;amp;lt;/h1&amp;amp;gt;
    &amp;amp;lt;/header&amp;amp;gt;

    &amp;amp;lt;main&amp;amp;gt;
        &amp;amp;lt;div class=&amp;quot;flexbox&amp;quot;&amp;amp;gt;
            &amp;amp;lt;h2&amp;amp;gt;Flexbox&amp;amp;lt;/h2&amp;amp;gt;
            &amp;amp;lt;ul&amp;amp;gt;
                &amp;amp;lt;li&amp;amp;gt;boite 1&amp;amp;lt;/li&amp;amp;gt;
                &amp;amp;lt;li&amp;amp;gt;boite 2&amp;amp;lt;/li&amp;amp;gt;
                &amp;amp;lt;li&amp;amp;gt;boite 3&amp;amp;lt;/li&amp;amp;gt;
            &amp;amp;lt;/ul&amp;amp;gt;
        &amp;amp;lt;/div&amp;amp;gt;

        &amp;amp;lt;div class=&amp;quot;grid&amp;quot;&amp;amp;gt;
            &amp;amp;lt;h2&amp;amp;gt;Grid&amp;amp;lt;/h2&amp;amp;gt;
            &amp;amp;lt;div class=&amp;quot;grid-container&amp;quot;&amp;amp;gt;
                &amp;amp;lt;img src=&amp;quot;./assets/img/css-logo.png&amp;quot; alt=&amp;quot;logo css&amp;quot; /&amp;amp;gt;

                &amp;amp;lt;form action=&amp;quot;&amp;quot;&amp;amp;gt;
                    &amp;amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;firstname&amp;quot; placeholder=&amp;quot;Prénom&amp;quot; /&amp;amp;gt;
                    &amp;amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;surname&amp;quot; placeholder=&amp;quot;Nom&amp;quot; /&amp;amp;gt;
                    &amp;amp;lt;textarea cols=&amp;quot;30&amp;quot; rows=&amp;quot;10&amp;quot; placeholder=&amp;quot;Ici votre message&amp;quot;&amp;amp;gt;&amp;amp;lt;/textarea&amp;amp;gt;
                    &amp;amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Valider&amp;quot; id=&amp;quot;btn-submit&amp;quot; /&amp;amp;gt;
                &amp;amp;lt;/form&amp;amp;gt;
            &amp;amp;lt;/div&amp;amp;gt;
        &amp;amp;lt;/div&amp;amp;gt;
    &amp;amp;lt;/main&amp;amp;gt;
&amp;amp;lt;/body&amp;amp;gt;

&amp;amp;lt;/html&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_शुरुआत&amp;quot;&amp;gt;[toc_शुरुआत]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_ग्रेडल_एकीकरण&amp;quot;&amp;gt;&amp;lt;mark&amp;gt;#&amp;lt;/mark&amp;gt; ग्रेडल एकीकरण&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;JBake को JBake Gradle प्लगइन का उपयोग करके या JBake CLI को सीधे बुलाकर Gradle बिल्ड में एकीकृत किया जा सकता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;----
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
}

[source,css]
----
@import url(&amp;quot;https://fonts.googleapis.com/css2?family=Oswald:wght@500&amp;amp;amp;display=swap&amp;quot;);

@font-face {
  font-family: &amp;quot;DMSerif&amp;quot;;
  src: url(./assets/fonts/DMSerifDisplay-Regular.ttf);
}

body {
  font-family: &amp;quot;DMSerif&amp;quot;, Verdana;
  background: url(./assets/img/bg.jpg) center/cover;
  min-height: 100vh;
}

h1 {
  text-transform: uppercase;
  letter-spacing: 3px;
  text-align: center;
  font-size: 2.5rem;
  text-shadow: 3px 3px 8px #00000042;
  color: #ab0ef4;
  font-family: &amp;quot;Oswald&amp;quot;, sans-serif;
  text-decoration: underline;
}

main {
  background: rgba(245, 245, 245, 0.9);
  min-height: 500px;
  width: 90%;
  margin: 0 auto;
  border: 2px solid rgb(0, 140, 255);
  border-radius: 20px 20px 0 0;
  box-shadow: 0px 0px 20px 4px #81cfc6;
  padding: 15px;
}

h2 {
  margin: 0;
}

.flexbox,
.grid,
.absolute {
  border: 2px solid skyblue;
  border-radius: 10px;
  padding: 10px;
  margin-top: 20px;
  min-height: 150px;
}

.flexbox ul {
  padding: 0;
  display: flex;
  justify-content: space-around;
}

.flexbox li {
  list-style: none;
  height: 160px;
  width: 160px;
  margin: 10px;
  background: turquoise;
  display: flex;
  justify-content: center;
  align-items: center;
}

.grid-container {
  display: grid;
  grid-template-columns: 30% 70%;
}

.grid img {
  width: 80%;
  margin: 20px auto;
  display: block;
}

form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  grid-template-areas: &amp;quot;i1 i2&amp;quot; &amp;quot;ta ta&amp;quot; &amp;quot;vi bt&amp;quot;;
}

input,
textarea {
  margin: 5px;
  border: 1px solid darkblue;
  padding: 10px;
  font-size: 1.1rem;
  font-family: &amp;quot;DMSerif&amp;quot;;
  border-radius: 5px;
}

textarea {
  grid-area: ta;
  height: 40px;
  resize: none;
}

#btn-submit {
  grid-area: bt;
  cursor: pointer;
  background: cyan;
  transition: 0.2s;
}

#btn-submit:hover {
  background: darkblue;
  color: white;
}

/* ABSOLUTE  */
/* Sans élément en Relative, de base, l&amp;#39;élément en absolute l&amp;#39;est par rapport au Body  */
/* Il faut mettre une position relative au parent pour contraindre l&amp;#39;élément en absolute dans ses frontières  */
.absolute {
  /* position relative par rapport à son parent,
  donc contenu dans les frontieres de son parents*/
  position: relative;
}


#circle1 {
  height: 80px;
  width: 80px;
  background: skyblue;
  position: absolute;
  border-radius: 150px;
  top: -20px;
  right: -20px;
}

#circle2 {
  height: 40px;
  width: 40px;
  border-radius: 150px;
  background: teal;
  position: absolute;
  left: 50%;
  transform:
  /*traslate de 50% de la taille du cercle,
  pour etre centré par rapport au centre du cercle,
  plutot que sur son bord gauche par défaut.*/
  translateX(-50%);
  top: 100px;
}
----

[source, html]
----
&amp;amp;lt;!DOCTYPE html&amp;amp;gt;
&amp;amp;lt;html lang=&amp;quot;fr&amp;quot;&amp;amp;gt;

&amp;amp;lt;head&amp;amp;gt;
    &amp;amp;lt;meta charset=&amp;quot;UTF-8&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;meta http-equiv=&amp;quot;X-UA-Compatible&amp;quot; content=&amp;quot;IE=edge&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;title&amp;amp;gt;Cours CSS&amp;amp;lt;/title&amp;amp;gt;

    &amp;amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;style.css&amp;quot; /&amp;amp;gt;
&amp;amp;lt;/head&amp;amp;gt;

&amp;amp;lt;body&amp;amp;gt;
    &amp;amp;lt;header&amp;amp;gt;
        &amp;amp;lt;h1&amp;amp;gt;Les bases de CSS&amp;amp;lt;/h1&amp;amp;gt;
    &amp;amp;lt;/header&amp;amp;gt;

    &amp;amp;lt;main&amp;amp;gt;
        &amp;amp;lt;div class=&amp;quot;flexbox&amp;quot;&amp;amp;gt;
            &amp;amp;lt;h2&amp;amp;gt;Flexbox&amp;amp;lt;/h2&amp;amp;gt;
            &amp;amp;lt;ul&amp;amp;gt;
                &amp;amp;lt;li&amp;amp;gt;boite 1&amp;amp;lt;/li&amp;amp;gt;
                &amp;amp;lt;li&amp;amp;gt;boite 2&amp;amp;lt;/li&amp;amp;gt;
                &amp;amp;lt;li&amp;amp;gt;boite 3&amp;amp;lt;/li&amp;amp;gt;
            &amp;amp;lt;/ul&amp;amp;gt;
        &amp;amp;lt;/div&amp;amp;gt;

        &amp;amp;lt;div class=&amp;quot;grid&amp;quot;&amp;amp;gt;
            &amp;amp;lt;h2&amp;amp;gt;Grid&amp;amp;lt;/h2&amp;amp;gt;
            &amp;amp;lt;div class=&amp;quot;grid-container&amp;quot;&amp;amp;gt;
                &amp;amp;lt;img src=&amp;quot;./assets/img/css-logo.png&amp;quot; alt=&amp;quot;logo css&amp;quot; /&amp;amp;gt;

                &amp;amp;lt;form action=&amp;quot;&amp;quot;&amp;amp;gt;
                    &amp;amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;firstname&amp;quot; placeholder=&amp;quot;Prénom&amp;quot; /&amp;amp;gt;
                    &amp;amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;surname&amp;quot; placeholder=&amp;quot;Nom&amp;quot; /&amp;amp;gt;
                    &amp;amp;lt;textarea cols=&amp;quot;30&amp;quot; rows=&amp;quot;10&amp;quot; placeholder=&amp;quot;Ici votre message&amp;quot;&amp;amp;gt;&amp;amp;lt;/textarea&amp;amp;gt;
                    &amp;amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Valider&amp;quot; id=&amp;quot;btn-submit&amp;quot; /&amp;amp;gt;
                &amp;amp;lt;/form&amp;amp;gt;
            &amp;amp;lt;/div&amp;amp;gt;
        &amp;amp;lt;/div&amp;amp;gt;

        &amp;amp;lt;div class=&amp;quot;absolute&amp;quot;&amp;amp;gt;
            &amp;amp;lt;h2&amp;amp;gt;Absolute&amp;amp;lt;/h2&amp;amp;gt;
            &amp;amp;lt;span id=&amp;quot;circle1&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;
            &amp;amp;lt;span id=&amp;quot;circle2&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;
        &amp;amp;lt;/div&amp;amp;gt;
    &amp;amp;lt;/main&amp;amp;gt;
&amp;amp;lt;/body&amp;amp;gt;

&amp;amp;lt;/html&amp;amp;gt;
----

&amp;amp;lt;&amp;amp;lt;toc_शुरुआत&amp;amp;gt;&amp;amp;gt;

== रिस्पॉन्सिव [[début_responsive]]

[source,css]
----
@import url(&amp;quot;https://fonts.googleapis.com/css2?family=Oswald:wght@500&amp;amp;amp;display=swap&amp;quot;);

@font-face {
  font-family: &amp;quot;DMSerif&amp;quot;;
  src: url(./assets/fonts/DMSerifDisplay-Regular.ttf);
}

body {
  font-family: &amp;quot;DMSerif&amp;quot;, Verdana;
  background: url(./assets/img/bg.jpg) center/cover;
  min-height: 100vh;
}

h1 {
  text-transform: uppercase;
  letter-spacing: 3px;
  text-align: center;
  /* pour etre plus responsive on peut passer la taille en vw(view port width) pour qu&amp;#39;elle s&amp;#39;adapte à la taille de l&amp;#39;ecran*/
  font-size: 2.5rem;
  text-shadow: 3px 3px 8px #00000042;
  color: #ab0ef4;
  font-family: &amp;quot;Oswald&amp;quot;, sans-serif;
  text-decoration: underline;
}

main {
  background: rgba(245, 245, 245, 0.9);
  min-height: 500px;
  width: 90%;
  margin: 0 auto;
  border: 2px solid rgb(0, 140, 255);
  border-radius: 20px 20px 0 0;
  box-shadow: 0px 0px 20px 4px #81cfc6;
  padding: 15px;
}

h2 {
  margin: 0;
}

.flexbox,
.grid,
.absolute {
  border: 2px solid skyblue;
  border-radius: 10px;
  padding: 10px;
  margin-top: 20px;
  min-height: 150px;
}

.flexbox ul {
  padding: 0;
  display: flex;
  justify-content: space-around;
}

.flexbox li {
  list-style: none;
  height: 160px;
  width: 160px;
  margin: 10px;
  background: turquoise;
  display: flex;
  justify-content: center;
  align-items: center;
}

.grid-container {
  display: grid;
  grid-template-columns: 30% 70%;
}

.grid img {
  width: 80%;
  margin: 20px auto;
  /* permet en media query de la centrer en petit écran*/
  display: block;
}

form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  grid-template-areas: &amp;quot;i1 i2&amp;quot; &amp;quot;ta ta&amp;quot; &amp;quot;vi bt&amp;quot;;
}

input,
textarea {
  margin: 5px;
  border: 1px solid darkblue;
  padding: 10px;
  font-size: 1.1rem;
  font-family: &amp;quot;DMSerif&amp;quot;;
  border-radius: 5px;
}

textarea {
  grid-area: ta;
  height: 40px;
  resize: none;
}

#btn-submit {
  grid-area: bt;
  cursor: pointer;
  background: cyan;
  transition: 0.2s;
}

#btn-submit:hover {
  background: darkblue;
  color: white;
}

.absolute {
  position: relative;
}


#circle1 {
  height: 80px;
  width: 80px;
  background: skyblue;
  position: absolute;
  border-radius: 150px;
  top: -20px;
  right: -20px;
}

#circle2 {
  height: 40px;
  width: 40px;
  border-radius: 150px;
  background: teal;
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: 100px;
}

/* RESPONSIVE:
a partir des tailles d&amp;#39;ecran permet de surcharger les reglages definis plus haut
*/
@media screen and (max-width: 900px) {
  .grid-container {
    display: block;
  }
  .grid-container img {
    width: 40%;
  }
}

@media screen and (max-width: 610px) {
  .flexbox ul {
    flex-direction: column;
    align-items: center;
  }

  form {
    grid-template-columns: 1fr;
    grid-template-rows: 1fr;
    grid-template-areas:
      &amp;quot;i1&amp;quot;
      &amp;quot;i2&amp;quot;
      &amp;quot;ta&amp;quot;
      &amp;quot;bt&amp;quot;;
  }
  input,
  textarea {
    font-size: 0.8rem;
  }
}
----

[source, html]
----
&amp;amp;lt;!DOCTYPE html&amp;amp;gt;
&amp;amp;lt;html lang=&amp;quot;fr&amp;quot;&amp;amp;gt;

&amp;amp;lt;head&amp;amp;gt;
    &amp;amp;lt;meta charset=&amp;quot;UTF-8&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;meta http-equiv=&amp;quot;X-UA-Compatible&amp;quot; content=&amp;quot;IE=edge&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;title&amp;amp;gt;Cours CSS&amp;amp;lt;/title&amp;amp;gt;

    &amp;amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;style.css&amp;quot; /&amp;amp;gt;
&amp;amp;lt;/head&amp;amp;gt;

&amp;amp;lt;body&amp;amp;gt;
    &amp;amp;lt;header&amp;amp;gt;
        &amp;amp;lt;h1&amp;amp;gt;Les bases de CSS&amp;amp;lt;/h1&amp;amp;gt;
    &amp;amp;lt;/header&amp;amp;gt;

    &amp;amp;lt;main&amp;amp;gt;
        &amp;amp;lt;div class=&amp;quot;flexbox&amp;quot;&amp;amp;gt;
            &amp;amp;lt;h2&amp;amp;gt;Flexbox&amp;amp;lt;/h2&amp;amp;gt;
            &amp;amp;lt;ul&amp;amp;gt;
                &amp;amp;lt;li&amp;amp;gt;boite 1&amp;amp;lt;/li&amp;amp;gt;
                &amp;amp;lt;li&amp;amp;gt;boite 2&amp;amp;lt;/li&amp;amp;gt;
                &amp;amp;lt;li&amp;amp;gt;boite 3&amp;amp;lt;/li&amp;amp;gt;
            &amp;amp;lt;/ul&amp;amp;gt;
        &amp;amp;lt;/div&amp;amp;gt;

        &amp;amp;lt;div class=&amp;quot;grid&amp;quot;&amp;amp;gt;
            &amp;amp;lt;h2&amp;amp;gt;Grid&amp;amp;lt;/h2&amp;amp;gt;
            &amp;amp;lt;div class=&amp;quot;grid-container&amp;quot;&amp;amp;gt;
                &amp;amp;lt;img src=&amp;quot;./assets/img/css-logo.png&amp;quot; alt=&amp;quot;logo css&amp;quot; /&amp;amp;gt;

                &amp;amp;lt;form action=&amp;quot;&amp;quot;&amp;amp;gt;
                    &amp;amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;firstname&amp;quot; placeholder=&amp;quot;Prénom&amp;quot; /&amp;amp;gt;
                    &amp;amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;surname&amp;quot; placeholder=&amp;quot;Nom&amp;quot; /&amp;amp;gt;
                    &amp;amp;lt;textarea cols=&amp;quot;30&amp;quot; rows=&amp;quot;10&amp;quot; placeholder=&amp;quot;Ici votre message&amp;quot;&amp;amp;gt;&amp;amp;lt;/textarea&amp;amp;gt;
                    &amp;amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Valider&amp;quot; id=&amp;quot;btn-submit&amp;quot; /&amp;amp;gt;
                &amp;amp;lt;/form&amp;amp;gt;
            &amp;amp;lt;/div&amp;amp;gt;
        &amp;amp;lt;/div&amp;amp;gt;

        &amp;amp;lt;div class=&amp;quot;absolute&amp;quot;&amp;amp;gt;
            &amp;amp;lt;h2&amp;amp;gt;Absolute&amp;amp;lt;/h2&amp;amp;gt;
            &amp;amp;lt;span id=&amp;quot;circle1&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;
            &amp;amp;lt;span id=&amp;quot;circle2&amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;
        &amp;amp;lt;/div&amp;amp;gt;
    &amp;amp;lt;/main&amp;amp;gt;
&amp;amp;lt;/body&amp;amp;gt;

&amp;amp;lt;/html&amp;amp;gt;
----

toc_शुरुआत

== डिबग &amp;amp;amp; निष्कर्ष [[शुरुआत_निष्कर्ष]]

[source,css]
----
/* all elements:
supprime les comportements par défaut*/
* {
  /* les marges à zéro*/
  margin: 0;
  /* les parge internes(padding) à zéro*/
  padding: 0;
  /* tous les bords avec un cadre rouge de 2px.
  qui est ou et qui fait quoi...*/
  border: 2px solid red;
}
----

&amp;amp;lt;&amp;amp;lt;toc_शुरुआत&amp;amp;gt;&amp;amp;gt;
----&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Mémo HTML</title>
            <link >https://cheroliv.com/blog/2023/0061_memo_html_post.html</link>
            <pubDate>Sun, 13 Aug 2023 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2023/0061_memo_html_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_अच्छे_लिंक&amp;quot;&amp;gt;अच्छे लिंक&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_भंडार_और_कोड_नमूना&amp;quot;&amp;gt;भंडार और कोड नमूना&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_अच्छे_लिंक&amp;quot;&amp;gt;अच्छे लिंक&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;html&amp;lt;/div&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://htmlcheatsheet.com&amp;quot; target=&amp;quot;&amp;quot;_blank&amp;quot;&amp;gt;htmlcheatsheet.com&amp;lt;/a&amp;gt;: HTML चेटशीट&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;फ़ॉन्ट&amp;lt;/div&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://fontawesome.com&amp;quot; target=&amp;quot;&amp;quot;_blank&amp;quot;&amp;gt;fontawesome.com&amp;lt;/a&amp;gt;: आइकन पुस्तकालय&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://www.toptal.com/designers/htmlarrows/symbols/&amp;quot; target=&amp;quot;&amp;quot;_blank&amp;quot;&amp;gt;toptal.com/designers/htmlarrows/symbols&amp;lt;/a&amp;gt;: HTML में मूल आइकन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;विशेष अक्षर और एस्केप अनुक्रम&amp;lt;/div&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://www.sonarsource.com/blog/encoding-differentials-why-charset-matters/&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://www.sonarsource.com/blog/encoding-differentials-why-charset-matters/&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://stackoverflow.com/a/3614344/13104550&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://stackoverflow.com/a/3614344/13104550&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://html.spec.whatwg.org/multipage/named-characters.html&amp;quot; class=&amp;quot;bare&amp;quot;&amp;gt;https://html.spec.whatwg.org/multipage/named-characters.html&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc&amp;quot;&amp;gt;[toc]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_भंडार_और_कोड_नमूना&amp;quot;&amp;gt;भंडार और कोड नमूना&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;github संग्रहालय:https://github.com/cheroliv/html-codebase[html-codebase, window = &amp;quot;_blank]&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;नोट स्रोत:&amp;lt;br&amp;gt;
index.html&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlightjs highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html hljs&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;!DOCTYPE html&amp;amp;gt;
&amp;amp;lt;html lang=&amp;quot;fr&amp;quot;&amp;amp;gt;

&amp;amp;lt;head&amp;amp;gt;
  &amp;amp;lt;meta charset=&amp;quot;UTF-8&amp;quot; /&amp;amp;gt;
  &amp;amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0&amp;quot; /&amp;amp;gt;
  &amp;amp;lt;!-- Le titre de la page  --&amp;amp;gt;
  &amp;amp;lt;title&amp;amp;gt;Cours HTML&amp;amp;lt;/title&amp;amp;gt;
  &amp;amp;lt;!-- Icone de l&amp;#39;onglet --&amp;amp;gt;
  &amp;amp;lt;link rel=&amp;quot;shortcut icon&amp;quot; href=&amp;quot;html-logo.png&amp;quot; /&amp;amp;gt;
  &amp;amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://use.fontawesome.com/releases/v5.8.2/css/all.css&amp;quot; /&amp;amp;gt;
&amp;amp;lt;/head&amp;amp;gt;

&amp;amp;lt;body&amp;amp;gt;
  &amp;amp;lt;header&amp;amp;gt;
    &amp;amp;lt;h1&amp;amp;gt;Texte - Titre H1&amp;amp;lt;/h1&amp;amp;gt;
    &amp;amp;lt;p&amp;amp;gt;
      &amp;amp;lt;em&amp;amp;gt;em pour mettre en italique&amp;amp;lt;/em&amp;amp;gt;,
      &amp;amp;lt;strong&amp;amp;gt;strong pour mettre en gras&amp;amp;lt;/strong&amp;amp;gt;
      &amp;amp;lt;span&amp;amp;gt;L&amp;#39;élement en span ne revient pas à la ligne&amp;amp;lt;/span&amp;amp;gt;.
    &amp;amp;lt;/p&amp;amp;gt;
    &amp;amp;lt;p&amp;amp;gt;
      Lorem ipsum dolor sit amet consectetur adipisicing elit. Exercitationem
      cumque ratione veniam officiis nulla a debitis at facilis sed
      dignissimos.
    &amp;amp;lt;/p&amp;amp;gt;
  &amp;amp;lt;/header&amp;amp;gt;

  &amp;amp;lt;section&amp;amp;gt;
    &amp;amp;lt;div&amp;amp;gt;
      &amp;amp;lt;h2&amp;amp;gt;Photo - Titre H2&amp;amp;lt;/h2&amp;amp;gt;
      &amp;amp;lt;img src=&amp;quot;./img-1.jpg&amp;quot; alt=&amp;quot;image-arbre&amp;quot; height=&amp;quot;200&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;/div&amp;amp;gt;

    &amp;amp;lt;div&amp;amp;gt;
      &amp;amp;lt;h3&amp;amp;gt;Liste - Titre H3&amp;amp;lt;/h3&amp;amp;gt;
      &amp;amp;lt;ul&amp;amp;gt;
        &amp;amp;lt;li&amp;amp;gt;UL = unordered list&amp;amp;lt;/li&amp;amp;gt;
        &amp;amp;lt;li&amp;amp;gt;UL = unordered list&amp;amp;lt;/li&amp;amp;gt;
        &amp;amp;lt;li&amp;amp;gt;UL = unordered list&amp;amp;lt;/li&amp;amp;gt;
      &amp;amp;lt;/ul&amp;amp;gt;
      &amp;amp;lt;ol&amp;amp;gt;
        &amp;amp;lt;li&amp;amp;gt;OL = ordered list&amp;amp;lt;/li&amp;amp;gt;
        &amp;amp;lt;li&amp;amp;gt;OL = ordered list&amp;amp;lt;/li&amp;amp;gt;
        &amp;amp;lt;li&amp;amp;gt;OL = ordered list&amp;amp;lt;/li&amp;amp;gt;
      &amp;amp;lt;/ol&amp;amp;gt;
    &amp;amp;lt;/div&amp;amp;gt;

    &amp;amp;lt;div&amp;amp;gt;
      &amp;amp;lt;h4&amp;amp;gt;Tableaux - Titre H4&amp;amp;lt;/h4&amp;amp;gt;
      &amp;amp;lt;table border=&amp;quot;4&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;4&amp;quot; style=&amp;quot;text-align: center&amp;quot;&amp;amp;gt;
        &amp;amp;lt;thead&amp;amp;gt;
          &amp;amp;lt;tr&amp;amp;gt;
            &amp;amp;lt;th&amp;amp;gt;Col 1&amp;amp;lt;/th&amp;amp;gt;
            &amp;amp;lt;th&amp;amp;gt;Col 2&amp;amp;lt;/th&amp;amp;gt;
            &amp;amp;lt;th&amp;amp;gt;Col 3&amp;amp;lt;/th&amp;amp;gt;
          &amp;amp;lt;/tr&amp;amp;gt;
        &amp;amp;lt;/thead&amp;amp;gt;
        &amp;amp;lt;tbody&amp;amp;gt;
          &amp;amp;lt;tr&amp;amp;gt;
            &amp;amp;lt;td rowspan=&amp;quot;2&amp;quot;&amp;amp;gt;Row 1 Cell 1&amp;amp;lt;/td&amp;amp;gt;
            &amp;amp;lt;td&amp;amp;gt;Row 1 Cell 2&amp;amp;lt;/td&amp;amp;gt;
            &amp;amp;lt;td&amp;amp;gt;Row 1 Cell 3&amp;amp;lt;/td&amp;amp;gt;
          &amp;amp;lt;/tr&amp;amp;gt;
          &amp;amp;lt;tr&amp;amp;gt;
            &amp;amp;lt;td&amp;amp;gt;Row 2 Cell 2&amp;amp;lt;/td&amp;amp;gt;
            &amp;amp;lt;td&amp;amp;gt;Row 2 Cell 3&amp;amp;lt;/td&amp;amp;gt;
          &amp;amp;lt;/tr&amp;amp;gt;
          &amp;amp;lt;tr&amp;amp;gt;
            &amp;amp;lt;td colspan=&amp;quot;3&amp;quot;&amp;amp;gt;Row 3 Cell 1&amp;amp;lt;/td&amp;amp;gt;
          &amp;amp;lt;/tr&amp;amp;gt;
        &amp;amp;lt;/tbody&amp;amp;gt;
      &amp;amp;lt;/table&amp;amp;gt;
    &amp;amp;lt;/div&amp;amp;gt;

    &amp;amp;lt;div&amp;amp;gt;
      &amp;amp;lt;h5&amp;amp;gt;&amp;amp;lt;span&amp;amp;gt;&amp;amp;amp;#9814;&amp;amp;lt;/span&amp;amp;gt; Liens - Titre H5&amp;amp;lt;/h5&amp;amp;gt;
      &amp;amp;lt;a href=&amp;quot;https://htmlcheatsheet.com/&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;amp;gt;HTML Cheatsheet&amp;amp;lt;/a&amp;amp;gt;
      &amp;amp;lt;br /&amp;amp;gt;
      &amp;amp;lt;a href=&amp;quot;https://www.toptal.com/designers/htmlarrows/symbols/&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;amp;gt;Icones natifs en HTML&amp;amp;lt;/a&amp;amp;gt;
    &amp;amp;lt;/div&amp;amp;gt;

    &amp;amp;lt;div&amp;amp;gt;
      &amp;amp;lt;h6&amp;amp;gt;&amp;amp;lt;i class=&amp;quot;fas fa-video&amp;quot;&amp;amp;gt;&amp;amp;lt;/i&amp;amp;gt; Vidéo - Titre H6&amp;amp;lt;/h6&amp;amp;gt;
      &amp;amp;lt;video src=&amp;quot;video.mp4&amp;quot; height=&amp;quot;150&amp;quot; autoplay loop muted&amp;amp;gt;&amp;amp;lt;/video&amp;amp;gt;
    &amp;amp;lt;/div&amp;amp;gt;
  &amp;amp;lt;/section&amp;amp;gt;
  &amp;amp;lt;br /&amp;amp;gt;
  &amp;amp;lt;!-- Formulaires en HTML --&amp;amp;gt;
  &amp;amp;lt;section&amp;amp;gt;
    &amp;amp;lt;h2&amp;amp;gt;Formulaire&amp;amp;lt;/h2&amp;amp;gt;
    &amp;amp;lt;form action=&amp;quot;/action.php&amp;quot; method=&amp;quot;post&amp;quot;&amp;amp;gt;
      &amp;amp;lt;label for=&amp;quot;name&amp;quot;&amp;amp;gt;Nom&amp;amp;lt;/label&amp;amp;gt;
      &amp;amp;lt;input id=&amp;quot;name&amp;quot; type=&amp;quot;text&amp;quot; placeholder=&amp;quot;Entrez votre nom&amp;quot; /&amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;

      &amp;amp;lt;label for=&amp;quot;number&amp;quot;&amp;amp;gt;Entrez votre age&amp;amp;lt;/label&amp;amp;gt;
      &amp;amp;lt;input type=&amp;quot;number&amp;quot; id=&amp;quot;number-age&amp;quot; value=&amp;quot;15&amp;quot; oninput=&amp;quot;document.getElementById(&amp;#39;range-age&amp;#39;).value=this.value&amp;quot;&amp;amp;gt;
      &amp;amp;lt;input type=&amp;quot;range&amp;quot; id=&amp;quot;range-age&amp;quot; min=&amp;quot;0&amp;quot; max=&amp;quot;100&amp;quot;
        oninput=&amp;quot;document.getElementById(&amp;#39;number-age&amp;#39;).value=this.value&amp;quot;&amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;

      &amp;amp;lt;!-- Input select --&amp;amp;gt;
      &amp;amp;lt;label for=&amp;quot;gender&amp;quot;&amp;amp;gt;Genre&amp;amp;lt;/label&amp;amp;gt;
      &amp;amp;lt;select id=&amp;quot;gender&amp;quot;&amp;amp;gt;
        &amp;amp;lt;option selected=&amp;quot;selected&amp;quot; value=&amp;quot;Homme&amp;quot;&amp;amp;gt;Homme&amp;amp;lt;/option&amp;amp;gt;
        &amp;amp;lt;option value=&amp;quot;Femme&amp;quot;&amp;amp;gt;Femme&amp;amp;lt;/option&amp;amp;gt;
      &amp;amp;lt;/select&amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;

      &amp;amp;lt;!-- Input radio --&amp;amp;gt;
      &amp;amp;lt;div&amp;amp;gt;
        &amp;amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;type&amp;quot; id=&amp;quot;human&amp;quot; checked /&amp;amp;gt;
        &amp;amp;lt;label for=&amp;quot;human&amp;quot;&amp;amp;gt;Humain&amp;amp;lt;/label&amp;amp;gt;

        &amp;amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;type&amp;quot; id=&amp;quot;dog&amp;quot; /&amp;amp;gt;
        &amp;amp;lt;label for=&amp;quot;dog&amp;quot;&amp;amp;gt;Chien&amp;amp;lt;/label&amp;amp;gt;

        &amp;amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;type&amp;quot; id=&amp;quot;cat&amp;quot; /&amp;amp;gt;
        &amp;amp;lt;label for=&amp;quot;cat&amp;quot;&amp;amp;gt;Chat&amp;amp;lt;/label&amp;amp;gt;
      &amp;amp;lt;/div&amp;amp;gt;

      &amp;amp;lt;textarea cols=&amp;quot;20&amp;quot; rows=&amp;quot;5&amp;quot; placeholder=&amp;quot;Votre message...&amp;quot;&amp;amp;gt;&amp;amp;lt;/textarea&amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;

      &amp;amp;lt;!-- Input Checkbox --&amp;amp;gt;
      &amp;amp;lt;label&amp;amp;gt;&amp;amp;lt;input type=&amp;quot;checkbox&amp;quot; /&amp;amp;gt;Accepter les CGV&amp;amp;lt;/label&amp;amp;gt; &amp;amp;lt;br /&amp;amp;gt;
      &amp;amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Submit&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;/form&amp;amp;gt;
  &amp;amp;lt;/section&amp;amp;gt;
  &amp;amp;lt;br /&amp;amp;gt;
  &amp;amp;lt;!-- Mail &amp;amp;amp; envoi de fichiers --&amp;amp;gt;
  &amp;amp;lt;footer&amp;amp;gt;
    &amp;amp;lt;a href=&amp;quot;mailto:fs@gmail.com&amp;quot;&amp;amp;gt;Ecrivez-moi !&amp;amp;lt;/a&amp;amp;gt;
    &amp;amp;lt;br /&amp;amp;gt;
    &amp;amp;lt;a href=&amp;quot;notice.txt&amp;quot; download=&amp;quot;nom-du-fichier&amp;quot;&amp;amp;gt;Télécharger la notice&amp;amp;lt;/a&amp;amp;gt;
    &amp;amp;lt;details&amp;amp;gt;
      &amp;amp;lt;summary&amp;amp;gt;Plus d&amp;#39;infos&amp;amp;lt;/summary&amp;amp;gt;
      &amp;amp;lt;p&amp;amp;gt;
        Lorem ipsum dolor, sit amet consectetur adipisicing elit. Harum,
        repellendus.
      &amp;amp;lt;/p&amp;amp;gt;
    &amp;amp;lt;/details&amp;amp;gt;
  &amp;amp;lt;/footer&amp;amp;gt;
&amp;amp;lt;/body&amp;amp;gt;

&amp;amp;lt;/html&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc&amp;quot;&amp;gt;[toc]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>मेमो जावास्क्रिप्ट</title>
            <link >https://cheroliv.com/blog/2023/0060_memo_js_post.html</link>
            <pubDate>Fri, 4 Aug 2023 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2023/0060_memo_js_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;गिटहब रिपॉजिटरी:https://github.com/cheroliv/js-codebase[js-codebase, window=&amp;quot;_blank]&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;toc_js&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय जावास्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;(No output)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#arrays&amp;quot;&amp;gt;एरे&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;फलन&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#param_x_scope&amp;quot;&amp;gt;पारामीटर्स और scopes&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#objects&amp;quot;&amp;gt;वस्तुएं&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#loops&amp;quot;&amp;gt;लूप&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#const_var_let&amp;quot;&amp;gt;Const, var और let&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#rest_and_spread_operators&amp;quot;&amp;gt;Rest और spread operators&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#destructuring&amp;quot;&amp;gt;[destructuring]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#import_export&amp;quot;&amp;gt;मॉड्यूल्स का आयात और निर्यात&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;कक्षाएँ&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;index.html&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-html&amp;quot; data-lang=&amp;quot;html&amp;quot;&amp;gt;&amp;amp;lt;!DOCTYPE html&amp;amp;gt;
&amp;amp;lt;html lang=&amp;quot;fr&amp;quot;&amp;amp;gt;

&amp;amp;lt;head&amp;amp;gt;
    &amp;amp;lt;meta charset=&amp;quot;UTF-8&amp;quot;&amp;amp;gt;
    &amp;amp;lt;title&amp;amp;gt;Document&amp;amp;lt;/title&amp;amp;gt;
    &amp;amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0&amp;quot; /&amp;amp;gt;
    &amp;amp;lt;meta http-equiv=&amp;quot;X-UA-Compatible&amp;quot; content=&amp;quot;ie=edge&amp;quot; /&amp;amp;gt;
&amp;amp;lt;/head&amp;amp;gt;

&amp;amp;lt;body&amp;amp;gt;
    index
    &amp;amp;lt;script src=&amp;quot;01_start.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
    &amp;amp;lt;script src=&amp;quot;02_arrays.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
    &amp;amp;lt;script src=&amp;quot;03_functions.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
    &amp;amp;lt;script src=&amp;quot;04_param_x_scope.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
    &amp;amp;lt;script src=&amp;quot;05_objects.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
    &amp;amp;lt;script src=&amp;quot;06_loops.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
    &amp;amp;lt;script src=&amp;quot;07_const_var_let.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
    &amp;amp;lt;script src=&amp;quot;08_rest_and_spread_operators.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
    &amp;amp;lt;script src=&amp;quot;09_destructuring.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
    &amp;amp;lt;script src=&amp;quot;10_module_import_export.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;
&amp;amp;lt;/body&amp;amp;gt;

&amp;amp;lt;/html&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_js&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय जावास्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;start&amp;quot;&amp;gt;चर, अंकगणितीय संचालक और स्ट्रिंग&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;01_start.js&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Variables
 */
//une variable stupide
var my_variable = &amp;quot;dummy variable&amp;quot;;
console.log(my_variable);

//assertion
console.assert(my_variable === &amp;quot;dummy variable&amp;quot;);

var username = &amp;quot;cheroliv&amp;quot;;
console.log(username);
console.assert(username === &amp;quot;cheroliv&amp;quot;);

//concaténation de string
console.assert(username === &amp;quot;cher&amp;quot; + &amp;quot;oliv&amp;quot;);

/**
 *  Opérateur arithmétique: + - * / %
 */
//integer
var x = 10;
var y = 5;
var z = 20;

console.log(x + y);
console.assert(x + y === 15);

console.log(x + y - z);
console.assert(x + y - z === -5);


console.log(x - y);
console.assert(x - y === 5);


console.log(x * y);
console.assert(x * y === 50);

console.log(x / y);
console.assert(x / y === 2);


console.log(&amp;quot;---------&amp;quot;);

x = 20;
y = 10;

console.log(x + y);
console.assert(x + y === 30);

console.log(x + y - z);
console.assert(x + y - z === 10);


console.log(x - y);
console.assert(x - y === 10);

console.log(x * y);
console.assert(x * y === 200);

console.log(x / z);
console.assert(x / z === 1);


//Littéraux de gabarits pour string avec backstick `
//Template literals (Template strings)
console.assert(`typeof z: ${typeof z}` === &amp;quot;typeof z: number&amp;quot;);

console.log(`x is type of : ${typeof x}`);
console.log(`y is type of : ${typeof y}`);
console.log(`z is type of : ${typeof z}`);

//typeof: donne le type de la variable
console.assert(typeof x === &amp;quot;number&amp;quot;);
console.assert(typeof y === &amp;quot;number&amp;quot;);
console.assert(typeof z === &amp;quot;number&amp;quot;);


console.log(&amp;quot;---------&amp;quot;);
/**
 * Incrémenation/décrémentation
 */
//incrémantation/décrémentation préfixe
console.log(++x) //incrémenté puis affiché: 21
console.log(x) //la valeur incrémenté: 21

//incrémantation/décrémentation suffixe
console.log(y++) //affiche la valeur sans incrémenation puis incrémente: 10
console.log(y) //la valeur incrémenté: 11

//décrémentation
x--;
y--;
console.assert(x === 20);
console.assert(y === 10);


/**
 * String: chaine de caractères
 */
console.log(`username: ${username}`);

//taille de la string
console.log(`username.length: ${username.length}`);
console.assert(username.length === 8);
console.assert(username.length === &amp;quot;cheroliv&amp;quot;.length);
console.log(&amp;quot;---------&amp;quot;);&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_js&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय जावास्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;arrays&amp;quot;&amp;gt;एरे&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;02_सरणी.js&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Les arrays
 */
// auteurs [[&amp;quot;nom &amp;quot;, &amp;quot;prénom&amp;quot;, &amp;quot;pays&amp;quot;]]
var writers = [
    [&amp;quot;Karl&amp;quot;, &amp;quot;Marx&amp;quot;, &amp;quot;de&amp;quot;],
    [&amp;quot;Jean-Jacques&amp;quot;, &amp;quot;Rousseau&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Victor&amp;quot;, &amp;quot;Hugo&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;René&amp;quot;, &amp;quot;Descartes&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Paul&amp;quot;, &amp;quot;Verlaine&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Antonio&amp;quot;, &amp;quot;Gramsci&amp;quot;, &amp;quot;it&amp;quot;],
    [&amp;quot;Georg&amp;quot;, &amp;quot;Lukacs&amp;quot;, &amp;quot;hu&amp;quot;],
    [&amp;quot;Franz&amp;quot;, &amp;quot;Kafka&amp;quot;, &amp;quot;hu&amp;quot;],
    [&amp;quot;Arthur&amp;quot;, &amp;quot;Rimbaud&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Gérard&amp;quot;, &amp;quot;de Nerval&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Chrétien&amp;quot;, &amp;quot;de Troyes&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;François&amp;quot;, &amp;quot;Rabelais&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Georg&amp;quot;, &amp;quot;Hegel&amp;quot;, &amp;quot;de&amp;quot;],
    [&amp;quot;Friedrich&amp;quot;, &amp;quot;Engels&amp;quot;, &amp;quot;de&amp;quot;],
]

console.table(writers);

// accés aux élèments du tableau
console.log(writers[0]);
console.log(`${writers[0][0]}, ${writers[0][1]} (${writers[0][2]})`);
console.assert(&amp;quot;Karl, Marx (de)&amp;quot; === `${writers[0][0]}, ${writers[0][1]} (${writers[0][2]})`);

//sauvegarder la valeur du prénom de Marx
var karl = writers[0][0]

//éditer un élement du tableau, le prénom de Marx
writers[0][0] = &amp;quot;Karlito&amp;quot;

console.log(`${writers[0][0]}, ${writers[0][1]} (${writers[0][2]})`);
console.assert(&amp;quot;Karlito, Marx (de)&amp;quot; === `${writers[0][0]}, ${writers[0][1]} (${writers[0][2]})`);

console.assert(&amp;quot;Karl&amp;quot; === karl);

//remettre la valeur initale du prénom de Marx
writers[0][0] = karl;

console.assert(`${karl}, Marx (de)` === `${writers[0][0]}, ${writers[0][1]} (${writers[0][2]})`);

console.log(&amp;quot;---------&amp;quot;);

/**
 *  Arrays: map/forEach/pop/push/slice/sort/shift/unshift
 */

var numbers = [1, 5, 4, 3, 2];

console.log(&amp;quot;Iterate with forEach&amp;quot;);
// parcourir avec array.forEach
numbers.forEach((it) =&amp;amp;gt; console.log(it));
console.log(&amp;quot;---------&amp;quot;);

console.log(&amp;quot;Iterate with map&amp;quot;);
// parcourir avec array.map
numbers.map((it) =&amp;amp;gt; console.log(it));
console.log(&amp;quot;---------&amp;quot;);

//afficher les éléments sur une ligne
//génère la string avec le formatage des nombres
const numbersString = (numberArray) =&amp;amp;gt; {
    var consoleOutput = new String();
    numberArray.forEach(number =&amp;amp;gt; consoleOutput += `${number}, `);
    return consoleOutput = consoleOutput.substring(0, consoleOutput.length - 2);
};

//affiche la chaine entre crochets dans la console
const displayNumbers = (numbersStr) =&amp;amp;gt; {
    console.log(`[${numbersString(numbersStr)}]`);
};

console.log(&amp;quot;orginal number array&amp;quot;)
displayNumbers(numbers);
console.log(&amp;quot;---------&amp;quot;);


//push: ajoute à la fin
console.log(&amp;quot;push&amp;quot;);
numbers.push(6);
displayNumbers(numbers);
console.log(&amp;quot;---------&amp;quot;);

//pop: suprime le dernier
console.log(&amp;quot;pop&amp;quot;);
numbers.pop();
displayNumbers(numbers);
console.log(&amp;quot;---------&amp;quot;);

//unshift: ajouter le parametre au debut de l&amp;#39;array
console.log(&amp;quot;unshift&amp;quot;);
numbers.unshift(0);
displayNumbers(numbers);
console.log(&amp;quot;---------&amp;quot;);

//shift: supprime le premier element de l&amp;#39;array
console.log(&amp;quot;shift&amp;quot;);
numbers.shift();
displayNumbers(numbers);
console.log(&amp;quot;---------&amp;quot;);

//slice: renvoi l&amp;#39;array entre les positions en argument
console.log(&amp;quot;slice&amp;quot;);
var sliceNumbersResult = numbers.slice(2, 4);
displayNumbers(sliceNumbersResult);
console.log(&amp;quot;---------&amp;quot;);

//sort asc
console.log(&amp;quot;sort asc&amp;quot;);
var ascSort = numbers.sort((a, b) =&amp;amp;gt; a - b);
displayNumbers(ascSort);
console.log(&amp;quot;---------&amp;quot;);

//sort desc
console.log(&amp;quot;sort desc&amp;quot;);
var descSort = numbers.sort((a, b) =&amp;amp;gt; b - a);
displayNumbers(descSort);
console.log(&amp;quot;---------&amp;quot;);&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_js&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय जावास्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;functions&amp;quot;&amp;gt;फ़ंक्शन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;03_functions.js&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 *  Les fonctions
 */

//function style legacy
function sayHelloWorldLegacy() {
    console.log(&amp;quot;Hello world legacy!&amp;quot;);
}
sayHelloWorldLegacy();

function sayHelloLegacy(firstName, lastName, style) {
    console.log(`Hello ${firstName}, ${lastName} (${style})`);
}
sayHelloLegacy(&amp;quot;Cher&amp;quot;, &amp;quot;Oliv&amp;quot;, &amp;quot;legacy&amp;quot;);

console.log(&amp;quot;---------&amp;quot;);

//function style arrow
const sayHelloWorld = () =&amp;amp;gt; console.log(&amp;quot;Hello world!&amp;quot;);
sayHelloWorld();

const sayHello = (firstName, lastName) =&amp;amp;gt;
    console.log(`Hello ${firstName}, ${lastName}`);
sayHello(&amp;quot;Cher&amp;quot;, &amp;quot;Oliv&amp;quot;);

console.log(&amp;quot;---------&amp;quot;);

var authors = [
    [&amp;quot;Chrétien&amp;quot;, &amp;quot;de Troyes&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;François&amp;quot;, &amp;quot;Rabelais&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;René&amp;quot;, &amp;quot;Descartes&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Jean-Jacques&amp;quot;, &amp;quot;Rousseau&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Georg&amp;quot;, &amp;quot;Hegel&amp;quot;, &amp;quot;de&amp;quot;],
    [&amp;quot;Karl&amp;quot;, &amp;quot;Marx&amp;quot;, &amp;quot;de&amp;quot;],
    [&amp;quot;Friedrich&amp;quot;, &amp;quot;Engels&amp;quot;, &amp;quot;de&amp;quot;],
    [&amp;quot;Victor&amp;quot;, &amp;quot;Hugo&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Paul&amp;quot;, &amp;quot;Verlaine&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Antonio&amp;quot;, &amp;quot;Gramsci&amp;quot;, &amp;quot;it&amp;quot;],
    [&amp;quot;Georg&amp;quot;, &amp;quot;Lukacs&amp;quot;, &amp;quot;hu&amp;quot;],
    [&amp;quot;Franz&amp;quot;, &amp;quot;Kafka&amp;quot;, &amp;quot;hu&amp;quot;],
    [&amp;quot;Arthur&amp;quot;, &amp;quot;Rimbaud&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Gérard&amp;quot;, &amp;quot;de Nerval&amp;quot;, &amp;quot;fr&amp;quot;],
]


const displayAuthors = (authorsArray) =&amp;amp;gt; authorsArray.forEach(author =&amp;amp;gt;
    console.log(`${author[0]} ${author[1]}, (${author[2]})`)
);

displayAuthors(authors);

console.log(&amp;quot;---------&amp;quot;);

/**
 * valeur par défaut des parametres d&amp;#39;une fonctions
 */
const add = (a = 0, b = 0) =&amp;amp;gt; a + b;
console.assert(add() === 0)
console.assert(add(1) === 1)
console.assert(add(1, 1) === 2)

console.log(&amp;quot;---------&amp;quot;);&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_js&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय जावास्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;param_x_scope&amp;quot;&amp;gt;पारामीटर्स और scopes&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;04_param_x_scope.js&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;//global scope: visible partout, dans et hors functions
var global;

const foo = () =&amp;amp;gt; {
    //local scope: visible uniquement dans la fonction foo
    var bar = &amp;quot;bar&amp;quot;
    console.log(bar)
}

foo();
console.log(&amp;quot;---------&amp;quot;);&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_js&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय जावास्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;objects&amp;quot;&amp;gt;वस्तुएं&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;05_objects.js&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Les objects
 */
var authors = [
    [&amp;quot;Chrétien&amp;quot;, &amp;quot;de Troyes&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;François&amp;quot;, &amp;quot;Rabelais&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;René&amp;quot;, &amp;quot;Descartes&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Jean-Jacques&amp;quot;, &amp;quot;Rousseau&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Georg&amp;quot;, &amp;quot;Hegel&amp;quot;, &amp;quot;de&amp;quot;],
    [&amp;quot;Karl&amp;quot;, &amp;quot;Marx&amp;quot;, &amp;quot;de&amp;quot;],
    [&amp;quot;Friedrich&amp;quot;, &amp;quot;Engels&amp;quot;, &amp;quot;de&amp;quot;],
    [&amp;quot;Victor&amp;quot;, &amp;quot;Hugo&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Paul&amp;quot;, &amp;quot;Verlaine&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Antonio&amp;quot;, &amp;quot;Gramsci&amp;quot;, &amp;quot;it&amp;quot;],
    [&amp;quot;Georg&amp;quot;, &amp;quot;Lukacs&amp;quot;, &amp;quot;hu&amp;quot;],
    [&amp;quot;Franz&amp;quot;, &amp;quot;Kafka&amp;quot;, &amp;quot;hu&amp;quot;],
    [&amp;quot;Arthur&amp;quot;, &amp;quot;Rimbaud&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Gérard&amp;quot;, &amp;quot;de Nerval&amp;quot;, &amp;quot;fr&amp;quot;],
];

var hugo = {
    firstName: authors[7][0],
    lastName: authors[7][1],
    country: authors[7][2],
};

var book = {
    author: hugo,
    title: &amp;quot;Les misérables&amp;quot;
};
console.log(hugo);
console.log(book);

//accéder à un membre de l&amp;#39;objet par point
console.log(hugo.country);

//accéder à un membre de l&amp;#39;objet par crochet
console.log(book[&amp;quot;title&amp;quot;]);

console.log(book.author.lastName);

console.log(book[&amp;quot;author&amp;quot;][&amp;quot;firstName&amp;quot;]);

//ajouter une clé a un objet
hugo.gender = &amp;quot;non binary&amp;quot;;
console.assert(hugo.gender === &amp;quot;non binary&amp;quot;);


//mettre à jour une clé
hugo.gender = &amp;quot;male&amp;quot;;
console.assert(hugo.gender !== &amp;quot;non binary&amp;quot;);
console.assert(hugo[&amp;quot;gender&amp;quot;] === &amp;quot;male&amp;quot;);

//supprimer une clé
delete hugo.gender;


//verfier que l&amp;#39;objet ne contient pas la clé gender
console.assert(!Object.keys(hugo).includes(&amp;quot;gender&amp;quot;));


console.log(&amp;quot;---------&amp;quot;);&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_js&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय जावास्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;loops&amp;quot;&amp;gt;लूप&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;06_loops.js&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Les boucles: Itérer sur arrays et objets.
 */

console.log(&amp;quot;for loop over array&amp;quot;);

var numbers = [12, 10, 8, 6, 4, 2, 0];

for (number of numbers) {
    console.log(number);
}

console.log(&amp;quot;---------&amp;quot;);

console.log(&amp;quot;for loop over object key&amp;quot;);

var obj = { a: 1, b: 2, c: 3, d: 4 };

for (key in obj) {
    console.log(key);
}

console.log(&amp;quot;---------&amp;quot;);

console.log(&amp;quot;for loop over object value&amp;quot;);

for (value in obj) {
    console.log(obj[value]);
}

console.log(&amp;quot;---------&amp;quot;);

console.log(&amp;quot;another for loop over authors array&amp;quot;)

var authors = [
    [&amp;quot;Chrétien&amp;quot;, &amp;quot;de Troyes&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;François&amp;quot;, &amp;quot;Rabelais&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;René&amp;quot;, &amp;quot;Descartes&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Jean-Jacques&amp;quot;, &amp;quot;Rousseau&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Georg&amp;quot;, &amp;quot;Hegel&amp;quot;, &amp;quot;de&amp;quot;],
    [&amp;quot;Karl&amp;quot;, &amp;quot;Marx&amp;quot;, &amp;quot;de&amp;quot;],
    [&amp;quot;Friedrich&amp;quot;, &amp;quot;Engels&amp;quot;, &amp;quot;de&amp;quot;],
    [&amp;quot;Victor&amp;quot;, &amp;quot;Hugo&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Paul&amp;quot;, &amp;quot;Verlaine&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Antonio&amp;quot;, &amp;quot;Gramsci&amp;quot;, &amp;quot;it&amp;quot;],
    [&amp;quot;Georg&amp;quot;, &amp;quot;Lukacs&amp;quot;, &amp;quot;hu&amp;quot;],
    [&amp;quot;Franz&amp;quot;, &amp;quot;Kafka&amp;quot;, &amp;quot;hu&amp;quot;],
    [&amp;quot;Arthur&amp;quot;, &amp;quot;Rimbaud&amp;quot;, &amp;quot;fr&amp;quot;],
    [&amp;quot;Gérard&amp;quot;, &amp;quot;de Nerval&amp;quot;, &amp;quot;fr&amp;quot;],
];

for (const [i, value] of authors.entries()) {
    console.log(`${value[0]}, ${value[1]} (${value[2]})`);
}

console.log(&amp;quot;---------&amp;quot;);

console.log(&amp;quot;while loop over array&amp;quot;)

var i = 0
while (i &amp;amp;lt; authors.length) {
    console.log(`${authors[i][0]}, ${authors[i][1]} (${authors[i][2]})`);
    i++;
}

console.log(&amp;quot;---------&amp;quot;);&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_js&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय जावास्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;const_var_let&amp;quot;&amp;gt;Const, var और let&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;07_const_var_let.js&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * const X var X let
 */
//var x du if n&amp;#39;est pas confiné au scope du if
const varTest = () =&amp;amp;gt; {
    var x = 1;
    console.log(x);
    console.assert(x === 1);
    if (true) {
        var x = 2;
        console.log(x);
        console.assert(x === 2);
    }
    console.log(x);
    console.assert(x !== 1);
    console.assert(x === 2);
}
varTest();

console.log(&amp;quot;---------&amp;quot;);

//var x est global à tous les fichier js
//chargés dans la page html
//var x issue du fichier 1_start.js
//ligne 46
console.log(x);
console.assert(x === 20);

console.log(&amp;quot;---------&amp;quot;);

//premier let x est confiné au scope de la fonction
//le let x du if est confiné au scope du if
const letTest = () =&amp;amp;gt; {
    let x = 1;
    console.log(x);
    console.assert(x === 1);
    if (true) {
        let x = 2;
        console.log(x);
        console.assert(x === 2);
    }
    console.log(x);
    console.assert(x === 1);
    console.assert(x !== 2);
}
letTest();

console.log(&amp;quot;---------&amp;quot;);

/**
 * const: déclare un emplacement mémoire non réattribuable
 * c&amp;#39;est modifiable pour un array,
 * mais non réinitialisable;
 * ex:
 * const arr = [25, 27, 29]
 * arr = [5, 7] //impossible
 * arr[0]=20 // possible
 * ex:
 * const n = 1;
 * n = 3; //impossible
 */
const arr = [25, 27, 29]
console.table(arr);
arr[0] = 20 // possible
console.table(arr);

arr.pop()
console.table(arr);
console.log(&amp;quot;---------&amp;quot;);&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_js&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय जावास्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;rest_and_spread_operators&amp;quot;&amp;gt;Rest और spread operators&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;08_विराम_और_प्रसार_ऑपरेटर्स.js&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Opérateur de rest:
 * const add = (...operandes) =&amp;amp;gt; a + b;
 * ou avec parametres avec valeur par défaut
 * const add = (a=0, b=0, ...operandes) =&amp;amp;gt; a + b;
 */

/**
 * spread opérateur:
 * récupère l&amp;#39;ensemble des elements d&amp;#39;une collection,
 * dans un array
 */
const user_ages = [25, 56, 12, 58, 41, 62, 26];

const max_user_age = Math.max(...user_ages);
const min_user_age = Math.min(...user_ages);

console.assert(max_user_age == 62);
console.assert(min_user_age == 12);

console.log(&amp;quot;---------&amp;quot;);&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_js&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय जावास्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;विघटन&amp;quot;&amp;gt;विघटन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;09_destructuring.js&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * L&amp;#39;affectation par décomposition (destructuring)
 */

const user = {
    first_name: &amp;quot;Oliv&amp;quot;,
    last_name: &amp;quot;Cher&amp;quot;,
    nick_name: &amp;quot;cheroliv&amp;quot;,
    gender: &amp;quot;male&amp;quot;,
    is_adult: true
};
console.log(user);

//première façon d&amp;#39;initaliser des variables sans destructuration
let first_name_legacy = user.first_name;
let last_name_legacy = user.last_name;
let nick_name_legacy = user.nick_name;
let gender_legacy = user.gender;
let is_adult_legacy = user.is_adult;

console.assert(&amp;quot;Oliv&amp;quot; === first_name_legacy);
console.assert(&amp;quot;Cher&amp;quot; === last_name_legacy);
console.assert(&amp;quot;cheroliv&amp;quot; === nick_name_legacy);
console.assert(&amp;quot;male&amp;quot; === gender_legacy);
console.assert(true === is_adult_legacy);
console.log(&amp;quot;---------&amp;quot;);
/**
 * Initialisation par déstructuration
 */
const {
    first_name,
    last_name,
    nick_name,
    gender,
    is_adult
} = user;

console.assert(user.first_name === first_name);
console.assert(user.last_name === last_name);
console.assert(user.nick_name === nick_name);
console.assert(user.gender === gender);
console.assert(user.is_adult === is_adult);

/**
 * Intialisation par déstructuration des arrays
 */
//cible explicite
const [a1, a2] = [15, 25, 17, 81, 51, 46];
console.assert(a1 === 15);
console.assert(a2 === 25);

//cible avec position par rapport aux index par virgules
//je veux b3 à 46
const [b1, b2, , , , b3] = [15, 25, 17, 81, 51, 46];
console.assert(b1 === 15);
console.assert(b2 === 25);
console.assert(b3 === 46);

//déstructuration avec operateur de rest
// je contruit un autre avec avec les elements
// à partir du premier élèment non destructuré
const [c1, c2, ...sub_arr] = [15, 25, 17, 81, 51, 46];
console.assert(b1 === 15);
console.assert(b2 === 25);
console.assert(sub_arr.length === 4);
console.assert(sub_arr[0] === 17);
console.assert(sub_arr[1] === 81);
console.assert(sub_arr[2] === 51);
console.assert(sub_arr[3] === 46);


// Une boucle pour comparer le resultat attendu
for (const [i, value] of[15, 25, 17, 81, 51, 46].entries()) {
    //on reconstruit le tableau à chaque iteration
    console.assert([c1, c2].concat(sub_arr)[i] === value);
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_js&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय जावास्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;import_export&amp;quot;&amp;gt;मॉड्यूल्स का आयात और निर्यात&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;10_module_import_export.js&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Import et export de module
 *
 * Dans le fichier html
 * au niveau de la balise d&amp;#39;import de script
 * spécifier le type module
 *
 * 1er technique: import nommé des fonctions:
 * import { sum, minus, times, div, rem } from &amp;quot;./dummy_math_functions.js&amp;quot;;
 *
 * 2eme technique: import global des fonction avec l&amp;#39;asterisque(*)
 * en préfixant l&amp;#39;import par un nommage du fichier importé:
 * import * as math from &amp;quot;./dummy_math_functions.js&amp;quot;;
 *
 * 3eme technique: import par alias avec le mot clé &amp;quot;as&amp;quot;
 * import {
 *     sum as add,
 *     minus as substract,
 *     times as multiply,
 *     div as divide,
 *     rem as modulo
 * } from &amp;quot;./dummy_math_functions.js&amp;quot;;
 */

import {
    sum,
    minus,
    times,
    div,
    rem
} from &amp;quot;./dummy_math_functions.js&amp;quot;;

console.assert(sum(1, 1) === 2);
console.assert(minus(4, 2) === 2);
console.assert(times(2, 2) === 4);
console.assert(div(4, 2) === 2);
console.assert(rem(4, 2) === 0);&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;dummy_math_functions.js&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;//sum
const sum = (x, y) =&amp;amp;gt; x + y;

// subtraction
const minus = (x, y) =&amp;amp;gt; x - y;

// multiplication
const times = (x, y) =&amp;amp;gt; x * y;

// division
const div = (x, y) =&amp;amp;gt; x / y;

// remainder: reste de la division euclidiene
const rem = (x, y) =&amp;amp;gt; x % y;

// log sum
const sum_log = (x, y) =&amp;amp;gt; console.log(sum(x, y));

// log subtraction
const minus_log = (x, y) =&amp;amp;gt; console.log(minus(x, y));

// log multiplication
const times_log = (x, y) =&amp;amp;gt; console.log(times(x, y));

// log division
const div_log = (x, y) =&amp;amp;gt; console.log(div(x, y));

// log remainder
const rem_log = (x, y) =&amp;amp;gt; console.log(rem(x, y));

export {
    sum,
    minus,
    times,
    div,
    rem,
    sum_log,
    minus_log,
    times_log,
    div_log,
    rem_log
};&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_js&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय जावास्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;classes&amp;quot;&amp;gt;क्लासों का उपयोग&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;11_classes.js&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-javascript&amp;quot; data-lang=&amp;quot;javascript&amp;quot;&amp;gt;/**
 * Utilisation des classes
 */
//creation d&amp;#39;un objet
class Account {
    constructor(username) {
        this.username = username;
    }
};

const acc1 = new Account(&amp;quot;cheroliv&amp;quot;);
console.table(acc1);
console.assert(acc1.username === &amp;quot;cheroliv&amp;quot;);

console.log(&amp;quot;---------&amp;quot;);

//création d&amp;#39;un objet et ajout de getter et setter(accesseurs)
class AccountInfo {
    constructor(username) {
        this._username = username;
    }

    get username() {
        return this._username;
    }

    /**
     * @param {(arg0: string) =&amp;amp;gt; void} new_username
     */
    set new_username(new_username) {
        this._username = new_username;
    }
};

const acc_info1 = new AccountInfo(&amp;quot;cheroliv&amp;quot;);
console.table(acc_info1);
//accés au membre _username avec le getter username()
console.assert(acc_info1.username === &amp;quot;cheroliv&amp;quot;);

//update la valeur username de acc_info1 avec le setter
acc_info1.new_username = &amp;quot;imrandeh&amp;quot;;
console.assert(acc_info1.username === &amp;quot;imrandeh&amp;quot;);

console.log(&amp;quot;---------&amp;quot;);&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc_js&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;परिचय जावास्क्रिप्ट&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>स्मरणिका फ़्रेमिंग</title>
            <link >https://cheroliv.com/blog/2022/0054_memo_cadrage_post.html</link>
            <pubDate>Sat, 31 Dec 2022 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2022/0054_memo_cadrage_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_फ्रेमिंग&amp;quot;&amp;gt;फ्रेमिंग&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_कार्यशाला_1_दृष्टि&amp;quot;&amp;gt;कार्यशाला 1: दृष्टि&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_पैटर्न_qqoqcp_कौन_क्या_कहाँ_कब_कैसे_क्यों&amp;quot;&amp;gt;पैटर्न “QQOQCP” – कौन, क्या, कहाँ, कब, कैसे, क्यों&amp;lt;/h4&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_2_उत्पाद_विज़न_बोर्ड&amp;quot;&amp;gt;2. उत्पाद विज़न बोर्ड&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;sect4&amp;quot;&amp;gt;
&amp;lt;h5 id=&amp;quot;_लक्ष्य_समूह&amp;quot;&amp;gt;लक्ष्य समूह&amp;lt;/h5&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;उपयोगकर्ता कौन हैं जो उत्पाद या पेशकश का उपयोग करते हैं? (सीधा, अप्रत्यक्ष)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect4&amp;quot;&amp;gt;
&amp;lt;h5 id=&amp;quot;_आवश्यकताएँ&amp;quot;&amp;gt;आवश्यकताएँ&amp;lt;/h5&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एप्लिकेशन के मुख्य उपयोगकर्ताओं की 5 प्रमुख आवश्यकताएँ क्या हैं ?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect4&amp;quot;&amp;gt;
&amp;lt;h5 id=&amp;quot;_उत्पाद&amp;quot;&amp;gt;उत्पाद&amp;lt;/h5&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मेरी मूल्य प्रस्ताव क्या है? उत्पाद की 5 मुख्य सुविधाएँ क्या हैं जो निम्नलिखित का उत्तर देने में सक्षम बनाती हैं? आवश्यकताएँ&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect4&amp;quot;&amp;gt;
&amp;lt;h5 id=&amp;quot;_व्यवसाय_लक्ष्य&amp;quot;&amp;gt;व्यवसाय लक्ष्य&amp;lt;/h5&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सफलता के मानक क्या हैं ?&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect4&amp;quot;&amp;gt;
&amp;lt;h5 id=&amp;quot;_दृष्टि&amp;quot;&amp;gt;दृष्टि&amp;lt;/h5&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;जब 4 कॉलम पूरे हो जाएँ, तो आपको उत्पाद विज़न के विज़न भाग को भरना होगा। बोर्ड को एक पूर्ण वाक्य में।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_वर्कशॉप_2_पर्सनाउपयोगकर्ता_यात्रा&amp;quot;&amp;gt;वर्कशॉप 2: पर्सना/उपयोगकर्ता यात्रा&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;प्रत्येक पर्सना के लिए एक उपयोगकर्ता यात्रा परिभाषित करें:&amp;lt;/div&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;मेरी सेवा कौन उपयोग करेगा? (लक्ष्य)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;वह क्या करना चाहता है ? (But)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;वह कैसे करेगा ? (उपयोगकर्ता यात्रा)&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_कार्यशाला_3_जोनिंग_स्टोरीबोर्ड_साइटमैप&amp;quot;&amp;gt;कार्यशाला 3: जोनिंग, स्टोरीबोर्ड, साइटमैप&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_1_ज़ोनिंग&amp;quot;&amp;gt;1. ज़ोनिंग&amp;lt;/h4&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_2_स्टोरीबोर्ड&amp;quot;&amp;gt;2. स्टोरीबोर्ड&amp;lt;/h4&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_3_sitemap&amp;quot;&amp;gt;3. SiteMap&amp;lt;/h4&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_कार्यशाला_4_wireframemoodboard&amp;quot;&amp;gt;कार्यशाला 4: Wireframe/Moodboard&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_1_वायरफ़्रेम&amp;quot;&amp;gt;1. वायरफ़्रेम&amp;lt;/h4&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_2_मूडबोर्ड&amp;quot;&amp;gt;2. मूडबोर्ड&amp;lt;/h4&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_वर्कशॉप_5_स्टोरी_मैपिंग_यूज़र_स्टोरीज़&amp;quot;&amp;gt;वर्कशॉप 5: स्टोरी मैपिंग/ यूज़र स्टोरीज़&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_स्टोरी_मैपिंग_यूएस_की_प्राथमिकता&amp;quot;&amp;gt;स्टोरी मैपिंग (यूएस की प्राथमिकता)&amp;lt;/h4&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_किसी_type_dutilisateur_के_रूप_में_मैं_un_objective_चाहता_हूँ_इसके_लिए_कि_une_raison&amp;quot;&amp;gt;किसी &amp;amp;lt;type d&amp;amp;#8217;utilisateur&amp;amp;gt; के रूप में, मैं &amp;amp;lt;un objective&amp;amp;gt; चाहता हूँ इसके लिए कि &amp;amp;lt;une raison&amp;amp;gt;।&amp;lt;/h4&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_कार्यशाला_6_backlog&amp;quot;&amp;gt;कार्यशाला 6: Backlog&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://www.atlassian.com/fr/agile/scrum/backlogs&amp;quot;&amp;gt;लंबित कार्य&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_कार्यशाला_7_तकनीक_और_वास्तुकला&amp;quot;&amp;gt;कार्यशाला 7: तकनीक और वास्तुकला&amp;lt;/h3&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>कॉटलिन ज्ञापन</title>
            <link >https://cheroliv.com/blog/2022/0053_memo_kotlin_post.html</link>
            <pubDate>Sun, 29 May 2022 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2022/0053_memo_kotlin_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;----
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
}


== अच्छे लिंक

https://play.kotlinlang.org/[kotlinlang प्लेग्राउंड](No output)

https://arrow-kt.io/[तीर.kt]+

https://arkivanov.github.io/MVIKotlin/[MVI:मॉडल व्यू इंटेंट]+

https://github.com/arkivanov/Essenty[Essenty]+

https://arkivanov.github.io/Decompose/[विघटित](No output)

== Bout de code divers

=== मानचित्र घटाना

बाइट की सूची को स्ट्रिंग की सूची में बदलें और स्ट्रिंग की सूची का सारांश दें +
एक स्ट्रिंग जिसमें संयोजन होता है। कैसे request भेजे गए requestBodyContent:byte[] की लॉग करें

[source,kotlin]
----
log.info(
    requestBodyContent!!.map { it.toInt().toChar().toString() }
        .reduce { request: String, s: String -&amp;amp;gt; request + s }
)
----

=== enum और सील्ड क्लासेस

[No output]link:0038_training_kotlin_enum_sealed_class_post[प्रशिक्षण kotlin enum सील्ड क्लास, window=&amp;quot;_blank]

=== functionnal interface और method reference

एक इकाई को DTO डोमेन मॉडल में परिवर्तित किया जा सकता है, एक विधि संदर्भ (फ़ंक्शनल शैली - Java 8) के साथ।

[source,kotlin]
----
fun findAllByLoginNot(
        pageable:Pageable,
        login:String)
    :Page&amp;amp;lt;UserDto&amp;amp;gt; {
    return userDao.findAllByLoginNot(
                    pageable,
                    login).map(::fromEntity)
}
----

एकhttps://stackoverflow.com/a/22245383/837404[अच्छी व्याख्या]

=== मानक आउटपुट को कैप्चर करें

[source,kotlin]
----
package functional

import java.io.ByteArrayOutputStream
import java.io.PrintStream
import java.lang.System.out
import java.lang.System.setOut
import kotlin.test.AfterTest
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals


class BasicsHOF {
    private val standardOut: PrintStream? = out
    private val outputStreamCaptor = ByteArrayOutputStream()

    @BeforeTest
    fun setUp() = setOut(PrintStream(outputStreamCaptor))

    @AfterTest
    fun tearDown() = setOut(standardOut)

    @Test
    fun `three times dope`() {

        3.times { println(&amp;quot;Hello&amp;quot;) }

        assertEquals(
            buildString {
                repeat(3) { append(&amp;quot;Hello\n&amp;quot;) }
                deleteAt(length - 1)
            }, outputStreamCaptor
                .toString()
                .trim()
        )
    }

    fun Int.times(fn: () -&amp;amp;gt; Unit) = (1..this).forEach { _ -&amp;amp;gt; fn() }
}
----

=== Kotlin में apply, run, let, also, use और with के बीच क्या अंतर है?

Kotlin फ़ंक्शनों की तुलना और लैम्ब्डा फ़ॉर्म का उपयोग संदर्भ

.परिचय Kotlin फ़ंक्शन`apply`, `run`, `let`, `also`, `use`, et `with`वस्तुओं को संभालने के विभिन्न तरीके प्रदान करते हैं। प्रत्येक का अपना उपयोग केस और व्यवहार होता है। इसके अलावा, लैम्ब्डा रेफरेंस रूपों से मौजूदा लैम्ब्डा कार्यों को संदर्भित करके कोड को अधिक पढ़ने योग्य और पुन: प्रयोज्य बनाया जा सकता है।

== लागू करना ==

फ़ंक्शन`apply`इसे ऑब्जेक्ट को उसकी सृजन के दौरान कॉन्फ़िगर करने के लिए उपयोग किया जाता है। यह उस ऑब्जेक्ट को लौटाता है जिस पर इसे कॉल किया जाता है।

उदाहरण लैम्ब्डा संदर्भ :

[source,kotlin]
----
val someObject = SomeClass().apply(::configureObject)
----

उदाहरण लैम्ब्डा के साथ :

[source,kotlin]
----
val someObject = SomeClass().apply {
// configuration des propriétés de someObject
}
----

== चलना ==

फ़ंक्शन`run`एक ऑब्जेक्ट पर कोड के एक ब्लॉक को निष्पादित करने और कोड ब्लॉक का परिणाम लौटाने के लिए उपयोग की जाती है।

लैम्ब्डा संदर्भ का उदाहरण :

[source,kotlin]
----
val result = someObject.run(::someFunction)
----

लैम्ब्डा के साथ उदाहरण :

[source,kotlin]
----
val result = someObject.run {
// bloc de code à exécuter sur someObject
// la dernière expression est renvoyée
}
----

== अनुमति दें ==

फ़ंक्शन`let`इसका उपयोग एक ऑब्जेक्ट पर कोड के ब्लॉक को निष्पादित करने और कोड ब्लॉक का परिणाम लौटाने के लिए किया जाता है।

उदाहरण के साथ लैम्ब्डा संदर्भ :

[source,kotlin]
----
val result = someObject.let(::processObject)
----

लैम्बडा के साथ उदाहरण:

[source,kotlin]
----
val result = someObject.let {
// bloc de code à exécuter sur someObject
// la dernière expression est renvoyée
}
----

== भी ==

फ़ंक्शन`also`इसे किसी वस्तु पर अतिरिक्त क्रिया करने के लिए उपयोग किया जाता है और यह उसी वस्तु को लौटाता है जिस पर इसे बुलाया जाता है।

लैम्ब्डा संदर्भ के साथ उदाहरण :

[source,kotlin]
----
someObject.also(::performAdditionalAction)
----

उदाहरण lambda के साथ :

[source,kotlin]
----
someObject.also {
// action additionnelle sur someObject
}
----

== उपयोग करें =|

कार्य`use`इसका उपयोग उन संसाधनों के साथ काम करने के लिए किया जाता है जिन्हें उपयोग के बाद बंद किया जाना चाहिए। यह स्वचालित रूप से फ़ंक्शन को बुलाती है`close`ब्लॉक के अंत में।

लैम्ब्डा संदर्भ के साथ उदाहरण:

[source,kotlin]
----
someResource.use(::useResource)
----

उदाहरण के साथ lambda :

[source,kotlin]
----
someResource.use {
// travailler avec la ressource
}
----

== के साथ ==

फ़ंक्शन`with`यह कई विधियों को एक ऑब्जेक्ट पर उसके नाम को दोहराए बिना कॉल करने के लिए उपयोग की जाती है और अंतिम अभिव्यक्ति का परिणाम लौटाती है।

उदाहरण लैम्ब्डा संदर्भ :

[source,kotlin]
----
val result = with(someObject, ::processWithObject)
----

लैम्ब्डा के साथ उदाहरण :

[source,kotlin]
----
val result = with(someObject) {
// appeler des méthodes sur someObject
// la dernière expression est renvoyée
}
----

लैम्ब्डा संदर्भ रूपों या ब्लॉकों का उपयोग करके`{}`, आप विभिन्न कार्यों में तर्क को समेट सकते हैं, इस प्रकार कोड की पढ़ने योग्यता और पुन: उपयोगिता में सुधार होता है।

.क्या let उस ऑब्जेक्ट को उसके पर किए गए साइड इफ़ेक्ट्स के साथ लौटाता है या इनपुट की प्रारंभिक अवस्था में function(let) में ?

== let Function en Kotlin ==

फ़ंक्शन`let`Kotlin में एक ऑब्जेक्ट पर ऑपरेशन करने और अलग परिणाम वापस करने के लिए उपयोग की जाती है। हालांकि, यह ध्यान रखना महत्वपूर्ण है कि फ़ंक्शन`let`यह विधि जिस ऑब्जेक्ट पर इसे बुलाया जाता है, उसके प्रारम्भिक स्थिति को संशोधित नहीं करती।

|===
|**हस्ताक्षर** |`inline fun &amp;amp;lt;T, R&amp;amp;gt; T.let(block: (T) -&amp;amp;gt; R): R`
|===

|===
|**उपयोग** |फ़ंक्शन`let`इसे सामान्यतः किसी ऑब्जेक्ट पर परिवर्तन लागू करने और इन परिवर्तनों पर आधारित परिणाम प्राप्त करने के लिए उपयोग किया जाता है।
|===

|===
|**परिणाम** |फ़ंक्शन द्वारा लौटाया गया मान`let`यह लैम्ब्डा अभिव्यक्ति का परिणाम है जो तर्क के रूप में पारित की गई है, सामान्यतया वस्तु पर किए गए संचालन का परिणाम होता है।
|===

|===
|**पार्श्व प्रभावों** |भले ही फ़ंक्शन`let`जब इसे लैम्ब्डा अभिव्यक्ति में उपयोग किया जाता है, तो यह ऑब्जेक्ट पर साइड इफ़ेक्ट्स डाल सकती है, लेकिन यह ऑब्जेक्ट की प्रारंभिक स्थिति को संशोधित नहीं करती।
|===

इस प्रकार, फ़ंक्शन`let`यह एक शानदार तरीका है किसी ऑब्जेक्ट पर संचालन करने का, साथ ही एक व्युत्पन्न परिणाम प्राप्त करते हुए, और मूल ऑब्जेक्ट की अखंडता को बनाए रखते हुए।
----&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>नोट JVM</title>
            <link >https://cheroliv.com/blog/2022/0052_memo_jvm_post.html</link>
            <pubDate>Sat, 28 May 2022 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2022/0052_memo_jvm_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;toc&amp;quot;&amp;gt;सामग्री की तालिका&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;olist arabic&amp;quot;&amp;gt;
&amp;lt;ol class=&amp;quot;arabic&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#टैंक&amp;quot;&amp;gt;[टैंक]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#math&amp;quot;&amp;gt;संख्याएँ और गणित&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;तारीख&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#java8date&amp;quot;&amp;gt;तारीखें और समय java8&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#arrCol&amp;quot;&amp;gt;सरणी और संग्रह&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#sysProp&amp;quot;&amp;gt;System.Properties&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#थ्रेड्स&amp;quot;&amp;gt;[थ्रेड्स]&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#regex&amp;quot;&amp;gt;नियमित अभिव्यक्तियाँ&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;char&amp;quot;&amp;gt;स्ट्रिंग्स और अक्षर&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;import java.text.Collator
import java.util.*
import kotlin.test.*

class StringsTest {
    @Test
    fun `chaines de caractères et caractères`() {
        //inférence de type
        val s = &amp;quot;C&amp;#39;est&amp;quot;
        assertEquals(&amp;quot;C&amp;#39;est&amp;quot;, s)

        //concaténation
        val t: String = s + &amp;quot; le moment.&amp;quot;
        assertEquals(&amp;quot;C&amp;#39;est le moment.&amp;quot;, t)

        // StringBuilder
        val t1: String = s + buildString { append(&amp;quot; le moment.&amp;quot;) }
        assertEquals(&amp;quot;C&amp;#39;est le moment.&amp;quot;, t1)

        //interpolation
        val t2 = &amp;quot;$s le moment.&amp;quot;
        assertEquals(&amp;quot;C&amp;#39;est le moment.&amp;quot;, t2)

        //multiligne chaine de caractères
        val t3 = &amp;quot;&amp;quot;&amp;quot;$s le moment.&amp;quot;&amp;quot;&amp;quot;
        assertEquals(&amp;quot;C&amp;#39;est le moment.&amp;quot;, t3)

        //conversion de type
        val t4 = t + &amp;quot; &amp;quot; + 23.4
        assertEquals(&amp;quot;C&amp;#39;est le moment. 23.4&amp;quot;, t4)

        val t5 = &amp;#39;C&amp;#39;.toString()
        assertEquals(&amp;quot;C&amp;quot;, t5)

        //taille de la chaine de caractères
        assertEquals(16, t.length)

        //sous-chaine d&amp;#39;une chaine de caractères

        //retourne une chaine de caractères contenant,
        //les caractères aux positions x à y-1
        //sub = t.substring(x, y)

        //t = &amp;quot;C&amp;#39;est le moment.&amp;quot;
        //retourne les caractères 6 et 7
        var sub = t.substring(6, 8)
        assertEquals(&amp;quot;le&amp;quot;, sub)

        //retourne les caractères 0 à 4
        sub = t.substring(0, 5)
        assertEquals(&amp;quot;C&amp;#39;est&amp;quot;, sub)

        //la longueur d&amp;#39;une sous-chaine est toujours égale (y-x)
        val numChars = sub.length
        assertEquals(5 - 0, numChars)

        //extraction des caractères d&amp;#39;une chaine
        assertEquals(&amp;#39;e&amp;#39;, t.elementAt(2))
        assertEquals(&amp;#39;e&amp;#39;, t.get(2))
        assertEquals(&amp;#39;e&amp;#39;, t[2])

        //conversion d&amp;#39;une chaine en tableau de caractères
        val ca = t.toCharArray()
        assertEquals(t.length, ca.size)
        t.mapIndexed { index, char -&amp;amp;gt; assertEquals(char, ca[index]) }

        //place les 4 premiers caractères de t1
        //dans le tableau ca a la position 2
        (t as java.lang.String).getChars(
            /* srcBegin = */ 0,
            /* srcEnd = */ 3,
            /* dst = */ ca,
            /* dstBegin = */ 1
        )
        assertEquals(&amp;quot;CC&amp;#39;et le moment.&amp;quot;, String(ca))
        //colle tous les caractères dans un meme string
        assertEquals(&amp;quot;CC&amp;#39;et le moment.&amp;quot;, ca.concatToString())

        //to lower case
        assertEquals(&amp;quot;c&amp;#39;est le moment.&amp;quot;, t.toLowerCase())
        assertEquals(&amp;quot;c&amp;#39;est le moment.&amp;quot;, t.lowercase())

        //to upper case
        assertEquals(&amp;quot;C&amp;#39;EST LE MOMENT.&amp;quot;, t.toUpperCase())
        assertEquals(&amp;quot;C&amp;#39;EST LE MOMENT.&amp;quot;, t.uppercase())

        //comparaison de chaines de caractères
        //t = &amp;quot;C&amp;#39;est le moment.&amp;quot;
        assertFalse(t.equals(&amp;quot;hello&amp;quot;))
        assertFalse(t == &amp;quot;hello&amp;quot;)

        //ignore la casse
        assertTrue(t.equalsIgnoreCase(&amp;quot;C&amp;#39;EST LE MOMENT.&amp;quot;))
        assertTrue(t.equals(&amp;quot;C&amp;#39;EST LE MOMENT.&amp;quot;, ignoreCase = true))

        //démarre par
        assertTrue(t.startsWith(&amp;quot;C&amp;#39;est&amp;quot;))
        //se finit par
        assertTrue(t.endsWith(&amp;quot;le moment.&amp;quot;))

        //compareTo
        //retourne une valeur &amp;amp;lt; 0, car s est
        //alphabétiquement avant &amp;quot;N&amp;#39;est&amp;quot;
        val r1: Int = s.compareTo(&amp;quot;N&amp;#39;est&amp;quot;)
        assertTrue(r1 &amp;amp;lt; 0)

        //variante ignorant la casse
        val r1Prime: Int = (s as java.lang.String).compareToIgnoreCase(&amp;quot;n&amp;#39;est&amp;quot;)
        assertTrue(r1Prime &amp;amp;lt; 0)

        //retourne 0 si les chaines sont equivalente
        val r2: Int = s.compareTo(&amp;quot;C&amp;#39;est&amp;quot;)
        assertEquals(0, r2)

        //retourne une valeur &amp;amp;gt; 0 car s vient apres &amp;quot;B&amp;#39;est&amp;quot;
        val r3: Int = s.compareTo(&amp;quot;B&amp;#39;est&amp;quot;)
        assertTrue(r3 &amp;amp;gt; 0)

        //Recherche de caractères et de sous-chaines de caractères

        //recherche de caractères
        //position du premier caractères &amp;#39;t&amp;#39;
        var pos = t.indexOf(&amp;#39;t&amp;#39;)
        assertEquals(4, pos)

        //position du suivant
        pos = t.indexOf(&amp;#39;t&amp;#39;, pos + 1)
        assertEquals(14, pos)

        //retour d&amp;#39;érreur -1 si absence de suivant
        pos = t.indexOf(&amp;#39;t&amp;#39;, pos + 1)
        assertEquals(-1, pos)

        //position du dernier &amp;#39;t&amp;#39; dans la chaine: 14
        pos = t.lastIndexOf(&amp;#39;t&amp;#39;)
        assertEquals(14, pos)

        //recherche de &amp;#39;t&amp;#39; vers l&amp;#39;arrière a partir du caractères 13
        pos = t.lastIndexOf(&amp;#39;t&amp;#39;, pos - 1)
        assertEquals(4, pos)

        //recherche de sous-chaines
        //retourne 2
        pos = t.indexOf(&amp;quot;est&amp;quot;)
        assertEquals(2, pos)

        //&amp;quot;est&amp;quot; n&amp;#39;apparait qu&amp;#39;une seule fois: retourne -1
        pos = t.indexOf(&amp;quot;est&amp;quot;, pos + 1)
        assertEquals(-1, pos)

        //recherche d&amp;#39;une sous-chaine depuis l&amp;#39;arrière
        //t = &amp;quot;C&amp;#39;est le moment.&amp;quot;
        //retourne 6
        pos = t.lastIndexOf(&amp;quot;le &amp;quot;)
        assertEquals(6, pos)

        //extrait depuis la position 9,
        //renvoi toute la chaine après &amp;quot;le &amp;quot;
        val noun = t.substring(pos + 3)
        assertEquals(-1, noun.indexOf(&amp;quot;le &amp;quot;))

        //remplacement de toutes les instances d&amp;#39;un caractère
        //par un autre caractère
        //ne fonctionne que avec les caractères, pas les chaines
        val exclaim: String = t.replace(&amp;#39;.&amp;#39;, &amp;#39;!&amp;#39;)
        assertEquals(&amp;#39;!&amp;#39;, exclaim.get(exclaim.length - 1))
        assertEquals(exclaim.length - 1, exclaim.indexOf(&amp;#39;!&amp;#39;))
        assertEquals(-1, exclaim.indexOf(&amp;#39;.&amp;#39;))

        //suppression des espaces blancs
        //au début et à la fin d&amp;#39;une chaine
        val noextraspaces = t.trim()
        assertNotEquals(&amp;#39; &amp;#39;, noextraspaces.get(0))
        assertNotEquals(&amp;#39; &amp;#39;, noextraspaces.get(noextraspaces.length - 1))

        //extraction des instances uniques de chaines de caractères
        //avec intern()
        val s1 = s.intern()
        assertEquals(s, s1)
        val s2 = &amp;quot;C&amp;#39;est&amp;quot;.intern()
        assertEquals(&amp;quot;C&amp;#39;est&amp;quot;, s2)
        assertEquals(s1, s2)

        //StringBuilder pour manipuler les caractères d&amp;#39;une chaine de caractères
        //crée un tampon StringBuilder à partir d&amp;#39;une chaine de caractères
        val b = StringBuilder(&amp;quot;N&amp;#39;est&amp;quot;)

        //extrait et définit des caractères individuel du tampon StringBuilder
        //le caractères à l&amp;#39;index 0
        val c: Char = b.get(0)
        assertEquals(&amp;#39;N&amp;#39;, c)

        //modifier le premier caractère de la chaine
        b.setCharAt(0, &amp;#39;C&amp;#39;)
        assertEquals(s, b.toString())

        //ajouter des données à un StringBuilder
        b.append(&amp;#39; &amp;#39;)
        b.append(&amp;quot;le moment.&amp;quot;)
        b.append(23)

        //insère des chaines de caractères ou autre dans le StringBuilder
        b.insert(6, &amp;quot;pas &amp;quot;)
        assertEquals(&amp;quot;C&amp;#39;est pas le moment.23&amp;quot;, b.toString())

        //remplace un sous ensemble de caractères
        //avec une chaine de caractères donnée
        b.replace(2, 9, &amp;quot;est&amp;quot;)
        assertEquals(&amp;quot;C&amp;#39;est le moment.23&amp;quot;, b.toString())

        //supprime les caractères
        b.delete(15, 18)
        assertEquals(&amp;quot;C&amp;#39;est le moment&amp;quot;, b.toString())
        b.deleteCharAt(2)
        assertEquals(&amp;quot;C&amp;#39;st le moment&amp;quot;, b.toString())

        //insert à la postion 2 et décale reste à droite(sans perte de données)
        b.insert(2, &amp;#39;e&amp;#39;)

        //tronque la taille de la donnée
        b.setLength(5)
        assertEquals(&amp;quot;C&amp;#39;est&amp;quot;, b.toString())

        //inverse les caractères de la chaine
        b.reverse()
        assertEquals(&amp;quot;tse&amp;#39;C&amp;quot;, b.toString())

        //écrase le StringBuilder, pret à etre réutilisé
        b.setLength(0)
        assertEquals(&amp;quot;&amp;quot;, b.toString())

        //java.util.StringTokenizer pour fragmenter une chaine
        //de caractères en un ensemble de mots
        var st = StringTokenizer(t)
        //nb d&amp;#39;items encore présentent dans la file
        assertEquals(3, st.countTokens())

        //est ce que il y a encore des items dans la file
        assertTrue(st.hasMoreTokens())

        //récupérer le token courrant
        assertEquals(&amp;quot;C&amp;#39;est&amp;quot;, st.nextToken())
        assertEquals(&amp;quot;le&amp;quot;, st.nextToken())
        assertEquals(&amp;quot;moment.&amp;quot;, st.nextToken())
        assertFalse(st.hasMoreTokens())
        assertEquals(0, st.countTokens())

        //extraire des occurences de mots délimités
        //par des caractères autres que des expaces.
        val str = &amp;quot;a:b:c:d&amp;quot;
        st = StringTokenizer(str, &amp;quot;:&amp;quot;)
        assertEquals(4, st.countTokens())
        assertTrue(st.hasMoreTokens())
        assertEquals(&amp;quot;a&amp;quot;, st.nextToken())
        assertEquals(&amp;quot;b&amp;quot;, st.nextToken())
        assertEquals(&amp;quot;c&amp;quot;, st.nextToken())
        assertEquals(&amp;quot;d&amp;quot;, st.nextToken())
        assertFalse(st.hasMoreTokens())
        assertEquals(0, st.countTokens())


        //text=&amp;quot;C&amp;#39;est le moment.&amp;quot;
        val text = t.toCharArray()
        var p = 0

        //sauter les espaces de tete
        //pour ramener p à la position du premier caractère imprimable
        while ((p &amp;amp;lt; text.size) &amp;amp;amp;&amp;amp;amp;
            (Character.isWhitespace(text[p]))
        ) p++
        assertEquals(0, p)
        assertEquals(&amp;quot;C&amp;#39;est le moment.&amp;quot;, text.concatToString())

        //met le premier mot du texte en majuscule
        while (p &amp;amp;lt; text.size &amp;amp;amp;&amp;amp;amp; Character.isLetter(text[p])) {
            text[p] = Character.toUpperCase(text[p])
            p++
        }
        assertEquals(1, p)
        assertEquals(&amp;#39;C&amp;#39;, text[0])
        assertTrue(Character.isUpperCase(text[0]))
        assertFalse(Character.isLetter(text[1]))

        //comparer des chaines de caractères
        // avec les contrainte la locale système
        val col = Collator.getInstance()
        //le résulat est négatif car chica
        //est avant chico dans l&amp;#39;ordre alphabétique
        assertTrue(col.compare(&amp;quot;chica&amp;quot;, &amp;quot;chico&amp;quot;) &amp;amp;lt; 0)
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc&amp;quot;&amp;gt;सामग्री की तालिका&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;math&amp;quot;&amp;gt;संख्याएँ और गणित&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;import java.math.BigInteger
import java.security.SecureRandom
import java.text.NumberFormat
import java.util.*
import kotlin.test.*

class NumbersMathTest {
    @Test
    fun `Nombres et Math`() {
        //Constantes utiles
        Byte.MIN_VALUE
        Byte.MAX_VALUE
        Short.MIN_VALUE
        Short.MAX_VALUE
        Float.MIN_VALUE
        Float.MAX_VALUE
        Math.PI
        Math.E
        val s = &amp;quot;-42&amp;quot;
        //conversion de chaine de caractères
        //vers un nombre, si possible.
        var b: Byte = java.lang.Byte.parseByte(s)
        var sh: Short = java.lang.Short.parseShort(s)
        var i: Int = java.lang.Integer.parseInt(s)
        var l: Long = java.lang.Long.parseLong(s)
        var f: Float = java.lang.Float.parseFloat(s)
        var d: Double = java.lang.Double.parseDouble(s)

        //valeur exacte
        val f_exac = java.lang.Float.valueOf(s)
        val d_exac = java.lang.Double.valueOf(s)

        //les routines de conversions entière gérent
        //les nombres dans diverses bases.
        //1011 en binare est égal a 11 en base dix
        b = java.lang.Byte.parseByte(&amp;quot;1011&amp;quot;, 2)
        assertEquals(11, b)
        //ff en base 16(hexa) est égal à 255 en base dix.
        sh = java.lang.Short.parseShort(&amp;quot;ff&amp;quot;, 16)
        assertEquals(255, sh)

        //la méthode valueOf() peut gérer des bases arbitraires.
        i = java.lang.Integer.valueOf(&amp;quot;egg&amp;quot;, 17).toInt()
        assertEquals(4334, i)

        //la méthode decode() gére les representations octale,
        //décimal, hexadécimal, en fonction du préfixe numérique
        //de la chaine de caractères
        //un 0 de tete signifie base 8
        //un 0x de tete signifie base 16
        //les autres sont en base 10
        val sho = java.lang.Short.decode(&amp;quot;0377&amp;quot;)

        //la classe Integer peut convertir les nombres
        //en diverses chaines de caractères.
        val decimal = java.lang.Integer.toString(42)
        assertEquals(&amp;quot;42&amp;quot;, decimal)

        val decimal_ = 42.toString()
        assertEquals(&amp;quot;42&amp;quot;, decimal_)

        val binary = java.lang.Integer.toBinaryString(42)
        assertEquals(&amp;quot;101010&amp;quot;, binary)

        val octal = java.lang.Integer.toOctalString(42)
        assertEquals(&amp;quot;52&amp;quot;, octal)

        val hex = java.lang.Integer.toHexString(42)
        assertEquals(&amp;quot;2a&amp;quot;, hex)

        val base36 = java.lang.Integer.toString(42, 36)
        assertEquals(&amp;quot;16&amp;quot;, base36)

        val base36_ = 42.toString(36)
        assertEquals(&amp;quot;16&amp;quot;, base36_)

        //java.text.NumberFormat effectue la conversion
        // d&amp;#39;une maniere spécifique aux parametres locaux
        //sans parametre prend la local systeme comme reference
        val nf = NumberFormat.getNumberInstance(Locale.FRANCE)
        val formatted_number = nf.format(9876543.21)
        assertNotEquals(&amp;quot;9876543.21&amp;quot;, formatted_number)

        //parse la chaine de caractères en fonction des parametres locaux(fr)
        val n = nf.parse(&amp;quot;1234567,89&amp;quot;)
        assertEquals(1234567.89, n)

        //les valeurs monétaires sont parfois formaté
        // d&amp;#39;une maniere differente des nombres
        val money_format = NumberFormat.getCurrencyInstance(Locale.FRANCE)
        assertEquals(&amp;quot;123,40 €&amp;quot;, money_format.format(1234.56))

        //java.lang.Math
        d = Math.toRadians(27.0)
        d = Math.cos(d)
        d = Math.sqrt(d)
        d = Math.log(d)
        d = Math.exp(d)
        d = Math.pow(10.0, d)
        d = Math.atan(d)
        d = Math.toDegrees(d)
        //arrondi au dessus
        val up = Math.ceil(d)
        //arrondi au dessous
        val down = Math.floor(d)
        //arrondi au plus près
        val nearest = Math.round(d)

        //java.lang.Math.Random()
        val r = Math.random()
        assertTrue(r &amp;amp;gt;= 0.0 &amp;amp;amp;&amp;amp;amp; r &amp;amp;lt; 1.0)

        //créé un nouvel objet Random, en l&amp;#39;initialisant
        //avec l&amp;#39;heure courante
        val generator = java.util.Random(System.currentTimeMillis())

        //prochaine valeur aléatoire de taille double
        d = generator.nextDouble()
        assertTrue((d &amp;amp;gt;= 0.0) &amp;amp;amp;&amp;amp;amp; (d &amp;amp;lt; 1.0))


        //prochaine valeur aléatoire de taille float
        f = generator.nextFloat()
        assertTrue((f &amp;amp;gt;= 0.0) &amp;amp;amp;&amp;amp;amp; (f &amp;amp;lt; 1.0))


        //prochaine valeur aléatoire de taille long
        l = generator.nextLong()
        assertTrue(
            (Math.abs(l) &amp;amp;lt;= Long.MAX_VALUE) &amp;amp;amp;&amp;amp;amp;
                    (Math.abs(l) &amp;amp;gt;= 0)
        )


        //prochaine valeur aléatoire de taille int
        i = generator.nextInt()
        assertTrue(
            (Math.abs(i) &amp;amp;lt;= java.lang.Integer.MAX_VALUE) &amp;amp;amp;&amp;amp;amp;
                    (Math.abs(i) &amp;amp;gt;= 0)
        )

        val limit = 100
        //prochaine valeur aléatoire de taille int
        //la limit max du ramdom est ramené à limit
        //et la limit min est 0
        i = generator.nextInt(limit)
        assertTrue(i in 0 until limit)


        //prochaine valeur aléatoire de taille booléen
        val bool = generator.nextBoolean()
        assertNotNull(bool)


        //valeur moyenne 0.0, déviation standard 1.0
        d = generator.nextGaussian()


        //randoms bytes
        //rempli un tableau avec des valeurs byte aléatoires
        val b_arr = ByteArray(128)
        generator.nextBytes(b_arr)
        b_arr.iterator().forEachRemaining {
            assertTrue(
                it &amp;amp;lt;= Byte.MAX_VALUE &amp;amp;amp;&amp;amp;amp;
                        it &amp;amp;gt;= Byte.MIN_VALUE
            )
        }

        //java.security.SecureRandom pour les nombres aléatoires
        //utilisé en cryptographie
        val secure_generator = SecureRandom()
        //le générateur génère sa propre tete de liste sur 16 octets
        secure_generator.setSeed(secure_generator.generateSeed(16))
        val sec_b_arr = ByteArray(128)
        secure_generator.nextBytes(sec_b_arr)
        sec_b_arr.iterator().forEachRemaining {
            assertTrue(
                it &amp;amp;lt;= java.lang.Byte.MAX_VALUE &amp;amp;amp;&amp;amp;amp;
                        it &amp;amp;gt;= java.lang.Byte.MIN_VALUE
            )
        }

        //java.math.BigDecimal java.math.BigInteger
        //pour travailler sur des grandes valeurs.
        //calcule de la factorielle de 1000
        var total = BigInteger.valueOf(1)
        (2..1000).forEach {
            total = total.multiply(BigInteger.valueOf(it.toLong()))
        }
        assertTrue(total.toString().length == 2568)
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc&amp;quot;&amp;gt;सामग्री की तालिका&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;date&amp;quot;&amp;gt;तारीखें और समय&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;import java.text.DateFormat
import java.text.SimpleDateFormat
import java.time.Instant
import java.util.*
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class DatesHoursTest {
    @Test
    fun `Dates et heures`() {
        //l&amp;#39;heure courante en millisecondes
        val t0 = System.currentTimeMillis()
        //une autre représentation de la meme information
        val now = java.util.Date()
        //converti un objet java.util.Date en une valeur long.
        val t1 = now.getTime()
        assertTrue(t1 &amp;amp;gt; Instant.EPOCH.toEpochMilli())
        //kotlin property access syntaxe style
        val t1_prime = now.time

        //java.text.DateFormat
        //affiche la date d&amp;#39;aujourd&amp;#39;hui en utilisant le format
        //par défaut des parametres locaux
        val defaultDateFormat = DateFormat.getDateInstance()
        //personnalisation du formatage et de la locale
        val df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE)
        val localeFormattedDate = df.format(Date())

        //constantes pour les styles de pattern de formatage
        assertEquals(0, DateFormat.FULL)
        assertEquals(1, DateFormat.LONG)
        assertEquals(2, DateFormat.MEDIUM)
        assertEquals(3, DateFormat.SHORT)
        assertEquals(2, DateFormat.DEFAULT)

        //utilise pour l&amp;#39;heure un format abrégé avec
        //des parametres personnalisés
        val tf = DateFormat.getTimeInstance(
            DateFormat.SHORT,
            Locale.FRANCE
        )
        //affiche l&amp;#39;heure en utilisant le format de tf
        val shortTime = tf.format(Date())
        assertTrue(shortTime.contains(&amp;#39;:&amp;#39;))

        //affiche la date et l&amp;#39;heure en utilisant
        //un format détaillé
        val longTimeStamp = DateFormat.getDateTimeInstance(
            DateFormat.FULL,
            DateFormat.FULL,
        )
        assert(longTimeStamp.format(Date()).isNotEmpty())

        //utilisez java.text.SimpleDateFormat
        //pour définir votre propre modele de formatage
        val customFormat = SimpleDateFormat(&amp;quot;yyyy.MM.dd&amp;quot;)
        assertEquals(10, customFormat.format(Date()).length)

        //DateFormat peut également parser les date contenu dans des chaines
        val kotlinAnnounceDate = customFormat.parse(&amp;quot;2019.05.08&amp;quot;)

        //la class Date et sa représentation en millisecondes
        //n&amp;#39;autorise qu&amp;#39;une forme trés simple d&amp;#39;arithmétique
        //on ajoute 3 600 000 millisecondes à l&amp;#39;heure courante
        val anHourFromNow = now.getTime() + (60 * 60 * 1000)
        assert(anHourFromNow &amp;amp;gt; now.getTime())

        //java.util.Calendar
        //pour manipuler les dates et heures de facon plus sophistiquée
        //instanciation selon les parametres locaux
        //et le fuseau horaire local
        val calendar = Calendar.getInstance()
        //initialisation du calendrier à la date de maintenant
        calendar.setTime(now)
        //détermine le jour de l&amp;#39;année auquel correspond la date courante
        val dayOfYear = calendar.get(Calendar.DAY_OF_YEAR)
        assert(dayOfYear &amp;amp;lt; 366)
        //réinitialisation de la date courante
        calendar.set(2019, Calendar.MAY, 8)
        assertEquals(4, calendar.get(Calendar.DAY_OF_WEEK))

        //à quel jour du mois correspond le deuxieme mercredi de mai 2019
        //set(key,value)
        calendar.set(Calendar.YEAR, 2019)
        calendar.set(Calendar.MONTH, Calendar.MAY)
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY)
        //defini à quel (n=2) semaine du mois est la date
        calendar.set(Calendar.DAY_OF_WEEK_IN_MONTH, 2)
        //extrait le jour du mois
        val dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH)
        assertEquals(8, dayOfMonth)

        calendar.setTime(kotlinAnnounceDate)
        //ajoute 30j à la date
        calendar.add(Calendar.DATE, 30)
        val monthAfter = calendar.getTime()
        //date est elle avant ou apres?
        assertTrue(monthAfter.after(kotlinAnnounceDate))
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc&amp;quot;&amp;gt;सामग्री की तालिका&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;java8date&amp;quot;&amp;gt;तारीखें और समय java8&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;Java 8 नया पैकेज &amp;lt;strong&amp;gt;&amp;lt;em&amp;gt;java.time&amp;lt;/em&amp;gt;&amp;lt;/strong&amp;gt; पेश करता है, जिसमें मूल वर्ग होते हैं जो&amp;lt;br&amp;gt;
अधिकांश डेवलपर्स काम करते हैं। इसमें चार उप‑पैकेज भी हैं:&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;em&amp;gt;java.time.chrono&amp;lt;/em&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;br&amp;gt;
वैकल्पिक कालक्रम कि डेवलपर्स कैलेंडर प्रणालियों का उपयोग करते हैं जो नहीं&amp;lt;br&amp;gt;
ISO मानक का पालन करने से यह इंटरैक्ट करेगा। एक उदाहरण एक जापानी गोभी होगा&amp;lt;br&amp;gt;
सहनशील प्रणाली।&amp;lt;br&amp;gt;
&amp;lt;strong&amp;gt;&amp;lt;em&amp;gt;java.time.format&amp;lt;/em&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;br&amp;gt;
इसमें दिनांक और समय ऑब्जेक्ट्स को बदलने के लिए उपयोग किया जाने वाला DateTimeFormatter निहित है&amp;lt;br&amp;gt;
एक स्ट्रिंग में और साथ ही डेटा और समय ऑब्जेक्ट्स में स्ट्रिंग को पार्स करने के लिए भी।&amp;lt;br&amp;gt;
&amp;lt;strong&amp;gt;&amp;lt;em&amp;gt;java.time.temporal&amp;lt;/em&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;br&amp;gt;
बेसिक दिनांक और समय क्लास के लिए आवश्यक इंटरफ़ेस रखता है और साथ ही&amp;lt;br&amp;gt;
अभिकल्पनाएँ (जैसे कि क्वेरीज़ और समायोजक) उन्नत तिथि संचालन के लिए।&amp;lt;br&amp;gt;
&amp;lt;strong&amp;gt;&amp;lt;em&amp;gt;java.time.zone&amp;lt;/em&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;br&amp;gt;
आधारित समय क्षेत्र नियमों के लिए उपयोग की जाने वाली कक्षाएँ;&amp;lt;br&amp;gt;
अधिकांश डेवलपर्स को इस पैकेज की आवश्यकता नहीं होगी।&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;../../img/java8-date-time.png&amp;quot; alt=&amp;quot;java8 date time&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;import java.time.LocalDate
import java.time.Month
import java.time.Period
import java.time.YearMonth
import java.time.temporal.*
import java.util.HashMap
import java.util.stream.Collectors
import kotlin.test.Test

class DatesHoursJava8Test {
    class BirthdayDiary {
        private val birthdays: MutableMap&amp;amp;lt;String, LocalDate&amp;amp;gt;

        init {
            birthdays = HashMap()
        }

        fun addBirthday(
            name: String, day: Int, month: Int,
            year: Int
        ): LocalDate {
            val birthday: LocalDate = LocalDate.of(year, month, day)
            birthdays[name] = birthday
            return birthday
        }

        fun getBirthdayFor(name: String): LocalDate? {
            return birthdays[name]
        }

        fun getAgeInYear(name: String, year: Int): Int {
            val period: Period = Period.between(
                birthdays[name],
                birthdays[name]!!.withYear(year)
            )
            return period.getYears()
        }

        fun getFriendsOfAgeIn(age: Int, year: Int): Set&amp;amp;lt;String&amp;amp;gt; {
            return birthdays.keys.stream()
                .filter { p: String -&amp;amp;gt; getAgeInYear(p, year) == age }
                .collect(Collectors.toSet())
        }

        fun getDaysUntilBirthday(name: String): Int {
            val period: Period = Period.between(
                LocalDate.now(),
                birthdays[name]
            )
            return period.getDays()
        }

        fun getBirthdaysIn(month: Month): Set&amp;amp;lt;String&amp;amp;gt; {
            return birthdays.entries.stream()
                .filter { (_, value): Map.Entry&amp;amp;lt;String, LocalDate&amp;amp;gt; -&amp;amp;gt; value.getMonth() === month }
                .map&amp;amp;lt;String&amp;amp;gt; { (key): Map.Entry&amp;amp;lt;String, LocalDate&amp;amp;gt; -&amp;amp;gt; key }
                .collect(Collectors.toSet())
        }

        val birthdaysInCurrentMonth: Set&amp;amp;lt;String&amp;amp;gt;
            get() = getBirthdaysIn(LocalDate.now().getMonth())
        val totalAgeInYears: Int
            get() = birthdays.keys.stream()
                .mapToInt { p: String -&amp;amp;gt;
                    getAgeInYear(
                        p,
                        LocalDate.now().getYear()
                    )
                }
                .sum()
    }

    //Les ajusteurs modifient les objets de date et d&amp;#39;heure. Supposons, par exemple, que nous voulions
    //renvoie le premier jour d&amp;#39;un trimestre qui contient un horodatage particulier :
    class FirstDayOfQuarter : TemporalAdjuster {
        override fun adjustInto(temporal: Temporal): Temporal? {
            val currentQuarter: Int = YearMonth.from(temporal)
                .get(IsoFields.QUARTER_OF_YEAR)
            return when (currentQuarter) {
                1 -&amp;amp;gt; LocalDate.from(temporal)
                    .with(TemporalAdjusters.firstDayOfYear())

                2 -&amp;amp;gt; LocalDate.from(temporal)
                    .withMonth(Month.APRIL.value)
                    .with(TemporalAdjusters.firstDayOfMonth())

                3 -&amp;amp;gt; LocalDate.from(temporal)
                    .withMonth(Month.JULY.value)
                    .with(TemporalAdjusters.firstDayOfMonth())

                4 -&amp;amp;gt; LocalDate.from(temporal)
                    .withMonth(Month.OCTOBER.value)
                    .with(TemporalAdjusters.firstDayOfMonth())

                else -&amp;amp;gt; null
            }
        }
    }

    enum class Quarter {
        FIRST, SECOND, THIRD, FOURTH
    }

    //Dans quel trimestre de l&amp;#39;année cette date se situe-t-elle ?
    class QuarterOfYearQuery : TemporalQuery&amp;amp;lt;Quarter&amp;amp;gt; {
        override fun queryFrom(temporal: TemporalAccessor): Quarter {
            val now = LocalDate.from(temporal)
            return if (now.isBefore(now.with(Month.APRIL).withDayOfMonth(1)))
                Quarter.FIRST
            else if (now.isBefore(
                    now.with(Month.JULY)
                        .withDayOfMonth(1)
                )
            ) Quarter.SECOND else if (now.isBefore(
                    now.with(Month.NOVEMBER)
                        .withDayOfMonth(1)
                )
            ) Quarter.THIRD else Quarter.FOURTH
        }
    }

    @Test
    fun `Dates et heures après java 8`() {
        val today = LocalDate.now()
        val currentMonth = today.month
        val firstMonthOfQuarter = currentMonth.firstMonthOfQuarter()

        val q = QuarterOfYearQuery()
        // Direct
        var quarter: Quarter? = q.queryFrom(LocalDate.now())
        println(quarter)
        // Indirect
        quarter = LocalDate.now().query(q)
        println(quarter)


        val now = LocalDate.now()
        val fdoq: Temporal = now.with(FirstDayOfQuarter())
        println(fdoq)
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc&amp;quot;&amp;gt;सामग्री की तालिका&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;arrCol&amp;quot;&amp;gt;सरणी और संग्रह&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;../../img/collections_classes_inheritance.png&amp;quot; alt=&amp;quot;Classes de collections et héritage&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;package playground.programming

import java.util.*
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue

class ArrayCollectionTest {
    @Test
    fun `Tableaux, collections`() {
        //Tableau
        //java.util.Arrays définit d&amp;#39;utiles méthodes de manipulation de tableaux,
        //y compris de tri et de recherche au sein d&amp;#39;un tableau
        val intArray = arrayOf(10, 5, 7, -3)
        //tri le tableau
        Arrays.sort(intArray)
        var pos = Arrays.binarySearch(intArray, 7)
        //la valeur 7 est trouvé a l&amp;#39;index 2
        assertEquals(2, pos)
        //12 pas trouvé retourne une valeur negative
        assert(Arrays.binarySearch(intArray, 12) &amp;amp;lt; 0)

        //les tableaux peuvent également etre triés
        //et faire l&amp;#39;objet d&amp;#39;une recherche
        val stringArray = arrayOf(&amp;quot;le&amp;quot;, &amp;quot;moment&amp;quot;, &amp;quot;c&amp;#39;est&amp;quot;)
        assertEquals(&amp;quot;c&amp;#39;est&amp;quot;, stringArray[2])
        assertEquals(&amp;quot;le&amp;quot;, stringArray[0])
        assertEquals(&amp;quot;moment&amp;quot;, stringArray[1])
        Arrays.sort(stringArray)
        assertEquals(&amp;quot;c&amp;#39;est&amp;quot;, stringArray[0])
        assertEquals(&amp;quot;le&amp;quot;, stringArray[1])
        assertEquals(&amp;quot;moment&amp;quot;, stringArray[2])

        //Arrays.equals() compare tous les éléments de deux tableaux
        //Arrays.clone() copie tous les elements du tableau dans un autre
        stringArray.forEachIndexed { i, it -&amp;amp;gt; assertEquals(it, stringArray.clone()[i]) }

        val data = ByteArray(100)
        //Arrays.fill() initialise tous les éléments des deux tableaux
        //initalise tous les éléments à -1
        Arrays.fill(data, -1)
        data.forEach { assertEquals(-1, it) }

        //attribue aux éléments 5, 6, 7, 8 et 9 la valeur -2
        Arrays.fill(data, 5, 10, -2)
        ((5 until (10 - 1))).forEach { assertEquals(-2, data[it]) }

        //récupère le type de data
        val type = data::class.java
        //est ce que data est un tableau?
        assertTrue(type.isArray())
        //est ce que data est un tableau de byte
        assertEquals(Byte::class.java, type.getComponentType())

        //Collection
        val s = java.util.HashSet&amp;amp;lt;String&amp;amp;gt;()
        s.add(&amp;quot;test&amp;quot;)
        assertTrue(s.contains(&amp;quot;test&amp;quot;))
        assertFalse(s.contains(&amp;quot;test2&amp;quot;))
        s.remove(&amp;quot;test&amp;quot;)
        assertFalse(s.contains(&amp;quot;test&amp;quot;))

        val ss = TreeSet&amp;amp;lt;String&amp;amp;gt;()
        ss.add(&amp;quot;b&amp;quot;)
        ss.add(&amp;quot;a&amp;quot;)
        ss.iterator().forEach { assertTrue(it == &amp;quot;a&amp;quot; || it == &amp;quot;b&amp;quot;) }

        //liste doublement chainée
        var dll: List&amp;amp;lt;String&amp;amp;gt; = LinkedList&amp;amp;lt;String&amp;amp;gt;()

        //plus efficace
        val l = java.util.ArrayList&amp;amp;lt;String&amp;amp;gt;()
        l.addAll(ss)
        l.addAll(1, ss)

        val obj = l.get(1)
        val obj_prime = l[1]
        assertEquals(obj, obj_prime)

        l.set(3, &amp;quot;nouvel élément&amp;quot;)
        l.add(&amp;quot;test&amp;quot;)
        l.add(0, &amp;quot;test2&amp;quot;)
        l.removeAt(1)
        l.remove(&amp;quot;a&amp;quot;)
        assertFalse(l.contains(&amp;quot;a&amp;quot;))
        l.removeAll(ss)
        assertFalse(l.containsAll(ss))
        assertFalse(l.isEmpty())
        assertTrue(l.isNotEmpty())


        val sublist = l.subList(1, 3)
        val elements = l.toArray()
        l.clear()

        val m = HashMap&amp;amp;lt;String, Integer&amp;amp;gt;()
        m.put(&amp;quot;clé&amp;quot;, Integer(42))
        m[&amp;quot;clé&amp;quot;] = Integer(42)
        val value: Integer = m.get(&amp;quot;clé&amp;quot;)!!
        assertEquals(Integer(42), value)
        m.remove(&amp;quot;clé&amp;quot;)
        assertTrue(m.isEmpty())
        val keys = m.keys
        assertTrue(keys.isEmpty())


        val set = HashSet&amp;amp;lt;String&amp;amp;gt;()
        set.add(&amp;quot;key_1&amp;quot;)
        set.add(&amp;quot;key_2&amp;quot;)
        set.add(&amp;quot;key_3&amp;quot;)
        val members = set.toArray()
        assertEquals(3, members.size)
        val list = ArrayList&amp;amp;lt;String&amp;amp;gt;()
        list.add(&amp;quot;items1&amp;quot;)
        list.add(&amp;quot;items2&amp;quot;)
        list.add(&amp;quot;items3&amp;quot;)
        val items = list.toArray()
        assertEquals(3, items.size)

        //trie et recherche d&amp;#39;éléments sur les collections
        list.add(&amp;quot;clé&amp;quot;)
        //en premier on trie
        Collections.sort(list)
        //en kotlin
        list.sort()
        //en deuxieme on cherche
        //retourne l&amp;#39;index du premier trouvé sinon -1
        pos = Collections.binarySearch(list, &amp;quot;clé&amp;quot;)
        assertEquals(0, pos)
        val list1 = mutableListOf(1, 2, 3, 4, 5)
        val list2 = mutableListOf&amp;amp;lt;Int&amp;amp;gt;(0, 0, 0, 0, 0)

        //d&amp;#39;autres méthodes intéressantes concernant Collections

        //copie list1 dans list2, 2e parametre dans 1er parametre
        Collections.copy(list2, list1)
        //comparaison de la copy avec filter
        assertTrue(list1.filterIndexed { i: Int, it: Int -&amp;amp;gt; it != list2[i] }.isEmpty())
        //comparaison de la copy avec map
        list1.mapIndexed { index: Int, it: Int -&amp;amp;gt; assertEquals(it, list2[index]) }

        //rempli avec des 0
        Collections.fill(list2, 0)
        assertTrue(list2.none { it != 0 })

        //le maximum
        assertEquals(5, Collections.max(list1))

        //le minimum
        assertEquals(1, Collections.min(list1))

        //renverse
        Collections.reverse(list)
        listOf(&amp;quot;items3&amp;quot;, &amp;quot;items2&amp;quot;, &amp;quot;items1&amp;quot;, &amp;quot;clé&amp;quot;).mapIndexed { i: Int, it: String -&amp;amp;gt; assertEquals(it, list[i]) }

        //mélange la list
        Collections.shuffle(list)

        //retourne un ensemble immuable possédant un seul élément 0
        Collections.singleton(0)
        //renvoi un emballage immuable autour d&amp;#39;une liste
        Collections.unmodifiableList(list)
        //renvoi un emballage synchronisé autour d&amp;#39;une map, ensemble clé valeur
        Collections.synchronizedMap(m)

        //java.util.Properties un est objet key value
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc&amp;quot;&amp;gt;सामग्री की तालिका&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;sysProp&amp;quot;&amp;gt;System.Properties&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html&amp;quot;&amp;gt;System.Properties आधिकारिक दस्तावेज़&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ कुछ दिलचस्प संपत्तियों की एक तालिका है।&amp;lt;br&amp;gt;
ये गुण जानकारी प्राप्त करने के लिए दिलचस्प हैं&amp;lt;br&amp;gt;
JVM के होस्ट सिस्टम पर.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3333%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 3.3343%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;कुंजी&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;अर्थ&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;फ़ाइल सेपरेटर&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;फ़ाइल पथ के घटकों को अलग करने वाला अक्षर। यह यूनिक्स पर &amp;quot;/&amp;quot; और विंडोज़ पर &amp;quot;\&amp;quot; है।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;java.class.path&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;क्लास फ़ाइलें रखने वाली निर्देशिकाओं और JAR अभिलेखों को खोजने में प्रयुक्त पथ। क्लास पथ के तत्व, path.separator गुण द्वारा निर्दिष्ट प्लेटफ़ॉर्म-विशिष्ट अक्षर से अलग किए जाते हैं।&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;java.home&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;जावा रनटाइम एनवायरनमेंट (JRE) की इंस्टॉलेशन डायरेक्टरी&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;java.vendor&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;JRE विक्रेता नाम&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;java.vendor.url&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;JRE विक्रेता URL&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;java.संस्करण&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;JRE version number&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;लाइन.सेपरेटर&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;ऑपरेटिंग सिस्टम द्वारा टेक्स्ट फ़ाइलों में लाइनों को अलग करने के लिए उपयोग किया जाने वाला अनुक्रम&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;os.arch&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;ऑपरेटिंग सिस्टम आर्किटेक्चर&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;os.name&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;�ऑपरेटिंग सिस्टम का नाम&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;os.version&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;�ऑपरेटिंग सिस्टम संस्करण&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;पथ.विभाजक&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;java.class.path में उपयोग किया जाने वाला पथ सेपरेटर अक्षर&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;user.dir&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;User working directory&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;user.home&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;उपयोगकर्ता होम निर्देशिका&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;user.name&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;उपयोगकर्ता खाता नाम&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc&amp;quot;&amp;gt;सामग्री की तालिका&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;threads&amp;quot;&amp;gt;Threads&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;import java.text.DateFormat
import java.util.*
import kotlin.test.Test

class ThreadsTest {

    @Test
    fun `threads test`() {
        //java.lang.Thread représente le thread fondamentale de l&amp;#39;API java
        //il existe deux manière de définir un thread
        //1) étendre la classe Thread ou une lambda en kotlin
        //2) implémenter l&amp;#39;interface Runnable,
        //      puis passer une instance de cet objet Runnable au constructeur de Thread.

        val list1: List&amp;amp;lt;Int&amp;amp;gt; = List(
            size = 45,
            init = { (1..31).random() }
        )
        println(&amp;quot;list1$list1&amp;quot;)
        //facon 1
        val t = Thread {
            Collections.sort(list1)
            println(&amp;quot;list1 sorted$list1&amp;quot;)
        }
        t.start()

        val list2 = List(
            size = 45,
            init = { (1..31).random() }
        )
        println(&amp;quot;list2$list2&amp;quot;)
        //facon 2
        val sorter = BackgroundSorter(list2)
        sorter.start()

        //priorité des threads
        //tant qu&amp;#39;un thread de niveau de priorité supérieure n&amp;#39;est pas fini
        //alors celui de niveau inférieur ne peut s&amp;#39;exécuter

        //on définit un thread avec une priorité inférieur à la normale
        t.setPriority(Thread.NORM_PRIORITY - 1)

        //ici on définit un thread avec une priorité inférieur à la priorité
        //du thread courant
        t.setPriority(Thread.currentThread().getPriority() - 1)

        //Thread.yield() fait une pause pour laisser les autres threads de meme priorité s&amp;#39;exécuter
    }

    class BackgroundSorter(private val l: List&amp;amp;lt;Int&amp;amp;gt;) : Thread() {
        override fun run() {
            Collections.sort(l)
            println(&amp;quot;list2 sorted$l&amp;quot;)
        }
    }

    //pour l&amp;#39;arrêt du thread, plutôt qu&amp;#39;utiliser la fonction Thread.stop()
    // qui laisse la memoire dans un état non controlé.
    //utiliser la méthode tel que l&amp;#39;exemple pleaseStop()
    class DummyClock(
        private val df: DateFormat = DateFormat.getTimeInstance(DateFormat.MEDIUM),
        private var keepRunning: Boolean = true
    ) : Thread() {
        init {
            isDaemon = true
            start()
        }

        override fun run() {
            while (keepRunning) {
                println(df.format(Date()))
                try {
                    sleep(1000)
                } catch (e: InterruptedException) {
                    println(e.message)
                }
            }
        }

        fun pleaseStop() {
            keepRunning = false
        }
    }

    //java.util.Timer
    //java.util.TimerTask
    //ces classes permettent l&amp;#39;exécution de taches répétitives
    @Test
    fun `Timer et TimerTask test`() {
        DummyClock()
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;#toc&amp;quot;&amp;gt;सामग्री की तालिका&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;regex&amp;quot;&amp;gt;नियमित अभिव्यक्तियाँ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;import java.util.*
import java.util.regex.Matcher
import java.util.regex.Pattern
import java.util.stream.Collectors
import kotlin.test.Test
import kotlin.test.assertEquals

class RegularExpressionsTest {
    @Test
    fun `expressions régulières`() {
        val p: Pattern = Pattern.compile(&amp;quot;honou?r&amp;quot;)
        val caesarUK = &amp;quot;For Brutus is an honourable man&amp;quot;
        val mUK: Matcher = p.matcher(caesarUK)
        assertEquals(true, mUK.find(), &amp;quot;Should matches UK spelling&amp;quot;)
        val caesarUS = &amp;quot;For Brutus is an honorable man&amp;quot;
        val mUS: Matcher = p.matcher(caesarUS)
        assertEquals(true, mUS.find(), &amp;quot;Should matches US spelling&amp;quot;)
    }

    @Test
    fun `expressions régulières plus complexes`() {
        //Notez que nous devons utiliser \\ car nous avons besoin d&amp;#39;un littéral \
        //et Java utilise un seul \ comme caractère d&amp;#39;échappement
        var pStr = &amp;quot;\\d&amp;quot; // Un chiffre numérique

        var text = &amp;quot;Apollo 13&amp;quot;
        var p = Pattern.compile(pStr)
        var m = p.matcher(text)
        print(pStr + &amp;quot; matches &amp;quot; + text + &amp;quot;? &amp;quot; + m.find())
        println(&amp;quot; ; match: &amp;quot; + m.group())
        pStr = &amp;quot;[a..zA..Z]&amp;quot; //N&amp;#39;importe quelle lettre

        p = Pattern.compile(pStr)
        m = p.matcher(text)
        print(pStr + &amp;quot; matches &amp;quot; + text + &amp;quot;? &amp;quot; + m.find())
        println(&amp;quot; ; match: &amp;quot; + m.group())

        //N&amp;#39;importe quel nombre de lettres, qui doivent toutes être comprises entre &amp;#39;a&amp;#39; et &amp;#39;j&amp;#39;
        //mais peut-être en majuscule ou en minuscule.
        pStr = &amp;quot;([a..jA..J]*)&amp;quot;
        p = Pattern.compile(pStr)
        m = p.matcher(text)
        print(pStr + &amp;quot; matches &amp;quot; + text + &amp;quot;? &amp;quot; + m.find())
        println(&amp;quot; ; match: &amp;quot; + m.group())
        text = &amp;quot;abacab&amp;quot;
        //&amp;#39;a&amp;#39; suivi de quatre caractères quelconques, suivi de &amp;#39;b&amp;#39;
        pStr = &amp;quot;a....b&amp;quot;
        p = Pattern.compile(pStr)
        m = p.matcher(text)
        print(pStr + &amp;quot; matches &amp;quot; + text + &amp;quot;? &amp;quot; + m.find())
        println(&amp;quot; ; match: &amp;quot; + m.group())
    }

    @Test
    fun `Quelles chaînes correspondent à la regex ?`() {
        val pStr = &amp;quot;\\d&amp;quot; // Un chiffre numérique
        val p = Pattern.compile(pStr)
        val ls: List&amp;amp;lt;String&amp;amp;gt; = Arrays.asList(&amp;quot;Cat&amp;quot;, &amp;quot;Dog&amp;quot;, &amp;quot;Ice-9&amp;quot;, &amp;quot;99 Luftballoons&amp;quot;)
        val containDigits: List&amp;amp;lt;String&amp;amp;gt; = ls.stream()
            .filter(p.asPredicate())
            .collect(Collectors.toList())
        assert(containDigits.contains(&amp;quot;Ice-9&amp;quot;))
        assert(containDigits.contains(&amp;quot;99 Luftballoons&amp;quot;))
        assertEquals(2, containDigits.size)
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_तालिका_regex_मेटा_अक्षर&amp;quot;&amp;gt;तालिका regex मेटा अक्षर&amp;lt;/h3&amp;gt;
&amp;lt;table class=&amp;quot;tableblock frame-all grid-all stretch&amp;quot;&amp;gt;
&amp;lt;colgroup&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7543%;&amp;quot;&amp;gt;
&amp;lt;col style=&amp;quot;width: 1.7592%;&amp;quot;&amp;gt;
&amp;lt;/colgroup&amp;gt;
&amp;lt;tbody&amp;gt;
&amp;lt;tr&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;मेटा अक्षर&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;कार्यक्षमता&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;नोट्स&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;?&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;वैकल्पिक वर्ण—शून्य या एक उदाहरण&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;*&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;पिछले अक्षर का शून्य या अधिक&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;(No output)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक या अधिक पिछले अक्षर&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;{M,N}&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;M और N उदाहरणों के बीच पिछला अक्षर&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\d&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक अंक&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\D&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक गैर‑संख्यात्मक अक्षर&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\w&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक शब्द का अक्षर&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;अंक, अक्षर और _&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\W&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक अक्षर बिना शब्द&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\s&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक अंतराल अक्षर&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\S&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक गैर-रिक्त स्थान अक्षर&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\n&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;नई पंक्ति का वर्ण&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;\t&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;टैब अक्षर&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;.&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;कोई भी अक्षर&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;N&amp;amp;#8217;inclut pas la nouvelle ligne en Java&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;[ ]&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;वर्गाकार कोष्ठक के बीच में निहित कोई भी अक्षर&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक अक्षर वर्ग कहा गया&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;[^ ]&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;कोष्ठक के भीतर नहीं आने वाला कोई भी अक्षर&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक उलटे अक्षर वर्ग को कहा गया&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;( )&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;पैटर्न तत्वों का समूह बनाना&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;एक समूह (या कैप्चर समूह)&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;|&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;वैकल्पिक संभावनाएँ परिभाषित करें&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;लॉजिकल OR लागू करें&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;^&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;p class=&amp;quot;tableblock&amp;quot;&amp;gt;स्ट्रिंग की शुरुआत $ स्ट्रिंग का अंत&amp;lt;/p&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;td class=&amp;quot;tableblock halign-left valign-top&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;पूरा करनाhttps://www.codeurjava.com/2015/05/les-expressions-regulieres-avec-regex.html[के साथ]&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>ग्रैडल नोट</title>
            <link >https://cheroliv.com/blog/2022/0047_memo_gradle_post.html</link>
            <pubDate>Mon, 23 May 2022 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2022/0047_memo_gradle_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;toc&amp;quot; class=&amp;quot;toc&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;toctitle&amp;quot;&amp;gt;Sommaire&amp;lt;/div&amp;gt;
&amp;lt;ul class=&amp;quot;sectlevel1&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_सहायता_दिखाएँ&amp;quot;&amp;gt;सहायता दिखाएँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_jvm_का_सिस्टम_प्रॉपर्टी_सेट_करें_d_system_prop&amp;quot;&amp;gt;JVM का सिस्टम प्रॉपर्टी सेट करें : `-D, --system-prop&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_परियोजना_की_संपत्ति_को_बिल्ड_स्क्रिप्ट_के_लिए_परिभाषित_करें_pmypropmyvalue&amp;quot;&amp;gt;परियोजना की संपत्ति को बिल्ड स्क्रिप्ट के लिए परिभाषित करें : `-Pmyprop=myvalue&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_gradle_की_स्टार्टअप_निर्देशिका_निर्दिष्ट_करता_है_डिफ़ॉल्ट_मान_वर्तमान_निर्देशिका_है&amp;quot;&amp;gt;Gradle की स्टार्टअप निर्देशिका निर्दिष्ट करता है। डिफ़ॉल्ट मान वर्तमान निर्देशिका है।&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_कमांड_लाइन_से_param_component_property_को_ओवरराइट_करें&amp;quot;&amp;gt;कमांड लाइन से &amp;#39;param_component&amp;#39; property को ओवरराइट करें :&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_kotlin_dsl_के_साथ_एक_सामान्य_प्रोज़क्ट_में_सोर्स_सेट_में_एक_फ़ोल्डर_जोड़ें&amp;quot;&amp;gt;Kotlin DSL के साथ एक सामान्य प्रोज़क्ट में सोर्स-सेट में एक फ़ोल्डर जोड़ें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_एंड्रॉइड_प्रोजेक्ट_में_स्रोत_सेट_में_ग्रोवी_dsl_के_माध्यम_से_फ़ोल्डर_जोड़ें&amp;quot;&amp;gt;एंड्रॉइड प्रोजेक्ट में स्रोत सेट में ग्रोवी DSL के माध्यम से फ़ोल्डर जोड़ें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_एक_सब_मॉड्यूल_का_निर्माण_और_परीक्षण_करने_से_बचें&amp;quot;&amp;gt;एक सब मॉड्यूल का निर्माण और परीक्षण करने से बचें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_tar_एक_फ़ोल्डर&amp;quot;&amp;gt;Tar एक फ़ोल्डर&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_एक_बिल्ड_की_निर्भरताएँ_दिखाएँ&amp;quot;&amp;gt;एक बिल्ड की निर्भरताएँ दिखाएँ&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_reduce_का_उपयोग_करने_का_उदाहरण_सूची_को_स्ट्रिंग_में_संयोजन&amp;quot;&amp;gt;reduce का उपयोग करने का उदाहरण: सूची को स्ट्रिंग में संयोजन&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_किसी_विशेष_कार्य_का_विवरण_प्राप्त_करें&amp;quot;&amp;gt;किसी विशेष कार्य का विवरण प्राप्त करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_workingdir_root_से_एक_कार्य_लॉन्च_करने_के_लिए_फिर_कार्य_को_से_प्रीफ़िक्स&amp;quot;&amp;gt;workingDir root से एक कार्य लॉन्च करने के लिए, फिर कार्य को &amp;lt;code&amp;gt;:&amp;lt;/code&amp;gt; से प्रीफ़िक्स&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_असफल_कार्यों_को_पुनः_चलाने_के_लिए_विकल्प_rerun_tasks_का_उपयोग_करें&amp;quot;&amp;gt;असफल कार्यों को पुनः चलाने के लिए, विकल्प &amp;lt;code&amp;gt;--rerun-tasks&amp;lt;/code&amp;gt; का उपयोग करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#_दूसरे_निर्देशिका_से_एक_विशिष्ट_प्रोजेक्ट_में_एक_टास्क_शुरू_करें&amp;quot;&amp;gt;दूसरे निर्देशिका से एक विशिष्ट प्रोजेक्ट में एक टास्क शुरू करें&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_सहायता_दिखाएँ&amp;quot;&amp;gt;सहायता दिखाएँ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;./gradlew --help&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_jvm_का_सिस्टम_प्रॉपर्टी_सेट_करें_d_system_prop&amp;quot;&amp;gt;JVM का सिस्टम प्रॉपर्टी सेट करें : `-D, --system-prop&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;./gradlew -Dmyprop=myvalue
#ou
./gradlew --system-prop myvalue&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_परियोजना_की_संपत्ति_को_बिल्ड_स्क्रिप्ट_के_लिए_परिभाषित_करें_pmypropmyvalue&amp;quot;&amp;gt;परियोजना की संपत्ति को बिल्ड स्क्रिप्ट के लिए परिभाषित करें : `-Pmyprop=myvalue&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;./gradlew -Pmyprop=myvalue
#ou
./gradlew --project-prop myvalue&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_gradle_की_स्टार्टअप_निर्देशिका_निर्दिष्ट_करता_है_डिफ़ॉल्ट_मान_वर्तमान_निर्देशिका_है&amp;quot;&amp;gt;Gradle की स्टार्टअप निर्देशिका निर्दिष्ट करता है। डिफ़ॉल्ट मान वर्तमान निर्देशिका है।&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;./gradlew -p ~/src/next_startup
#ou
./gradlew --project-dir ~/src/next_startup&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_कमांड_लाइन_से_param_component_property_को_ओवरराइट_करें&amp;quot;&amp;gt;कमांड लाइन से &amp;#39;param_component&amp;#39; property को ओवरराइट करें :&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;./gradlew -Pparam_component=CUSTOM_VALUE&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_kotlin_dsl_के_साथ_एक_सामान्य_प्रोज़क्ट_में_सोर्स_सेट_में_एक_फ़ोल्डर_जोड़ें&amp;quot;&amp;gt;Kotlin DSL के साथ एक सामान्य प्रोज़क्ट में सोर्स-सेट में एक फ़ोल्डर जोड़ें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;sourceSets {
    getByName(&amp;quot;test&amp;quot;){
        java.srcDir(&amp;quot;src/scripts/groovy&amp;quot;)
    }
    getByName(&amp;quot;test&amp;quot;){
        java.srcDir(&amp;quot;src/scripts/kscript&amp;quot;)
    }
    getByName(&amp;quot;test&amp;quot;){
        java.srcDir(&amp;quot;src/test/javascript&amp;quot;)
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_एंड्रॉइड_प्रोजेक्ट_में_स्रोत_सेट_में_ग्रोवी_dsl_के_माध्यम_से_फ़ोल्डर_जोड़ें&amp;quot;&amp;gt;एंड्रॉइड प्रोजेक्ट में स्रोत सेट में ग्रोवी DSL के माध्यम से फ़ोल्डर जोड़ें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;android {
    sourceSets {
        main.java.srcDirs += &amp;quot;src/main/../../../../ceelo/domain/src/main/java/&amp;quot;
        test.java.srcDirs += &amp;quot;src/test/../../../../ceelo/domain/src/test/java/&amp;quot;
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_एक_सब_मॉड्यूल_का_निर्माण_और_परीक्षण_करने_से_बचें&amp;quot;&amp;gt;एक सब मॉड्यूल का निर्माण और परीक्षण करने से बचें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;gradle build -x :excluded-module:check -x :excluded-module:assemble -x :excluded-module:build&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;फ़ाइलें ले जाना&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;tasks.register(&amp;quot;moveWebappNode&amp;quot;) {
    doLast {
        ant.withGroovyBuilder {
            &amp;quot;move&amp;quot;(
                &amp;quot;webapp/node_modules&amp;quot; to &amp;quot;$rootDir/webapp-src/node_modules&amp;quot;,
            )
        }
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_tar_एक_फ़ोल्डर&amp;quot;&amp;gt;Tar एक फ़ोल्डर&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;tasks.register&amp;amp;lt;Tar&amp;amp;gt;(&amp;quot;tarWebapp&amp;quot;) {
    dependsOn(&amp;quot;moveWebappNpm&amp;quot;)
    group = WEBAPP
    description = &amp;quot;tar webapp&amp;quot;
    doLast {
        setOf(
            &amp;quot;build&amp;quot;,
            &amp;quot;target&amp;quot;,
            &amp;quot;node_modules&amp;quot;
        ).forEach { dir -&amp;amp;gt; exclude { it.name .dir } }
        archiveFileName.set(&amp;quot;webapp.tar&amp;quot;)
        destinationDirectory.set(File(&amp;quot;${rootDir.absolutePath}$sep$WEBAPP_SRC&amp;quot;))
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_एक_बिल्ड_की_निर्भरताएँ_दिखाएँ&amp;quot;&amp;gt;एक बिल्ड की निर्भरताएँ दिखाएँ&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;tasks.register(&amp;quot;printDependencies&amp;quot;) {
    description = &amp;quot;print project dependencies&amp;quot;
    group = WEBAPP
    doLast {
        println(&amp;quot;${project.name} dependencies&amp;quot;)
        mutableMapOf&amp;amp;lt;String, Map&amp;amp;lt;String, String&amp;amp;gt;&amp;amp;gt;(
            &amp;quot;buildDependencies&amp;quot; to buildDependencies,
            &amp;quot;domainDeps&amp;quot; to domainDeps,
            &amp;quot;domainTestDeps&amp;quot; to domainTestDeps,
        ).apply { putAll(appModules) }
            .forEach { module -&amp;amp;gt;
                if (module.value.isNotEmpty()) {
                    println(&amp;quot;${module.key}:&amp;quot;)
                    module.value.forEach { println(dependency(it)) }
                    println()
                }
            }
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_reduce_का_उपयोग_करने_का_उदाहरण_सूची_को_स्ट्रिंग_में_संयोजन&amp;quot;&amp;gt;reduce का उपयोग करने का उदाहरण: सूची को स्ट्रिंग में संयोजन&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;tasks.register(&amp;quot;printWebappSrc&amp;quot;) {
    description = &amp;quot;print webapp sources&amp;quot;
    group = WEBAPP
    doLast {
        webAppSrc
            .reduce { acc, s -&amp;amp;gt; &amp;quot;$acc\n\t$s&amp;quot; }
            .run { println(&amp;quot;$WEBAPP_SRC: $this\n&amp;quot;) }
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_किसी_विशेष_कार्य_का_विवरण_प्राप्त_करें&amp;quot;&amp;gt;किसी विशेष कार्य का विवरण प्राप्त करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;./gradlew -q help --task foo&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_workingdir_root_से_एक_कार्य_लॉन्च_करने_के_लिए_फिर_कार्य_को_से_प्रीफ़िक्स&amp;quot;&amp;gt;workingDir root से एक कार्य लॉन्च करने के लिए, फिर कार्य को &amp;lt;code&amp;gt;:&amp;lt;/code&amp;gt; से प्रीफ़िक्स&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;./gradlew :foo&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_असफल_कार्यों_को_पुनः_चलाने_के_लिए_विकल्प_rerun_tasks_का_उपयोग_करें&amp;quot;&amp;gt;असफल कार्यों को पुनः चलाने के लिए, विकल्प &amp;lt;code&amp;gt;--rerun-tasks&amp;lt;/code&amp;gt; का उपयोग करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;./gradlew check --rerun-tasks&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_दूसरे_निर्देशिका_से_एक_विशिष्ट_प्रोजेक्ट_में_एक_टास्क_शुरू_करें&amp;quot;&amp;gt;दूसरे निर्देशिका से एक विशिष्ट प्रोजेक्ट में एक टास्क शुरू करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;विकल्प`-p` (ou &amp;lt;code&amp;gt;--project-dir&amp;lt;/code&amp;gt;) एक Gradle प्रोजेक्ट तक पहुँचने का पथ निर्दिष्ट करने और उसे एक कार्य निष्पादित करने की अनुमति देता है, भले ही वर्तमान निर्देशिका अलग हो।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;उदाहरण के लिए, कार्य शुरू करने के लिए`build`परियोजना स्थित में`~/projets/mon-autre-projet`होते हुए एक अन्य निर्देशिका में :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;./gradlew -p ~/projets/mon-autre-projet build&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यह कई परियोजनाओं में कार्यों को स्क्रिप्ट करने के लिए केंद्रीय स्थान से विशेष रूप से उपयोगी है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;भी देखें :&amp;lt;/div&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://docs.gradle.org/current/userguide/command_line_interface.html#sec:command_line_warnings&amp;quot;&amp;gt;ref&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://docs.gradle.org/current/userguide/command_line_interface.html#sec:command_line_options&amp;quot;&amp;gt;ref&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://stackoverflow.com/a/36178581/837404&amp;quot;&amp;gt;चर्चा&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>प्रशिक्षण - kotlin: enum, sealed classes</title>
            <link >https://cheroliv.com/blog/2022/0038_training_kotlin_enum_sealed_class_post.html</link>
            <pubDate>Tue, 17 May 2022 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2022/0038_training_kotlin_enum_sealed_class_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सील्ड क्लासेस, enum नहीं हैं (कीवर्ड: enum).&amp;lt;br&amp;gt;
जावा से आने पर, आप अपनी सुविधा प्रदान करने वाली सूची को ओवरलोड करने के लिए ललचा सकते हैं: // Java code&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-java&amp;quot; data-lang=&amp;quot;java&amp;quot;&amp;gt;enum PizzaOrderStatus {
    ORDER_RECEIVED,
    PIZZA_BEING_MADE,
    OUT_FOR_DELIVERY,
    COMPLETED;
    public PizzaOrderStatus nextStatus() {
        switch (this) {
        case ORDER_RECEIVED: return PIZZA_BEING_MADE;
        case PIZZA_BEING_MADE: return OUT_FOR_DELIVERY;
        case OUT_FOR_DELIVERY: return COMPLETED;
        case COMPLETED:return COMPLETED;
        }
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इसके बजाय, आप sealed क्लास का उपयोग कर सकते हैं :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;sealed class PizzaOrderStatus(protected val orderId: Int) {
    abstract fun nextStatus() : PizzaOrderStatus
    class OrderReceived(orderId: Int) : PizzaOrderStatus(orderId) {
        override fun nextStatus(): PizzaOrderStatus {
            return PizzaBeingMade(orderId)
        }
    }
    class PizzaBeingMade(orderId: Int) : PizzaOrderStatus(orderId) {
        override fun nextStatus(): PizzaOrderStatus {
            return OutForDelivery(orderId)
        }
    }
    class OutForDelivery(orderId: Int) : PizzaOrderStatus(orderId) {
        override fun nextStatus(): PizzaOrderStatus {
            return Completed(orderId)
        }
    }
    class Completed(orderId: Int) : PizzaOrderStatus(orderId) {
        override fun nextStatus(): PizzaOrderStatus {
            return this
        }
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस दृष्टिकोण का लाभ यह है कि हम अब डेटा को साथ में संचारित कर सकते हैं स्थिति:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;var status: PizzaOrderStatus = OrderReceived(123)
while (status !is Completed) {
    status = when (status) {
        is OrderReceived -&amp;amp;gt; status.nextStatus()
        is PizzaBeingMade -&amp;amp;gt; status.nextStatus()
        is OutForDelivery -&amp;amp;gt; status.nextStatus()
        is Completed -&amp;amp;gt; status
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सामान्य रूप से, sealed classes अच्छी होती हैं यदि आप संबद्ध डेटा रखना चाहते हैं एक राज्य&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>### ग्रैडल एकीकरण</title>
            <link >https://cheroliv.com/blog/2022/0036_training_kotlin_post.html</link>
            <pubDate>Thu, 12 May 2022 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2022/0036_training_kotlin_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_mind_map&amp;quot;&amp;gt;Mind map&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;span class=&amp;quot;image&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;../../diagram/training_kotlin.png&amp;quot; alt=&amp;quot;training_kotlin&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_फलनात्मक_प्रोग्रामिंग&amp;quot;&amp;gt;फलनात्मक प्रोग्रामिंग&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;अभ्यास पुस्तक से लिए गए हैं:&amp;lt;br&amp;gt;
&amp;lt;mark&amp;gt;#&amp;lt;/mark&amp;gt; ग्रेडल एकीकरण JBake को JBake Gradle प्लगइन का उपयोग करके या JBake CLI को सीधे बुलाकर Gradle बिल्ड में एकीकृत किया जा सकता है:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;----
tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) {
    mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;)
    classpath = configurations[&amp;quot;jbake&amp;quot;]
    args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;)
} +
लेखक: Massimo Carli +
रिपॉज़िटरी: https://github.com/kodecocodes/fpk-materials

=== सिंटैक्स

==== पहला प्रोग्राम टेस्ट

अवधारणाएँ: स्क्रीन प्रदर्शन, फ़ंक्शन +
प्रथम कार्यक्रम परीक्षण:https://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/programming/FirstProgramTest.kt[source](No output)

==== संयोजित फ़ंक्शन परीक्षण

धारणाएँ: स्मृति, चर, मान, वस्तु, फ़ंक्शन विस्तार +
(No output)https://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/programming/ConcatFunctionTest.kt[source]+

==== जन्मदिन संदेश परीक्षण आउटपुट

अवधारणा: समुच्चय, लूप +
https://developer.android.com/codelabs/basic-android-kotlin-training-first-kotlin-program?continue=https%3A%2F%2Fdeveloper.android.com%2Fcourses%2Fpathways%2Fandroid-basics-kotlin-one%23codelab-https%3A%2F%2Fdeveloper.android.com%2Fcodelabs%2Fbasic-android-kotlin-training-first-kotlin-program[### Gradle एकीकरण

JBake को Gradle बिल्ड्स में JBake Gradle प्लगिन का उपयोग करके या JBake CLI को सीधे कॉल करके एकीकृत किया जा सकता है:

----

tasks.register&amp;amp;lt;JavaExec&amp;amp;gt;(&amp;quot;bake&amp;quot;) { mainClass.set(&amp;quot;org.jbake.launcher.Main&amp;quot;) classpath = configurations[&amp;quot;jbake&amp;quot;] args = listOf(projectDir.absolutePath, &amp;quot;$buildDir/jbake&amp;quot;) } ```

Kotlin का परिचय] +
जन्मदिन संदेश टेस्ट आउटपुट:https://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/programming/BirthdayMessageTestOutput.kt[source]Veuillez fournir le texte français à traduire.

=== Kotlin का कोर्स

video::YRjY3jRrQYY[youtube]

=== जावा में संग्रहों पर ट्यूटोरियल

https://docs.oracle.com/javase/tutorial/collections/index.html[संग्रह,window=_blank]

कलेक्शन इंटरफ़ेस का कोर +
image:../../img/0036_training_kotlin_post/colls-coreInterfaces.gif[Collections] +

=== बुनियादी कार्यात्मक

==== घोषणात्मक X आदेशात्मक दृष्टिकोण

[source,kotlin]
----
package functional

import kotlin.test.Test
import kotlin.test.assertEquals

class DeclarativeTests {
    val input = listOf(
        &amp;quot;123&amp;quot;, &amp;quot;abc&amp;quot;, &amp;quot;1ds&amp;quot;, &amp;quot;987&amp;quot;, &amp;quot;abdf&amp;quot;, &amp;quot;1d3&amp;quot;, &amp;quot;de1&amp;quot;, &amp;quot;88&amp;quot;, &amp;quot;101&amp;quot;
    )

    fun imperativeSum(list: List&amp;amp;lt;String&amp;amp;gt;): Int {
        var sum = 0
        for (item in list) {
            try {
                sum += item.toInt()
            } catch (_: NumberFormatException) {
            }
        }
        return sum
    }

    @Test
    fun `test imperative approach`() {
        imperativeSum(input).run {
            println(&amp;quot;Sum $this&amp;quot;)
            assertEquals(1299, this)
        }
    }

    fun isValidNumber(s: String) = try {
        s.toInt()
        true
    } catch (_: NumberFormatException) {
        false
    }

    fun declarativeSum(list: List&amp;amp;lt;String&amp;amp;gt;) = list
        .filter(::isValidNumber)
        .map(String::toInt)
        .sum()

    @Test
    fun `test declarative approach`() {
        assertEquals(1299, declarativeSum(input).apply {
            println(&amp;quot;Sum $this&amp;quot;)
        })
    }
}
----

==== अभ्यास 1.1

sumInRange फ़ंक्शन लागू करें, जो मान जोड़ता है में +
एक List&amp;amp;lt;String&amp;amp;gt; एक दिए गए अंतराल में। हस्ताक्षर है:

[source,kotlin]
----
fun sumInRange(input: List&amp;amp;lt;String&amp;amp;gt;, range: IntRange): Int
----

[source,kotlin]
----
@Test
fun `Exercise 1_1`() {
    assertEquals(4, sumInRange(
        listOf(&amp;quot;1&amp;quot;, &amp;quot;10&amp;quot;, &amp;quot;a&amp;quot;, &amp;quot;7&amp;quot;, &amp;quot;ad2&amp;quot;, &amp;quot;3&amp;quot;),
            1..5
        ).apply { println(&amp;quot;sumInRange 1..5: $this&amp;quot;) }
    )
}
----

इसे आज़माएँ और अपने उत्तर की जाँच करें के साथhttps://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/functional/DeclarativeTests.kt[समाधान, windows=&amp;quot;_blank].

==== उच्च-क्रम फ़ंक्शन

[source,kotlin]
----
package functional

import java.io.ByteArrayOutputStream
import java.io.PrintStream
import java.lang.System.*
import java.lang.Thread.sleep
import kotlin.math.sign
import kotlin.test.Test
import kotlin.test.assertEquals

class BasicsHOFTests {
    val ONE_SECOND = 1000L

    @Test
    fun `high order function`() {
        //capture de la sortie standard
        val standardOut: PrintStream? = out
        val outputStreamCaptor = ByteArrayOutputStream()
        setOut(PrintStream(outputStreamCaptor))

        3.times { println(&amp;quot;Hello&amp;quot;) }
        assertEquals(
            buildString {
                repeat(3) { append(&amp;quot;Hello\n&amp;quot;) }
                deleteAt(length - 1)
            }, outputStreamCaptor
                .toString()
                .trim()
        )

        //libération de la sortie standard
        setOut(standardOut)
    }

    fun Int.times1(fn: () -&amp;amp;gt; Unit) {
        for (i in 1..this) {
            fn()
        }
    }

    fun Int.times2(fn: () -&amp;amp;gt; Unit) {
        for (i in 1..this) fn()
    }

    fun Int.times3(fn: () -&amp;amp;gt; Unit) =
        (1..this).forEach { fn() }


    fun Int.times4(fn: () -&amp;amp;gt; Unit) =
        repeat((1..this).count()) { fn() }

    fun Int.times(fn: () -&amp;amp;gt; Unit) =
        (1..this).forEach { _ -&amp;amp;gt; fn() }
}
----

==== अभ्यास 1.2

क्रोनो लागू करें, जो एक प्रकार के फ़ंक्शन को स्वीकार करता है`() -&amp;amp;gt;` +
इकाई इनपुट के रूप में ली जाती है और निष्पादन में लगने वाला समय लौटाती है। हस्ताक्षर : +

[source,kotlin]
----
fun chrono(fn : () -&amp;amp;gt; Unité) : Long
----

[source,kotlin]
----
@Test
fun `Exercise 1_2`() {
    val waitOneSec = { sleep(ONE_SECOND) }
    chrono(waitOneSec).apply {
        println(&amp;quot;chrono: $this&amp;quot;)
        assertEquals(1, sign)
    }
}
----

इसे आज़माएँ और अपने उत्तर की जाँच करें के साथhttps://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/functional/BasicsHOFTests.kt[हल, windows=&amp;quot;_blank].

==== रचना

[source,kotlin]
----
package functional

import kotlin.test.Test
import kotlin.test.assertEquals


fun double(x: Int): Int = 2 * x
fun square(x: Int): Int = x * x
fun squareAndDouble1(x: Int) = double(square(x))

infix fun &amp;amp;lt;A, B, C&amp;amp;gt; ((A) -&amp;amp;gt; B).compose(g: (B) -&amp;amp;gt; C)
        : (A) -&amp;amp;gt; C = { a -&amp;amp;gt; g(this(a)) }

class CompositionTests {
    @Test
    fun composition_impure() {
        assertEquals(200, double(square(10)))
        assertEquals(200, squareAndDouble1(10))
    }

    @Test
    fun composition_pure() {
        val squareAndDouble = ::square compose ::double
        assertEquals(200, squareAndDouble(10))
    }

}
----

==== # एक नया JBake प्रोजेक्ट प्रारम्भ करें

jbake -i

# साइट को बेक (जनरेट) करें jbake -b

# स्थानिक रूप से बेक करके सर्व करें jbake -b -s

# बेक करें और परिवर्तनों की निगरानी करें jbake -b --reset

# स्रोत और गंतव्य निर्दिष्ट करें jbake source_folder output_folder

# बेक करने से पहले आउटपुट निर्देशिका साफ़ करें jbake -b . output --reset ``` शुद्ध फ़ंक्शन और परीक्षणीयता

[source,kotlin]
----
package functional

import java.io.ByteArrayOutputStream
import java.io.PrintStream
import java.lang.System.out
import java.lang.System.setOut
import kotlin.test.Test
import kotlin.test.assertEquals


var count = 0

//impure car une variable global subit un effet de bord
fun impure(value: Int): Int {
    count++
    return value + count
}

//impure car utilisation de la sortie standard qui fait muter le system
fun addOneAndLog(x: Int): Int {
    val result = x + 1
    println(&amp;quot;New Value is $result&amp;quot;)
    return result
}

//pure
fun addOne(x: Int) = (x + 1).run {
    Pair(this, &amp;quot;New Value is $this&amp;quot;)
}

class PureTests {
    @Test
    fun `impure fonction`() {
        assertEquals(3, impure(2))

        val standardOut = out
        val outputStreamCaptor = ByteArrayOutputStream()
        setOut(PrintStream(outputStreamCaptor))

        addOneAndLog(3)

        assertEquals(
            &amp;quot;New Value is 4&amp;quot;,
            outputStreamCaptor
                .toString()
                .trim()
        )
        setOut(standardOut)
    }

    @Test
    fun `pure fonction`() {
        addOne(3).run {
            assertEquals(4, first)
            assertEquals(&amp;quot;New Value is 4&amp;quot;, second)
        }
    }
}
----

==== अपवाद प्रबंधन

[source,kotlin]
----
package functional

import org.junit.jupiter.api.assertThrows
import kotlin.Result.Companion.failure
import kotlin.Result.Companion.success
import kotlin.test.Test
import kotlin.test.assertEquals

//NumberFormatException est un effet de bord qui rend la fonction impure
fun strToInt(str: String) = str.toInt()

//pure
fun strToIntOrNull(str: String) = try {
    str.toInt()
} catch (nfe: NumberFormatException) {
    null
}

//pure avec gestion de l&amp;#39;exception plus élégante
fun strToIntResult(str: String): Result&amp;amp;lt;Int&amp;amp;gt; =
    try {
        success(str.toInt())
    } catch (nfe: NumberFormatException) {
        failure(nfe)
    }

class ExceptionHandlingTests {
    @Test
    fun impure() {
        assertThrows&amp;amp;lt;NumberFormatException&amp;amp;gt; { strToInt(&amp;quot;foo&amp;quot;) }
        assertEquals(1, strToInt(&amp;quot;1&amp;quot;))
    }

    @Test
    fun pure() {
        assertEquals(null, strToIntOrNull(&amp;quot;foo&amp;quot;))
        assertEquals(1, strToIntOrNull(&amp;quot;1&amp;quot;))
    }

    @Test
    fun `pure avec result`() {
        assertEquals(1, strToIntResult(&amp;quot;1&amp;quot;).getOrNull())
        assertEquals(
            &amp;quot;For input string: \&amp;quot;foo\&amp;quot;&amp;quot;,
            strToIntResult(&amp;quot;foo&amp;quot;)
                .exceptionOrNull()
                ?.message
        )
    }
}
----

=== मुख्य बिंदु

* जबकि वस्तु‑उन्मुख प्रोग्रामिंग का अर्थ है वस्तुओं के साथ प्रोग्रामिंग करना।

फ़ंक्शनल प्रोग्रामिंग का मतलब फ़ंक्शन के साथ प्रोग्राम करना है। आप एक समस्या को कई उप‑समस्याओं में तोड़ते हैं, जिन्हें आप मॉडल करते हैं के साथ फ़ंक्शन।

* उच्च कोटि के फ़ंक्शन अन्य फ़ंक्शन को इनपुट के रूप में स्वीकार करते हैं या अन्य फ़ंक्शन लौटाते हैं

वे वापसी मान के रूप में कार्य करते हैं। श्रेणी सिद्धांत संयोजन का सिद्धांत है, और आप इसे समझने के लिए उपयोग करते हैं कैसे अपने फ़ंक्शन को संयोजित करें एक कार्यक्रम में एक शुद्ध फ़ंक्शन का आउटपुट मान केवल इसके इनपुट पैरामीटर पर निर्भर करता है, और यह इसका कोई दुष्प्रभाव नहीं।

* एक साइड इफ़ेक्ट वह कार्य है जो कोई फ़ंक्शन बाहरी दुनिया पर करता है। यह

यह मानक आउटपुट में एक लॉग या किसी वैश्विक चर के मान में संशोधन हो सकता है। फ़ंक्शनल प्रोग्रामिंग शुद्ध कार्यों के लिए काम करती है, लेकिन यह भी प्रदान करती है इन अशुद्ध फ़ंक्शन को शुद्ध फ़ंक्शन में बदलने के लिए उपकरण। आप एक अशुद्ध फ़ंक्शन को शुद्ध बना सकते हैं प्रभावों को स्थानांतरित करके उन्हें परिणाम मान का भाग

* फ़ंक्शनल प्रोग्रामिंग संयोजन का विषय है।

त्रुटि प्रबंधन साइड इफ़ेक्ट का एक विशिष्ट मामला है, और कोटलिन आपको उपकरण देता है उन्हें कार्यात्मक रूप से प्रबंधित करने के लिए।

=== जावा8 को गहराई से समझें: लैम्ब्डा अभिव्यक्तियाँ और फंक्शनल इंटरफ़ेस

video::20waNRw6wMA[youtube,list=PLzzeuFUy_Cng0wZhqbnkvWAW0d2fdVfyQ]

=== श्रेणी सिद्धांत

गणितीय श्रेणियों का सिद्धांत:

video::LVHoROSF3KA[youtube]

=== फ़ंक्शन के मूल सिद्धांत

==== अभ्यास 2.1

क्या आप एक फ़ंक्शन का उदाहरण लिख सकते हैं जो अलग-अलग मानों को मैप करता है? +
जिसके डोमेन में सीमा में असमान मान होते हैं, जैसे f(b) और f(c) नीचे दिए गए चित्र में? +

इसे आज़माएँ, फिर चुनौती प्रोजेक्ट को देखें कि आपने कैसे किया, एक समाधान के लिए। +
आप लिंक का पालन करके सलाह और एक स्पष्टीकरण पाएँगे की ओर https://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/functional/BasicsHOFTests.kt[समाधान, खिड़कियाँ=&amp;quot;_blank]. +

==== अभ्यास 2.2

Can you write the inverse function of twice ? +
विलोम फलन के लिए डोमेन और श्रेणी क्या हैं? +
Check out the challenge project and Appendix B for the solution.

[source,kotlin]
----
fun chrono(fn : () -&amp;amp;gt; Unité) : Long
----

[source,kotlin]
----
@Test
fun `Exercise 1_2`() {
    val waitOneSec = { sleep(ONE_SECOND) }
    chrono(waitOneSec).apply {
        println(&amp;quot;chrono: $this&amp;quot;)
        assertEquals(1, sign)
    }
}

----

इसे आज़माएँ और अपने उत्तर के साथ जाँचेंhttps://github.com/cheroliv/cheroliv.com/blob/master/codes/src/test/kotlin/functional/BasicsHOFTests.kt[हल, windows=&amp;quot;_blank].&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>मेमो डिज़ाइन सिस्टम</title>
            <link >https://cheroliv.com/blog/2022/0031_memo_design_system_post.html</link>
            <pubDate>Sun, 9 Jan 2022 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2022/0031_memo_design_system_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_उपकरण&amp;quot;&amp;gt;उपकरण&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;चित्रांकन&amp;lt;/strong&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://undraw.co/&amp;quot;&amp;gt;undraw.co&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;ओपन सोर्स चित्रण सभी विचारों के लिए जिनकी आप कल्पना कर सकते हैं और बना सकते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://absurd.design/&amp;quot;&amp;gt;बेतुका.डिज़ाइन&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;बेतुके चित्र जो समझ में आते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://drawkit.com/&amp;quot;&amp;gt;drawkit.com&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;शानदार निःशुल्क चित्र। साप्ताहिक अपडेट।&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://icons8.com/&amp;quot;&amp;gt;icons8.com&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;आइकन, चित्रण, फोटो, संगीत, और डिज़ाइन टूल्स।&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://blush.design/&amp;quot;&amp;gt;ब्लश.design&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;आइकन, चित्रण, फोटो, संगीत और डिज़ाइन टूल&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://www.humaaans.com/&amp;quot;&amp;gt;humaaans.com&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;लोगों के चित्रणों को एक डिज़ाइन लाइब्रेरी के साथ मिलाएँ और मेल खाएँ&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;रंग&amp;lt;/strong&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://coolors.co/&amp;quot;&amp;gt;coolors.co&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;अति‑तेज़ रंग स्कीम जेनरेटर!&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;प्रवृत्तियाँ&amp;lt;/strong&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://fr.pinterest.com&amp;quot;&amp;gt;पिन्टरेस्ट&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;विचारों की दृश्यात्मक खोज : चित्र, वीडियो, विषयगत संग्रह&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://dribbble.com&amp;quot;&amp;gt;ड्रिबल&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;डिज़ाइनरों के लिए प्लेटफ़ॉर्म जो अपनी रचनाएँ साझा करते हैं और बातचीत करते हैं।&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;UX/UI और डिज़ाइन सिस्टम्स&amp;lt;/strong&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://material.io/&amp;quot;&amp;gt;गूगल मटीरियल डिज़ाइन&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;Google का डिज़ाइन सिस्टम एकीकृत और अनुकूलन योग्य उपयोगकर्ता इंटरफ़ेस के लिए।&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://developer.apple.com/design/human-interface-guidelines/&amp;quot;&amp;gt;एप्पल मानव इंटरफ़ेस दिशानिर्देश&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;Apple की सिफ़ारिशें iOS और macOS के लिए सहज एप्लिकेशन डिज़ाइन करने के लिए।&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://www.uxpin.com/&amp;quot;&amp;gt;UXPin&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;डिज़ाइन और सहयोग प्लेटफ़ॉर्म, प्रोटोटाइप और डिज़ाइन सिस्टम बनाने के लिए।&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://www.frontify.com/&amp;quot;&amp;gt;Frontify&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;ब्रांड और डिज़ाइन सिस्टम प्रबंधन प्लेटफ़ॉर्म, संगतता सुनिश्चित करने के लिए।&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://designsystemsrepo.com/design-systems/&amp;quot;&amp;gt;डिज़ाइन सिस्टम्स रिपॉज़िटरी&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;संसाधनों और डिज़ाइन सिस्टम के उदाहरणों का संग्रह, प्रेरणा के लिए।&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फ़्रंटएंड डेवलपमेंट&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://htmlcheatsheet.com&amp;quot; target=&amp;quot;&amp;quot;_blank&amp;quot;&amp;gt;htmlcheatsheet.com&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;HTML चेटशीट&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://fontawesome.com&amp;quot; target=&amp;quot;&amp;quot;_blank&amp;quot;&amp;gt;fontawesome.com&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;आइकन लाइब्रेरी&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://www.toptal.com/designers/htmlarrows/symbols/&amp;quot; target=&amp;quot;&amp;quot;_blank&amp;quot;&amp;gt;toptal.com/designers/htmlarrows/symbols&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;HTML में स्वदेशी आइकन&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://css-tricks.com/&amp;quot;&amp;gt;CSS-Tricks&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;CSS के लिए आवश्यक, लेख, ट्यूटोरियल और आधुनिक फ्रंटएंड टिप्स के साथ।&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://www.frontendmentor.io/&amp;quot;&amp;gt;फ़्रंटएंड मेंटर&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;वास्तविक परियोजनाओं पर आधारित फ्रंटएंड कोडिंग चुनौतियाँ जो आपके कौशल को बेहतर बनाती हैं।&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://dev.to/&amp;quot;&amp;gt;Dev.to&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;विकासकों का समुदाय लेख, ट्यूटोरियल और परियोजनाएँ साझा करने के लिए।&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://codepen.io/&amp;quot;&amp;gt;CodePen&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;ऑनलाइन कोड संपादक और कोड स्निपेट एवं डेमो साझा करने के लिए समुदाय&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;AI द्वारा सहायता प्राप्त फ्रंटएंड विकास&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;dlist&amp;quot;&amp;gt;
&amp;lt;dl&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://v0.dev/&amp;quot;&amp;gt;v0.dev&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;v0 प्राकृतिक भाषा विवरणों को कोड और उपयोगकर्ता इंटरफ़ेस में परिवर्तित करता है।&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://uizard.io/&amp;quot;&amp;gt;Uizard&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;Uizard, मॉकअप (इमेज, स्केच) को HTML, CSS और React कोड में बदलने पर केंद्रित है।&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://www.usegalileo.ai/explore&amp;quot;&amp;gt;usegalileo.ai&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;Galileo AI आपको प्राकृतिक भाषा में इंटरफ़ेस का वर्णन करने की अनुमति देता है, और AI संपादन योग्य Figma डिज़ाइन उत्पन्न करता है।&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;dt class=&amp;quot;hdlist1&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;https://play.teleporthq.io/&amp;quot;&amp;gt;TeleportHQ&amp;lt;/a&amp;gt;&amp;lt;/dt&amp;gt;
&amp;lt;dd&amp;gt;
&amp;lt;p&amp;gt;TeleportHQ एक लो‑कोड फ्रंट‑एंड विकास प्लेटफ़ॉर्म है जो कृत्रिम बुद्धिमत्ता (AI) का उपयोग करके आपको दृश्य रूप से वेबसाइट्स बनाने और तैनात करने में मदद करता है।&amp;lt;/p&amp;gt;
&amp;lt;/dd&amp;gt;
&amp;lt;/dl&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Kubernetes, Microk8s, Docker: पहले कदम</title>
            <link >https://cheroliv.com/blog/2020/0029_kubernetes_microk8s_docker_premiers_pas_post.html</link>
            <pubDate>Tue, 3 Nov 2020 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2020/0029_kubernetes_microk8s_docker_premiers_pas_post.html</guid>
            <description>&amp;lt;div id=&amp;quot;preamble&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://microk8s.io/docs/&amp;quot;&amp;gt;MicroK8s का आधिकारिक दस्तावेज़&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_माइक्रोk8s_पैकेज_की_स्थापना&amp;quot;&amp;gt;माइक्रोk8s पैकेज की स्थापना:&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Gradle: एक Gradle कार्य से एक बाह्य प्रक्रिया निष्पादित करें</title>
            <link >https://cheroliv.com/blog/2020/0028_gradle_executer_un_processus_externe_depuis_une_tache_gradle_post.html</link>
            <pubDate>Mon, 28 Sep 2020 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2020/0028_gradle_executer_un_processus_externe_depuis_une_tache_gradle_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_gradle_kotlin_dsl&amp;quot;&amp;gt;Gradle-Kotlin-DSL:&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-kotlin&amp;quot; data-lang=&amp;quot;kotlin&amp;quot;&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Kotlin: NotImplementedException, NotImplementedError</title>
            <link >https://cheroliv.com/blog/2020/0027_kotlin_not_implemented_exception_not_implemented_error_post.html</link>
            <pubDate>Sun, 27 Sep 2020 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2020/0027_kotlin_not_implemented_exception_not_implemented_error_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;NotImplementedException NotImplementedError, परीक्षणों के लिए उपयोगिता, यह जानने में मदद करता है, कि हम कहाँ हैं, और विफलता का कारण।&amp;lt;br&amp;gt;
अभी तक लागू नहीं किया गया, सही अपवाद उठाने की अनुमति देता है&amp;lt;br&amp;gt;
Il y a :&amp;lt;br&amp;gt;
&amp;lt;a href=&amp;quot;http://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/NotImplementedException.html&amp;quot;&amp;gt;org.apache.commons.lang3.NotImplementedException&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;a href=&amp;quot;https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-not-implemented-error/&amp;quot;&amp;gt;kotlin.NotImplementedError&amp;lt;/a&amp;gt;+&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Untar</title>
            <link >https://cheroliv.com/blog/2020/0026_untar_post.html</link>
            <pubDate>Sat, 26 Sep 2020 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2020/0026_untar_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_लिंक_interserver_net&amp;quot;&amp;gt;लिंक: &amp;lt;a href=&amp;quot;https://www.interserver.net/tips/kb/extract-tar-gz-files-using-linux-command-line/&amp;quot;&amp;gt;interserver.net&amp;lt;/a&amp;gt;&amp;lt;/h4&amp;gt;

&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Gradle: परीक्षणों को दोहराएँ, भले ही परीक्षण UP-TO-DATE हों</title>
            <link >https://cheroliv.com/blog/2020/0025_gradle_rejouer_les_tests_meme_lorsque_les_tests_sont_UP-TO-DATE_post.html</link>
            <pubDate>Fri, 25 Sep 2020 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2020/0025_gradle_rejouer_les_tests_meme_lorsque_les_tests_sont_UP-TO-DATE_post.html</guid>
            <description></description>
        </item><item>
            <title>Docker एप्लिकेशन इंस्टॉल नहीं करता, बल्कि इसे खींचता है।</title>
            <link >https://cheroliv.com/blog/2020/0024_docker_n_installe_pas_l_application_mais_tire_la_plutot_post.html</link>
            <pubDate>Thu, 24 Sep 2020 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2020/0024_docker_n_installe_pas_l_application_mais_tire_la_plutot_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_स्रोत_hackernoon_com&amp;quot;&amp;gt;स्रोत: &amp;lt;a href=&amp;quot;https://hackernoon.com/dont-install-postgres-docker-pull-postgres-bee20e200198&amp;quot;&amp;gt;hackernoon.com&amp;lt;/a&amp;gt;&amp;lt;/h4&amp;gt;

&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>फ्रेंच में घिरकिन :</title>
            <link >https://cheroliv.com/blog/2020/0023_gherkin_en_francais_post.html</link>
            <pubDate>Wed, 23 Sep 2020 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2020/0023_gherkin_en_francais_post.html</guid>
            <description></description>
        </item><item>
            <title>Gradle cli: पैरामीटर ओवरराइड करें</title>
            <link >https://cheroliv.com/blog/2020/0022_gradle_cli_surcharger_un_parametre_post.html</link>
            <pubDate>Tue, 22 Sep 2020 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2020/0022_gradle_cli_surcharger_un_parametre_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code&amp;gt;----
----
$ ./gradlew -Pparam_component=CUSTOM
----
----&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>गिट मेमो</title>
            <link >https://cheroliv.com/blog/2020/0021_memo_git_post.html</link>
            <pubDate>Mon, 21 Sep 2020 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2020/0021_memo_git_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_स्रोत&amp;quot;&amp;gt;स्रोत:&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;*https://xenovation.com/blog/source-control-management/git/how-to-change-remote-git-repository[विदेशी नवाचार] *https://intellipaat.com/community/3102/git-show-remote-url-how-can-i-determine-the-url-that-a-local-git-repository-was-originally-cloned-from[intellipaat]&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_गिट_में_रिमोट_रिपॉजिटरी_बदलें&amp;quot;&amp;gt;गिट में रिमोट रिपॉजिटरी बदलें&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;वर्तमान रिमोट रिपॉज़िटरी का URL प्रदर्शित करें:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>URL से खींचें</title>
            <link >https://cheroliv.com/blog/2020/0021_aspirer_depuis_une_URL_post.html</link>
            <pubDate>Sun, 20 Sep 2020 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2020/0021_aspirer_depuis_une_URL_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code&amp;gt;----
----
$ wget -r -k -np http://site.com/docs/manual/
----

लक्ष्य फ़ोल्डर सेट करने के लिए, -P तर्क जोड़ें और फिर पथ दें।
----&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>एक बूटेबल डिस्क बनाएं</title>
            <link >https://cheroliv.com/blog/2020/0020_creer_un_disk_bootable_post.html</link>
            <pubDate>Sat, 19 Sep 2020 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2020/0020_creer_un_disk_bootable_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_लिंक_etcher&amp;quot;&amp;gt;लिंक: &amp;lt;a href=&amp;quot;https://www.balena.io/etcher/&amp;quot;&amp;gt;etcher&amp;lt;/a&amp;gt;&amp;lt;/h4&amp;gt;

&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>लक्ष्य फ़ोल्डर में CLI के माध्यम से अनज़िप करें</title>
            <link >https://cheroliv.com/blog/2020/0019_dezipper_en_CLI_dans_un_dossier_cible_post.html</link>
            <pubDate>Fri, 18 Sep 2020 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2020/0019_dezipper_en_CLI_dans_un_dossier_cible_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_लिंक_askubuntu&amp;quot;&amp;gt;लिंक: &amp;lt;a href=&amp;quot;https://askubuntu.com/questions/86849/how-to-unzip-a-zip-file-from-the-terminal&amp;quot;&amp;gt;askubuntu&amp;lt;/a&amp;gt;&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यदि आप किसी विशेष लक्ष्य फ़ोल्डर में निकालना चाहते हैं, तो आप उपयोग कर सकते हैं : &amp;lt;code&amp;gt;` $ unzip फ़ाइल.zip -d लक्ष्य_फ़ोल्डर &amp;lt;/code&amp;gt;` यदि स्रोत और गंतव्य निर्देशिकाएँ समान हैं, तो आप बस कर सकते हैं: &amp;lt;code&amp;gt;` $ अनज़िप़ करें फ़ाइल.zip &amp;lt;/code&amp;gt;`&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>निर्देशिका सूची में फ़ाइल आकारों का योग दिखाएँ</title>
            <link >https://cheroliv.com/blog/2020/0018_Afficher_la_somme_des_tailles_de_fichier_dans_la_liste_des_r%C3%A9pertoires_post.html</link>
            <pubDate>Thu, 17 Sep 2020 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2020/0018_Afficher_la_somme_des_tailles_de_fichier_dans_la_liste_des_r%C3%A9pertoires_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_लिंक_stackexchange&amp;quot;&amp;gt;लिंक: &amp;lt;a href=&amp;quot;https://unix.stackexchange.com/questions/72661/show-sum-of-file-sizes-in-directory-listing&amp;quot;&amp;gt;stackexchange&amp;lt;/a&amp;gt;&amp;lt;/h4&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code&amp;gt;----
----
$ du -ach --exclude &amp;quot;./.*&amp;quot; /home/troll/
----
----&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>github पर एक ब्रांच हटाएँ</title>
            <link >https://cheroliv.com/blog/2020/0017_detruire_une_branch_sur_github_post.html</link>
            <pubDate>Wed, 16 Sep 2020 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2020/0017_detruire_une_branch_sur_github_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_गिटहब_पर_एक_ब्रांच_हटाना&amp;quot;&amp;gt;गिटहब पर एक ब्रांच हटाना&amp;lt;/h4&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_लिंक_gist&amp;quot;&amp;gt;लिंक: &amp;lt;a href=&amp;quot;https://gist.github.com/cheroliv/921a13ed23ae6d4d66af8d43dd536987&amp;quot;&amp;gt;gist&amp;lt;/a&amp;gt;&amp;lt;/h4&amp;gt;

&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Asciidoc/Markdown मेमो</title>
            <link >https://cheroliv.com/blog/2020/0016_asciidoc_markdown_memo_post.html</link>
            <pubDate>Tue, 15 Sep 2020 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2020/0016_asciidoc_markdown_memo_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;क्यों asciidoc या markdown ? यहाँ मैं asciidoc की ओर बढ़ रहा हूँ, क्योंकि मेरे पास पहले से कुछ टिकट asciidoc में लिखे हुए हैं।&amp;lt;br&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;Asciidoc एक मार्कअप भाषा है जो सामग्री बनाने की अनुमति देता है, एक लेआउट प्रदान करके जो मानव के लिए पढ़ने योग्य पाठ को बनाए रखता है।&amp;lt;br&amp;gt;
यह साधारण सामग्री के लिए अतिरिक्त सॉफ़्टवेयर के बिना पाठ प्रसंस्करण को मानक बनाने का एक तरीका है।&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;ulist&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;कड़ियाँ :&amp;lt;/div&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://blog.oxiane.com/2018/06/13/asciidoc-documentation-as-code/&amp;quot; target=&amp;quot;&amp;quot;_blank&amp;quot;&amp;gt;@jmdoudoux पर blog.oxiane.com&amp;lt;/a&amp;gt;[asciidoc]&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://powerman.name/doc/asciidoc&amp;quot; target=&amp;quot;&amp;quot;_blank&amp;quot;&amp;gt;powerman.name&amp;lt;/a&amp;gt;[asciidoc]&amp;lt;/p&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Debian : एक .deb फ़ाइल को कमांड लाइन से इंस्टॉल करें</title>
            <link >https://cheroliv.com/blog/2019/0013_how-to-install-a-deb-file_post.html</link>
            <pubDate>Mon, 19 Aug 2019 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2019/0013_how-to-install-a-deb-file_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक .deb फ़ाइल से कमांड लाइन के माध्यम से एक डेबियन पैकेज स्थापित करने के लिए।&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ sudo dpkg -i /chemin/du/fichier/deb/&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ देखिए के लिएhttps://unix.stackexchange.com/questions/159094/how-to-install-a-deb-file-by-dpkg-i-or-by-apt[संदर्भ]+&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Gradle: IDE में संसाधन फ़ोल्डर दृश्यमान</title>
            <link >https://cheroliv.com/blog/2019/0011_gradle_configuration_ide_jbake_content_post.html</link>
            <pubDate>Fri, 16 Aug 2019 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2019/0011_gradle_configuration_ide_jbake_content_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक Gradle बिल्ड टूल द्वारा संचालित एप्लिकेशन प्रोजेक्ट में&amp;lt;br&amp;gt;
सभी फ़ोल्डरों पर दृश्यता होना अधिक सुखद होता है&amp;lt;br&amp;gt;
एप्लिकेशन के विकास में भागीदार,&amp;lt;br&amp;gt;
जैसे संसाधन फ़ोल्डर जो नहीं हैं&amp;lt;br&amp;gt;
पथों में परंपरागत रूप से।&amp;lt;br&amp;gt;
उदाहरण के लिए मैं चाहता हूँ कि फ़ोल्डर src/jbake,&amp;lt;br&amp;gt;
यह ‘resource folder’ के रूप में दृश्यमान हो,&amp;lt;br&amp;gt;
इसे प्रोजेक्ट की कॉन्फ़िगरेशन में दर्ज करके किया जा सकता है,&amp;lt;br&amp;gt;
IDE के विज़र्ड्स में. हालाँकि यह विकल्प अगले रीलोड पर सहेजा नहीं जाता&amp;lt;br&amp;gt;
IDE में Gradle प्रोजेक्ट. इस कॉन्फ़िगरेशन को स्थायी रूप से लागू करने के लिए&amp;lt;br&amp;gt;
समाधान स्रोत पथों की कॉन्फ़िगरेशन को ओवरराइड करना है&amp;lt;br&amp;gt;
बिल्ड.gradle कॉन्फ़िगरेशन फ़ाइल में जैसे लाइन 18, 19, 20 और 21 पर:&amp;lt;br&amp;gt;
build.gradle और&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-groovy&amp;quot; data-lang=&amp;quot;groovy&amp;quot;&amp;gt;plugins {
    id &amp;quot;java&amp;quot;
    id &amp;quot;groovy&amp;quot;
    id &amp;quot;org.jbake.site&amp;quot; version &amp;quot;5.0.0&amp;quot;
    id &amp;quot;org.ajoberstar.git-publish&amp;quot; version &amp;quot;2.1.1&amp;quot;
}
repositories {
    mavenCentral()
    jcenter()
}
group project_group
version project_version
sourceSets {
    main {
        java { srcDirs = [] }
        groovy { srcDirs =[&amp;quot;src/main/java&amp;quot;, &amp;quot;src/main/groovy&amp;quot;] }
        resources {
            srcDirs =[
                    &amp;quot;src/main/resources&amp;quot;,
                    &amp;quot;src/jbake&amp;quot;//in order to get site src content in the IDE
            ]
        }
    }
    test {
        java { srcDirs = [] }
        groovy { srcDirs =[&amp;quot;src/test/java&amp;quot;, &amp;quot;src/test/groovy&amp;quot;] }
    }
}
test {
    useJUnitPlatform()
}
configurations {
    ivy
}
dependencies {
    ivy &amp;quot;org.apache.ivy:ivy:$ivy_version&amp;quot;
    implementation &amp;quot;org.codehaus.groovy:groovy-all:$groovy_version&amp;quot;
    implementation &amp;quot;org.asciidoctor:asciidoctor-java-integration:$asciidoctor_java_integration_version&amp;quot;
    implementation &amp;quot;org.freemarker:freemarker:$freemarker_version&amp;quot;
    testImplementation &amp;quot;org.junit.jupiter:junit-jupiter-api:$junit5_version&amp;quot;
    testRuntimeOnly &amp;quot;org.junit.jupiter:junit-jupiter-engine:$junit5_version&amp;quot;
}
gitPublish {
    repoUri = github_pages_blog_repository
    branch = git_branch
    contents {
        from(file(jbake_content_from)) {
            into jbake_content_to
        }
    }
}
tasks.withType(GroovyCompile) {
    groovyClasspath += configurations.ivy
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Groovy script, grab और ivy configuration</title>
            <link >https://cheroliv.com/blog/2019/0010_gradle_groovy_script_grab_ivy_configuration_post.html</link>
            <pubDate>Wed, 14 Aug 2019 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2019/0010_gradle_groovy_script_grab_ivy_configuration_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;टिकट का विषय Gradle बिल्ड स्क्रिप्ट की कॉन्फ़िगरेशन है।&amp;lt;br&amp;gt;
मुझे एक ग्रूवी स्क्रिप्ट का उपयोग करने में सक्षम होना चाहिए, किसी संदर्भ की आवश्यकता के बिना।&amp;lt;br&amp;gt;
उस Gradle परियोजना में जिसमें मैंने इसे संलग्न किया।&amp;lt;br&amp;gt;
मैं इस ग्रूवी स्क्रिप्ट को Gradle के बाहर चलाने में सक्षम होना चाहता हूँ।&amp;lt;br&amp;gt;
बाहरी निर्भरता पुनर्प्राप्ति के ivy एनोटेशन के बिना&amp;lt;br&amp;gt;
वे प्रदर्शन या संकलन समस्या खड़ी नहीं करते&amp;lt;br&amp;gt;
ग्रैडल बिल्ड स्क्रिप्ट का&amp;lt;br&amp;gt;
कन्फ़िगरेशन को समझाने के लिए मैं दो स्क्रिप्ट पर निर्भर हूँ:&amp;lt;br&amp;gt;
एक Gradle बिल्ड स्क्रिप्ट और एक Groovy स्क्रिप्ट.&amp;lt;br&amp;gt;
ग्रूवी स्क्रिप्ट में लाइन 2 के प्रारम्भ में है,&amp;lt;br&amp;gt;
बाह्य निर्भरता को खींचने का एक निर्देश&amp;lt;br&amp;gt;
ivy निर्भरता प्रबंधक की मदद से.&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-Groovy&amp;quot; data-lang=&amp;quot;Groovy&amp;quot;&amp;gt;#!/usr/bin/env groovy
@Grab(&amp;quot;commons-io:commons-io:2.6&amp;quot;)

import org.apache.commons.io.FileUtils

static String getSeparator() {
    System.getProperty(&amp;quot;file.separator&amp;quot;)
}

String from = &amp;quot;${System.getProperty(&amp;quot;user.home&amp;quot;)}${separator}.config${separator}transmission${separator}torrents&amp;quot;
String to = &amp;quot;${System.getProperty(&amp;quot;user.home&amp;quot;)}${separator}Documents${separator}torrents_completed&amp;quot;

File fromDlDir = new File(&amp;quot;${System.getProperty(&amp;quot;user.home&amp;quot;)}${separator}Téléchargements&amp;quot;)
File fromDir = new File(from)
File toDir = new File(to)

Collection&amp;amp;lt;File&amp;amp;gt; torrentFiles = FileUtils.listFiles(
        fromDir,
        [&amp;quot;torrent&amp;quot;] as String[],
        false)
torrentFiles.addAll(FileUtils.listFiles(
        fromDlDir,
        [&amp;quot;torrent&amp;quot;, &amp;quot;torrent.added&amp;quot;] as String[],
        false))


torrentFiles.empty ?: torrentFiles.each { it -&amp;amp;gt;
    FileUtils.copyFileToDirectory(it, toDir)
}
println torrentFiles.size()&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;build.gradle फ़ाइल में, अब देखते हैं कैसे सामंजस्य बिठाएं&amp;lt;br&amp;gt;
दो निर्भरता प्रबंधक, Ivy और Gradle. दोनों के बीच का समझौता पंक्तियों में होता है :&amp;lt;br&amp;gt;
26, 30, 37, 38 et 39&amp;lt;br&amp;gt;
इस प्रकार मैं अपने ग्रूवी स्क्रिप्ट को मैन्युअली चला सकता हूँ&amp;lt;br&amp;gt;
और Gradle संकलन @Grab द्वारा बाधित नहीं है।&amp;lt;br&amp;gt;
ग्रोवी स्क्रिप्ट की निर्भरताओं को Gradle में प्रदान नहीं किया जाना चाहिए।&amp;lt;br&amp;gt;
लेकिन मैं Gradle से Groovy स्क्रिप्ट नहीं चला सकता।&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-Groovy&amp;quot; data-lang=&amp;quot;Groovy&amp;quot;&amp;gt;plugins {
    id &amp;quot;java&amp;quot;
    id &amp;quot;groovy&amp;quot;
}

repositories {
    mavenCentral()
    jcenter()
}

sourceSets {
    main {
        java { srcDirs = [] }
        groovy { srcDirs =[&amp;quot;src/main/java&amp;quot;, &amp;quot;src/main/groovy&amp;quot;] }
        resources {
            srcDirs =[&amp;quot;src/main/resources&amp;quot;]
        }
    }
    test {
        java { srcDirs = [] }
        groovy { srcDirs =[&amp;quot;src/test/java&amp;quot;, &amp;quot;src/test/groovy&amp;quot;] }
    }
}

configurations {
    ivy
}

dependencies {
    ivy &amp;quot;org.apache.ivy:ivy:$ivy_version&amp;quot;
    implementation &amp;quot;org.codehaus.groovy:groovy-all:$groovy_version&amp;quot;
}



tasks.withType(GroovyCompile) {
    groovyClasspath += configurations.ivy
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;टिकट का संदर्भ परhttps://stackoverflow.com/a/18174033/837404[स्टैकओवरफ़्लो]&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Groovy: थोड़ा बीजगणित, महत्तम समापवर्तक (PGCD) और लघुत्तम समापवर्त्य (PPMC)</title>
            <link >https://cheroliv.com/blog/2019/0009_groovy_algebre_pgcd_ppmc_post.html</link>
            <pubDate>Tue, 13 Aug 2019 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2019/0009_groovy_algebre_pgcd_ppmc_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_पीपीएमसी&amp;quot;&amp;gt;पीपीएमसी&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://fr.wikipedia.org/wiki/Plus_petit_commun_multiple&amp;quot;&amp;gt;wiki PPMC या लघुत्तम समापवर्तक&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;AlgebraUtils.groovy&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-groovy&amp;quot; data-lang=&amp;quot;groovy&amp;quot;&amp;gt;package com.cheroliv.misc

import groovy.transform.CompileStatic

@CompileStatic
class AlgebraUtils {

    /**
     * Great common divisor
     * Plus grand commun diviseur(pgcd)
     * Great Common Divisor
     * @param a
     * @param b
     * @return
     */
    static Integer gcd(Integer a, Integer b) {
        !b ? a : gcd(b, a % b)
    }


    /**
     * Least common multiple
     * Plus petit commun multiplicateur(ppmc)
     * @param a
     * @param b
     * @return
     */
    static BigInteger lcm(Integer a, Integer b) {
        (a * b / gcd(a, b)) as BigInteger
    }

    static void main(String... args) {
        Integer a = 96
        Integer b = 28
        println &amp;quot;gcd($a, $b) = ${gcd(a, b)}&amp;quot;
        a = 790
        b = 990
        println &amp;quot;lcm($a, $b) = ${lcm(a, b)}&amp;quot;
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;परिणाम:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;gcd(96, 28) = 4 ल.स.गु.(790, 990) = 78210&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Bash : एक्सटेंशन द्वारा फ़ाइलों को खोजें और आउटपुट को फ़ाइल में find के साथ रखें</title>
            <link >https://cheroliv.com/blog/2019/0008_bash_find_trouver_fichiers_par_extension_post.html</link>
            <pubDate>Mon, 12 Aug 2019 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2019/0008_bash_find_trouver_fichiers_par_extension_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मैं नाम के मानदंडों के अनुसार फ़ाइलों की खोज कर रहा हूँ: फ़ाइलों की सूची जिनका एक्सटेंशन .h और .cpp है&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ find . -name &amp;#39;*.h&amp;#39; -o -name &amp;#39;*.cpp&amp;#39; + +&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;फ़ाइलों की सूची जिनका एक्सटेंशन .h और .cpp है&amp;lt;br&amp;gt;
परिणाम फ़ाइल list_of_txt_files.list में सहेजा जाता है&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ find . -name &amp;#39;*.h&amp;#39; -o -name &amp;#39;*.cpp&amp;#39; -print &amp;amp;gt; list_of_txt_files.list&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मैं .chm एक्सटेंशन वाले फ़ाइलों की सूची खोज रहा हूँ&amp;lt;br&amp;gt;
और मैं इस सूची को नष्ट कर देता हूँ।&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ find . -name &amp;quot;*.chm&amp;quot; -type f -delete&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>वॉटरफ़ॉल पद्धति के साथ एक डिजिटल प्रोजेक्ट का प्रबंधन करना</title>
            <link >https://cheroliv.com/blog/2019/0015_projet_avec_methodologie_en_cascade_post.html</link>
            <pubDate>Thu, 1 Aug 2019 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2019/0015_projet_avec_methodologie_en_cascade_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_विश्लेषण_करना_और_आवश्यकताएँ_एकत्र_करना&amp;quot;&amp;gt;विश्लेषण करना और आवश्यकताएँ एकत्र करना&amp;lt;/h3&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_परियोजना_प्रबंधन_को_परिभाषित_करें&amp;quot;&amp;gt;परियोजना प्रबंधन को परिभाषित करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;../../diagram/definir_projet.png&amp;quot; alt=&amp;quot;definir la gestion de projet&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;../../img/triangle_qcd.png&amp;quot; alt=&amp;quot;triangle_qcd&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_परियोजना_को_परिप्रेक्ष्य_में_रखना&amp;quot;&amp;gt;परियोजना को परिप्रेक्ष्य में रखना&amp;lt;/h3&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_विश्लेषण_करें_और_आवश्यकताएँ_एकत्र_करें&amp;quot;&amp;gt;विश्लेषण करें और आवश्यकताएँ एकत्र करें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;sect3&amp;quot;&amp;gt;
&amp;lt;h4 id=&amp;quot;_लक्ष्य_और_प्राप्तियों_को_तैयार_करें&amp;quot;&amp;gt;लक्ष्य और प्राप्तियों को तैयार करें&amp;lt;/h4&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_एक_पढ़ने_की_ग्रिड_को_डिक्रिप्ट_करें&amp;quot;&amp;gt;एक पढ़ने की ग्रिड को डिक्रिप्ट करें&amp;lt;/h3&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect1&amp;quot;&amp;gt;
&amp;lt;h2 id=&amp;quot;_अपनी_टीम_के_साथ_परियोजना_को_फ्रेम_करें&amp;quot;&amp;gt;अपनी टीम के साथ परियोजना को फ्रेम करें&amp;lt;/h2&amp;gt;
&amp;lt;div class=&amp;quot;sectionbody&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;../../img/conductor.png&amp;quot; alt=&amp;quot;chef d&amp;amp;#8217;orchestre&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_विशेषज्ञों_से_परामर्श_करके_समाधान_खोजें&amp;quot;&amp;gt;विशेषज्ञों से परामर्श करके समाधान खोजें&amp;lt;/h3&amp;gt;

&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;sect2&amp;quot;&amp;gt;
&amp;lt;h3 id=&amp;quot;_एक_परियोजना_प्रबंधन_पद्धति_चुनें&amp;quot;&amp;gt;एक परियोजना प्रबंधन पद्धति चुनें&amp;lt;/h3&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;../../img/cascading_planning.png&amp;quot; alt=&amp;quot;planning en cascade&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;imageblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;img src=&amp;quot;../../img/Cycle_V_details.jpeg&amp;quot; alt=&amp;quot;cycle en V&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>एक PostgreSQL इंटेंस में डेटाबेस लिस्ट करना</title>
            <link >https://cheroliv.com/blog/2019/0014_list_all_databases_in_postgresql_post.html</link>
            <pubDate>Tue, 30 Jul 2019 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2019/0014_list_all_databases_in_postgresql_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मुझे इंस्टॉल करने का मन नहीं है।https://www.pgadmin.org/[pgAdmin] ou &amp;lt;a href=&amp;quot;http://phppgadmin.sourceforge.net/&amp;quot;&amp;gt;phppgadmin&amp;lt;/a&amp;gt; जबकि सब कुछ कमांड लाइन पर मौजूद है।&amp;lt;br&amp;gt;
इसके लिए हमें टर्मिनल खोलना होगा और पोस्टgres उपयोगकर्ता के रूप में लॉग इन करना होगा।&amp;lt;br&amp;gt;
postgres उपयोगकर्ता ही डिफ़ॉल्ट रूप से psql एप्लिकेशन लॉन्च करने का अधिकार रखता है, जो कमांड-लाइन क्लाइंट है। (&amp;lt;a href=&amp;quot;https://fr.wikipedia.org/wiki/Interface_en_ligne_de_commande&amp;quot;&amp;gt;कमांड लाइन इंटरफ़ेस&amp;lt;/a&amp;gt;) postgresql,&amp;lt;br&amp;gt;
कमांड लाइन से टर्मिनल के माध्यम से ऑनलाइन डेटाबेस से संवाद करने में सक्षम होना&amp;lt;br&amp;gt;
जुड़ने के लिए, टर्मिनल खोलें और यह टाइप करें:&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ sudo -i -u postgres&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;PostgreSQL कमांड प्रॉम्प्ट तक सीधे पहुँचने के लिए, यह टाइप करें :&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ sudo -i -u postgres psql&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;एक postgresql इंस्टेंस के डेटाबेस को लिस्ट करने के लिए, यहाँ कमांड है :&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-SQL&amp;quot; data-lang=&amp;quot;SQL&amp;quot;&amp;gt;postgres=# \l&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;परिणाम:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;डेटाबेसों की सूची नाम    | स्वामी | एन्कोडिंग | संरेखण | अक्षर प्रकार |    पहुँच के अधिकार&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;fiber     | tech         | UTF8     | fr_FR.UTF-8     | fr_FR.UTF-8  | =Tc/tech&amp;lt;br&amp;gt;
|              |          |                 |              | tech=CTc/tech fiberdev  | tech         | UTF8     | fr_FR.UTF-8     | fr_FR.UTF-8  | =Tc/tech&amp;lt;br&amp;gt;
|              |          |                 |              | tech=CTc/tech fiberweb  | tech         | UTF8     | fr_FR.UTF-8     | fr_FR.UTF-8  | =Tc/tech&amp;lt;br&amp;gt;
|              |          |                 |              | tech=CTc/tech postgres  | postgres     | UTF8     | fr_FR.UTF-8     | fr_FR.UTF-8  | template0 | postgres     | UTF8     | fr_FR.UTF-8     | fr_FR.UTF-8  | =c/postgres&amp;lt;br&amp;gt;
|              |          |                 |              | postgres=CTc/postgres template1 | postgres     | UTF8     | fr_FR.UTF-8     | fr_FR.UTF-8  | =c/postgres&amp;lt;br&amp;gt;
|              |          |                 |              | postgres=CTc/postgres (blank)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;q दबाएं परिणामों के प्रदर्शन से बाहर निकलने के लिए&amp;lt;br&amp;gt;
&amp;lt;br&amp;gt;
postgresl के उदाहरण के स्कीमा की सूची बनाने के लिए&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-sql&amp;quot; data-lang=&amp;quot;sql&amp;quot;&amp;gt;postgres=# SELECT schema_name FROM information_schema.schemata;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;परिणाम&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;सार्वजनिक जानकारी_स्कीमा pg_catalog pg_toast_temp_1 pg_temp_1 pg_toast (6 लाइनों)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;ou&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-sql&amp;quot; data-lang=&amp;quot;sql&amp;quot;&amp;gt;postgres=# SELECT nspname FROM pg_catalog.pg_namespace;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;परिणाम&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;pg_toast pg_temp_1 pg_toast_temp_1 pg_catalog सूचना_स्कीमा सार्वजनिक (6 lignes)&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Groovy: फ़ाइलों को रिकर्सिव रूप से नाम बदलें</title>
            <link >https://cheroliv.com/blog/2019/0007_groovy_rename_recursively_files_post.html</link>
            <pubDate>Mon, 29 Jul 2019 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2019/0007_groovy_rename_recursively_files_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मेरे टीवी के वीडियो प्लेयर की अपनी विधि है पार करने की&amp;lt;br&amp;gt;
एक फ़ाइल से दूसरे फ़ाइल तक निरंतर पढ़ते हुए&amp;lt;br&amp;gt;
और उसका प्लेबैक मोड 1&amp;amp;#8230;&amp;amp;#8203;..mp4 से 10&amp;amp;#8230;&amp;amp;#8203;.mp4 तक जाने का है,&amp;lt;br&amp;gt;
और नहीं 1&amp;amp;#8230;&amp;amp;#8203;mp4 से 2&amp;amp;#8230;&amp;amp;#8203;.mp4 तक।&amp;lt;br&amp;gt;
समस्या यह है कि लगभग 900 फ़ाइलें और फ़ोल्डर हैं।&amp;lt;br&amp;gt;
बिंगो ग्रूवी को मैनिपुलेट करने के लिए एक उत्कृष्ट उपयोग का मामला&amp;lt;br&amp;gt;
फ़ाइलें, नाम बदलना, फ़ाइल नाम में पैटर्न खोज&amp;lt;br&amp;gt;
या फ़ाइल।&amp;lt;br&amp;gt;
Ici le but est de changer les noms commençant par&amp;lt;br&amp;gt;
एक अंक और जिसका नाम का दूसरा अक्षर&amp;lt;br&amp;gt;
यह एक संख्या नहीं है, मैं इस नाम के प्रारम्भ में एक 0 जोड़ दूँगा&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;दो अंक से शुरू होने के लिए फ़ाइलों का नाम बदलें.groovy&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-groovy&amp;quot; data-lang=&amp;quot;groovy&amp;quot;&amp;gt;#!/usr/bin/env groovy
/**
 * get a crossplateform separator
 * @return
 */
static String getSeparator() {
    System.getProperty(&amp;quot;file.separator&amp;quot;)
}
/**
 * rename file
 * @param file
 * @param newName
 * @return the renamed file
 */
static File rename(File file, String newName) {
    assert file.renameTo(file
            .parentFile.path +
            getSeparator() +
            newName)
    new File(file
            .parentFile.path +
            getSeparator() +
            newName)
}

String rootFolderPath = System.getProperty(&amp;quot;user.home&amp;quot;) +
        &amp;quot;/Bureau/ng-courses/Udemy - Angular 7 &amp;quot; +
        &amp;quot;(formerly Angular 2) - The Complete Guide&amp;quot;

File rootFolder = new File(rootFolderPath)
assert rootFolder.exists()
assert rootFolder.directory
assert rootFolder.canRead()

List&amp;amp;lt;File&amp;amp;gt; dirList = new ArrayList&amp;amp;lt;&amp;amp;gt;()

//Adding rootFolder in dirList
// just in case there is some files in it
dirList.add(rootFolder)

//looping to get list of directories
//recursively inside rootFolder
rootFolder.traverse { File file -&amp;amp;gt;
    !file.directory ?: dirList.add(file)
}

//looping through dirList
//to rename directories filling criterias
for (int i = dirList.size() - 1; i &amp;amp;gt;= 0; i--) {
    Character[] chars = dirList.get(i).name.chars
    !(chars[0].digit &amp;amp;amp;&amp;amp;amp; !chars[1].digit) ?:
            dirList.set(i, rename(dirList.get(i),
                    &amp;quot;0${dirList.get(i).name}&amp;quot;))
    if (dirList.get(i).directory) {
        //looping through directory
        //to rename file filling criterias
        dirList.get(i).listFiles().each { File f -&amp;amp;gt;
            Character[] cs = f.name.chars
            !(cs[0].digit &amp;amp;amp;&amp;amp;amp; !cs[1].digit) ?:
                    rename(f, &amp;quot;0${f.name}&amp;quot;)
        }
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Groovy: मानदंड के साथ फ़ाइलों की खोज, चयन की प्रतिलिपि बनाएँ</title>
            <link >https://cheroliv.com/blog/2019/0006_groovy_find_files_copy_to_post.html</link>
            <pubDate>Fri, 19 Jul 2019 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2019/0006_groovy_find_files_copy_to_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;इस स्क्रिप्ट का उद्देश्य फ़ाइलों की खोज करना है,&amp;lt;br&amp;gt;
एक मूल निर्देशिका से; चयन प्राप्त करें&amp;lt;br&amp;gt;
एक सूची में। अंत में इस फ़ाइल सूची की प्रतिलिपि बनाएँ&amp;lt;br&amp;gt;
एक गंतव्य निर्देशिका में यह Groovy में&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;findCopyTo.groovy&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-groovy&amp;quot; data-lang=&amp;quot;groovy&amp;quot;&amp;gt;#!/usr/bin/env groovy
@Grab(&amp;quot;commons-io:commons-io:2.6&amp;quot;)

import groovy.io.FileType
import org.apache.commons.io.FileUtils

/**
 * un separateur OS independant
 * @return
 */
static String getSep() {
    System.getProperty(&amp;quot;file.separator&amp;quot;)
}
/**
 * la liste des fichiers dont le titre contient un item
 * de la liste des motifs
 *
 * @param path
 * @param motifs
 * @return la liste des chemins complet de fichiers
 */
static List&amp;amp;lt;String&amp;amp;gt; findFilesContainingMotifs(
        String path,
        List&amp;amp;lt;String&amp;amp;gt; motifs) {
    List&amp;amp;lt;String&amp;amp;gt; filePathResultList = new ArrayList&amp;amp;lt;&amp;amp;gt;()
    new File(path)
            .eachFileRecurse(FileType.FILES) {
                if (it.name.toLowerCase().contains(&amp;#39;cucumber&amp;#39;)) {
                    filePathResultList.add it.path
                }
            }
    filePathResultList
}

/**
 * copy vers la liste des fichiers
 * @param files
 * @param to
 */
static void copyFilesTo(List&amp;amp;lt;String&amp;amp;gt; files, String to) {
    File toDirDest = new File(to)
    files.each { String filepath -&amp;amp;gt;
        File file = new File(filepath)
        //si le dernier caractere de to n&amp;#39;est pas un separateur
        // alors ajoute le a la chaine
        (to.substring(to.length() - 1) == sep) ?: to.concat(sep)
        if (to + file.name != filepath) {
            FileUtils.copyFileToDirectory(file, toDirDest)
            file.delete()
        }
    }
}
/**
 * la list des arguments
 */
String userName = System.getProperty(&amp;quot;user.name&amp;quot;)
List&amp;amp;lt;String&amp;amp;gt; motifs = [&amp;#39;cucumber&amp;#39;]
String path = &amp;quot;/media/$userName/320/Books/&amp;quot;
String to = &amp;quot;/media/$userName/320/Books/bdd/&amp;quot;
/**
 * lappel aux methodes
 */
copyFilesTo(findFilesContainingMotifs(path, motifs), to)

//affiche moi les fichiers déplacés
findFilesContainingMotifs(path, motifs).each {
    println it
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Groovy: फ़ाइलों का संचालन, खोज और हटाना</title>
            <link >https://cheroliv.com/blog/2019/0005_groovy_manipulation_files_post.html</link>
            <pubDate>Thu, 18 Jul 2019 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2019/0005_groovy_manipulation_files_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ मैं एक बिल्ड प्रोजेक्ट में एक प्रॉपर्टी के लोडिंग पर ध्यान केंद्रित करूँगा।https://docs.gradle.org/current/userguide/userguide.html[gradle]&amp;lt;br&amp;gt;
कोड में उपलब्ध न होने पर&amp;lt;br&amp;gt;
यह प्रॉपर्टी ~/.gradle/ फ़ोल्डर की gradle.properties फ़ाइल में परिभाषित की जाएगी।&amp;lt;br&amp;gt;
~ HOME_PATH प्रतीकात्मक चर का एक शॉर्टकट है जो सत्र उपयोगकर्ता मूल का प्रतिनिधित्व करता है: वहhttps://fr.wikipedia.org/wiki/R%C3%A9pertoire_personnel[व्यक्तिगत निर्देशिका].&amp;lt;br&amp;gt;
एक ही तरह से एक बिल्ड प्रोजेक्ट मेंhttps://maven.apache.org/guides/index.html[maven], के साथ `~/.m2/settings.xml इस स्क्रिप्ट का उद्देश्य उल्लिखित पैटर्न से मेल खाने वाले फ़ाइलों को हटाना है।&amp;lt;br&amp;gt;
चर strCriteria में. इसके लिए मैं उनका उपयोग करूँगाhttps://fr.wikipedia.org/wiki/Fermeture_(informatique)[बंद]: हर, सभी खोजें,  एकत्रित करें&amp;lt;br&amp;gt;
साथ में StringTokenizer क्लास जो मेरे मानदंड स्ट्रिंग को टुकड़ों में विभाजित करेगा&amp;lt;br&amp;gt;
इनकी एक स्ट्रिंग्स की सूची प्राप्त करने के लिए। यदि मेरे साफ़ करने वाले फ़ोल्डर की किसी फ़ाइल के नाम में कोई पैटर्न मौजूद हो&amp;lt;br&amp;gt;
तो वह परिणाम सूची में जोड़े जाने से नाश का उम्मीदवार होगा।&amp;lt;br&amp;gt;
और अंतिम पंक्ति पर एक छोटा उदाहरणhttps://en.wikipedia.org/wiki/Elvis_operator[एल्विस ऑपरेटर]&amp;lt;br&amp;gt;
filemanip.groovy&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-groovy&amp;quot; data-lang=&amp;quot;groovy&amp;quot;&amp;gt;#!/usr/bin/env groovy
//Mes criteres de selection des fichiers à detruire
String strCriteria = &amp;quot;Dummies Dummie ajax Objective-C Windows blackberry &amp;quot; +
        &amp;quot;wordpress joomla ios c# f# rails ruby flex asp flash Dreamweaver adobe &amp;quot; +
        &amp;quot;CoffeeScript c++ .chm .epub .rar .zip .tar drupal drupals .net php javascript &amp;quot; +
        &amp;quot;.js iphone ipad js _js facebook gwt vaadin linq python py zope window &amp;quot; +
        &amp;quot;3D scala gaming active_directory tomcat jboss glassfish microsoft 2d &amp;quot; +
        &amp;quot;lego blogger blog cocoa dojo dom dotnetnuke eclipse .gz unity sharepoint &amp;quot; +
        &amp;quot;.tgz iwork filemaker .doc .txt&amp;quot;


//repertoire personnel
String userDir = System.getProperty(&amp;quot;user.home&amp;quot;)
//un separateur de chemin crossplatform
String sep = System.getProperty(&amp;quot;file.separator&amp;quot;)
//la variable symbolique
String sym_books_vrac_path = &amp;quot;books_vrac_path&amp;quot;

//le chemin de mon fichier gradle.properties hors projet
String propertiesFilePath = userDir
        .concat(&amp;quot;${sep}.gradle${sep}gradle.properties&amp;quot;)


File propertiesFile = new File(propertiesFilePath)


//je m&amp;#39;aassure que le fichier existe et que ce n&amp;#39;est pas un dossier
assert propertiesFile.exists() &amp;amp;amp;&amp;amp;amp; !propertiesFile.directory

Properties gradleProperties = new Properties()

//on boucle avec un inpustream sur le fichier
//gradle.properties pour peupler ma variable gradleProperties
propertiesFile.withInputStream { InputStream it -&amp;amp;gt;
    gradleProperties.load(it)
}

//le chemin du dossier books_vrac est la valeur de notre clé books_vrac_path
String pathVracDir = gradleProperties.get(sym_books_vrac_path)

//j&amp;#39;ai récuperé tous ces livres en tapant cette commande dans le terminal
//wget -m -np -c -R &amp;quot;index.html*&amp;quot; &amp;quot;http://the-eye.eu/public/Books/IT%20Various/&amp;quot;

//on ouvre le dossier dont le chemin est dans la variable pathVracDir
// on s&amp;#39;assure qu&amp;#39;il existe et que c&amp;#39;est un dossier
File vracDir = new File(pathVracDir)
assert vracDir.exists() &amp;amp;amp;&amp;amp;amp; vracDir.directory


//separer les élèments de ma liste de critère
StringTokenizer tokenizer = new StringTokenizer(strCriteria)

//la liste de critere
List&amp;amp;lt;String&amp;amp;gt; criteriaList = new ArrayList&amp;amp;lt;&amp;amp;gt;()

//j&amp;#39;itère sur les tokens et je construit ma liste de token,
// mot clef critère de recherche
tokenizer.each { String it -&amp;amp;gt;
    criteriaList.add(it.toLowerCase())
}

//je collect tous les noms de fichier dans le dossier
List&amp;amp;lt;String&amp;amp;gt; fileNameList = vracDir
        .listFiles()
        .collect { File it -&amp;amp;gt;
            it.directory ?: it.name
        }

// je collect les noms de fichier qui contiendraient un des criteres
List&amp;amp;lt;String&amp;amp;gt; resultList = fileNameList.findAll { String name -&amp;amp;gt;
    criteriaList.findAll { String crit -&amp;amp;gt;
        name.toLowerCase().contains(crit)
    }
}

// je parcours ma liste de résultat pour les effacer
resultList.each { String fileName -&amp;amp;gt;
    assert new File(vracDir.path + sep + fileName).delete()
}

println fileNameList.size()
println resultList.size()
resultList.empty ?: println(vracDir.path + sep + resultList.first())&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Groovy: एक स्ट्रिंग में अक्षरों की श्रृंखला बदलें और एक फ़ाइल से Properties लोड करें</title>
            <link >https://cheroliv.com/blog/2019/0004_groovy_replace_string_load_properties_post.html</link>
            <pubDate>Wed, 17 Jul 2019 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2019/0004_groovy_replace_string_load_properties_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ एक काम करने वाला ग्रूवी कोड का टुकड़ा है,&amp;lt;br&amp;gt;
एक String में एक अक्षर अनुक्रम के सभी उदाहरणों को बदलने के लिए&amp;lt;br&amp;gt;
और एक .properties फ़ाइल को एक properties ऑब्जेक्ट में लोड करें।&amp;lt;br&amp;gt;
एक स्ट्रिंग में कमांड निष्पादित करें।&amp;lt;br&amp;gt;
replaceTextinFile.groovy&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-groovy&amp;quot; data-lang=&amp;quot;groovy&amp;quot;&amp;gt;#!/usr/bin/env groovy
println System.getProperty(&amp;quot;user.home&amp;quot;)

static String getSeparator_() {
    System.getProperty(&amp;quot;file.separator&amp;quot;)
}

String separator = separator_

String path = System.getProperty(&amp;quot;user.home&amp;quot;)
        .concat(&amp;quot;${separator}.gradle&amp;quot; +
                separator +
                &amp;quot;gradle.properties&amp;quot;)

File propertiesFile = new File(path)

assert propertiesFile.exists() &amp;amp;amp;&amp;amp;amp; !propertiesFile.directory

Properties gradleProperties = new Properties()

propertiesFile.withInputStream { InputStream it -&amp;amp;gt;
    gradleProperties.load(it)
}

String user_name = gradleProperties.getProperty(&amp;quot;user_name&amp;quot;)

String text
String resultText
text = new File(&amp;quot;${System.getProperty(&amp;quot;user.home&amp;quot;)}&amp;quot; +
        separator +
        &amp;quot;src&amp;quot; +
        separator +
        &amp;quot;cheroliv.github.io&amp;quot; +
        separator +
        &amp;quot;src&amp;quot; +
        separator +
        &amp;quot;main&amp;quot; +
        separator +
        &amp;quot;resources&amp;quot; +
        separator +
        &amp;quot;eco_space.txt&amp;quot;).text

String to = separator +
        &amp;quot;media&amp;quot; +
        separator +
        &amp;quot;${user_name}&amp;quot; +
        separator +
        &amp;quot;320&amp;quot; +
        separator +
        &amp;quot;videoCours&amp;quot; +
        separator
String from = &amp;quot;${System.getProperty(&amp;quot;user.home&amp;quot;)}&amp;quot; +
        separator +
        &amp;quot;p2p&amp;quot; +
        separator

resultText = text.replace(to, from)

println resultText

//execute command line in a string
println &amp;quot;rsync -avr ${resultText} ${to}&amp;quot;.execute().text&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item><item>
            <title>Groovy: ASCII वर्ण</title>
            <link >https://cheroliv.com/blog/2019/0003_groovy_char_ascci_post.html</link>
            <pubDate>Wed, 10 Jul 2019 00:00:00 +0000</pubDate>
            <guid isPermaLink="false">blog/2019/0003_groovy_char_ascci_post.html</guid>
            <description>&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;यहाँ एक कार्यात्मक ग्रूवी कोड का टुकड़ा है, जो एक टेक्स्ट फ़ाइल बनाता है,&amp;lt;br&amp;gt;
ASCII तालिका के पहले 256 पढ़ने योग्य अक्षर के साथ&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-groovy&amp;quot; data-lang=&amp;quot;groovy&amp;quot;&amp;gt;#!/usr/bin/env groovy
import java.nio.charset.StandardCharsets

List&amp;amp;lt;Character&amp;amp;gt; chars = new ArrayList&amp;amp;lt;&amp;amp;gt;()
int j = 0
Character jumpLine = &amp;#39;\n&amp;#39;

256.times { Integer idx -&amp;amp;gt;
    if (Character.isAlphabetic(idx) || Character.isDigit(idx)) {
        if (j % 10 == 0 &amp;amp;amp;&amp;amp;amp; j != 0) {
            chars.add(jumpLine)
            chars.add(idx as char)
        } else chars.add(idx as char)
        j++
    }
}

String seperator = System.getProperty(&amp;quot;file.separator&amp;quot;)

String path = &amp;quot;${System.getProperty(&amp;quot;user.home&amp;quot;)}${seperator}ascii.txt&amp;quot;
File speCharFile = new File(path)

if (speCharFile.exists() &amp;amp;amp;&amp;amp;amp; !speCharFile.directory) {
    speCharFile.text = &amp;quot;&amp;quot;
} else {
    speCharFile.createNewFile()
}

String text = new String()

chars.each { Character it -&amp;amp;gt;
    text = it == jumpLine ? &amp;quot;$text$it&amp;quot; : &amp;quot;$text $it &amp;quot;
}

speCharFile.setText(text, StandardCharsets.UTF_8.toString())&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;मैंने फ़ाइल spe_char.groovy का नाम दिया,&amp;lt;br&amp;gt;
फ़ाइल वाला फ़ोल्डर से&amp;lt;br&amp;gt;
एक टर्मिनल खोलें और स्क्रिप्ट को चलाने के लिए कॉपी पेस्ट करें&amp;lt;br&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;listingblock&amp;quot;&amp;gt;
&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;pre class=&amp;quot;highlight&amp;quot;&amp;gt;&amp;lt;code class=&amp;quot;language-bash&amp;quot; data-lang=&amp;quot;bash&amp;quot;&amp;gt;$ groovy spe_char.groovy&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;परिणाम:&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;paragraph&amp;quot;&amp;gt;
&amp;lt;p&amp;gt;0  1  2  3  4  5  6  7  8  9 A  B  C  D  E  F  G  H  I  J K  L  M  N  O  P  Q  R  S  T U  V  W  X  Y  Z  a  b  c  d e  f  g  h  i  j  k  l  m  n o  p  q  r  s  t  u  v  w  x y  z  ª  µ  º  À  Á  Â  Ã  Ä Å  Æ  Ç  È  É  Ê  Ë  Ì  Í  Î Ï  Ð  Ñ  Ò  Ó  Ô  Õ  Ö  Ø  Ù Ú  Û  Ü  Ý  Þ  ß  à  á  â  ã ä  å  æ  ç  è  é  ê  ë  ì  í î  ï  ð  ñ  ò  ó  ô  õ  ö  ø ù  ú  û  ü  ý  þ  ÿ&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;</description>
        </item>

    </channel>
</rss>
