<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Rop on Ocarina — précis</title>
    <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/tags/rop/</link>
    <description>Recent content in Rop on Ocarina — précis</description>
    <generator>Hugo</generator>
    <language>fr-FR</language>
    <lastBuildDate>Thu, 04 Jun 2026 17:04:59 +0200</lastBuildDate>
    <atom:link href="https://mojo-molotov.github.io/from-ocarina-to-igor/fr/tags/rop/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>02.03.01 — Le type Result[T]</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/01-result/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/01-result/</guid>
      <description>&lt;h1 id=&#34;020301le-type-resultt&#34;&gt;02.03.01 — Le type &lt;code&gt;Result[T]&lt;/code&gt;&lt;a class=&#34;anchor&#34; href=&#34;#020301le-type-resultt&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Fichier source : &lt;a href=&#34;https://github.com/mojo-molotov/ocarina/blob/main/src/ocarina/railway/result.py&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;src/ocarina/railway/result.py&lt;/code&gt;&lt;/a&gt; — &lt;strong&gt;zéro dépendance&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;code&#34;&gt;Code&lt;a class=&#34;anchor&#34; href=&#34;#code&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;from&lt;/span&gt; dataclasses &lt;span style=&#34;color:#ff79c6&#34;&gt;import&lt;/span&gt; dataclass, field&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;from&lt;/span&gt; typing &lt;span style=&#34;color:#ff79c6&#34;&gt;import&lt;/span&gt; TypeGuard, final&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;_BaseResult&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&amp;#34;&amp;#34;Base class ensuring both Ok and Fail have error attribute for type narrowing.&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error: Exception &lt;span style=&#34;color:#ff79c6&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;None&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@final&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@dataclass(frozen&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;Ok&lt;/span&gt;[T](_BaseResult):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    value: T&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error: &lt;span style=&#34;color:#ff79c6&#34;&gt;None&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;None&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@final&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@dataclass(frozen&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;Fail&lt;/span&gt;(_BaseResult):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error: Exception &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; field(default_factory&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;lambda&lt;/span&gt;: Exception(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Unknown error&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;type&lt;/span&gt; Result[T] &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; Ok[T] &lt;span style=&#34;color:#ff79c6&#34;&gt;|&lt;/span&gt; Fail&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;is_ok&lt;/span&gt;[T](result: Result[T]) &lt;span style=&#34;color:#ff79c6&#34;&gt;-&amp;gt;&lt;/span&gt; TypeGuard[Ok[T]]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;isinstance&lt;/span&gt;(result, Ok)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;is_fail&lt;/span&gt;[T](result: Result[T]) &lt;span style=&#34;color:#ff79c6&#34;&gt;-&amp;gt;&lt;/span&gt; TypeGuard[Fail]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;isinstance&lt;/span&gt;(result, Fail)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;six-décisions-de-design-à-décortiquer&#34;&gt;Six décisions de design à décortiquer&lt;a class=&#34;anchor&#34; href=&#34;#six-d%c3%a9cisions-de-design-%c3%a0-d%c3%a9cortiquer&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;h3 id=&#34;1-_baseresult-comme-parent-commun&#34;&gt;1. &lt;code&gt;_BaseResult&lt;/code&gt; comme parent commun&lt;a class=&#34;anchor&#34; href=&#34;#1-_baseresult-comme-parent-commun&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;_BaseResult&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error: Exception &lt;span style=&#34;color:#ff79c6&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But unique : permettre à &lt;em&gt;mypy&lt;/em&gt; d&amp;rsquo;&lt;strong&gt;accéder à &lt;code&gt;result.error&lt;/code&gt; sans narrowing préalable&lt;/strong&gt;. Sans cette base, on devrait écrire :&lt;/p&gt;</description>
    </item>
    <item>
      <title>03.01 — Effect, Thunk[T], Result[T]</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/01-effect-thunk-result/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/01-effect-thunk-result/</guid>
      <description>&lt;h1 id=&#34;0301effect-thunkt-resultt&#34;&gt;03.01 — &lt;code&gt;Effect&lt;/code&gt;, &lt;code&gt;Thunk[T]&lt;/code&gt;, &lt;code&gt;Result[T]&lt;/code&gt;&lt;a class=&#34;anchor&#34; href=&#34;#0301effect-thunkt-resultt&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Trois lignes de code dans &lt;code&gt;custom_types/&lt;/code&gt; + une dans &lt;code&gt;railway/&lt;/code&gt;. Tout le DSL repose dessus.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;triplet&#34;&gt;Triplet&lt;a class=&#34;anchor&#34; href=&#34;#triplet&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;# src/ocarina/custom_types/effect.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;type&lt;/span&gt; Effect &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; Callable[[], &lt;span style=&#34;color:#ff79c6&#34;&gt;None&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;type&lt;/span&gt; Effects &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;tuple&lt;/span&gt;[Effect, &lt;span style=&#34;color:#ff79c6&#34;&gt;...&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;# src/ocarina/custom_types/thunk.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;type&lt;/span&gt; Thunk[T] &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; Callable[[], T]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;# src/ocarina/railway/result.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;type&lt;/span&gt; Result[T] &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; Ok[T] &lt;span style=&#34;color:#ff79c6&#34;&gt;|&lt;/span&gt; Fail&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Type&lt;/th&gt;&#xA;          &lt;th&gt;Sémantique FP&lt;/th&gt;&#xA;          &lt;th&gt;Définition&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;Effect&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Effet de bord (déféré)&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;() -&amp;gt; None&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;Thunk[T]&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;em&gt;Computation&lt;/em&gt; déférée avec valeur&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;() -&amp;gt; T&lt;/code&gt; (paresse + valeur)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;Result[T]&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;em&gt;Computation&lt;/em&gt; qui peut échouer&lt;/td&gt;&#xA;          &lt;td&gt;Union discriminée &lt;code&gt;Ok[T] | Fail&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;distinction-effect-vs-thunk&#34;&gt;Distinction Effect vs Thunk&lt;a class=&#34;anchor&#34; href=&#34;#distinction-effect-vs-thunk&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;log_msg: Effect &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;lambda&lt;/span&gt;: &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;)        &lt;span style=&#34;color:#6272a4&#34;&gt;# () -&amp;gt; None&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;get_42: Thunk[&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;int&lt;/span&gt;] &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;lambda&lt;/span&gt;: &lt;span style=&#34;color:#bd93f9&#34;&gt;42&lt;/span&gt;                 &lt;span style=&#34;color:#6272a4&#34;&gt;# () -&amp;gt; int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fetch:  Thunk[Result[&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;int&lt;/span&gt;]] &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;lambda&lt;/span&gt;: Ok(&lt;span style=&#34;color:#bd93f9&#34;&gt;42&lt;/span&gt;)     &lt;span style=&#34;color:#6272a4&#34;&gt;# () -&amp;gt; Result[int]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Si la fonction &lt;em&gt;retourne&lt;/em&gt; quelque chose qu&amp;rsquo;on va consommer ailleurs → &lt;code&gt;Thunk[T]&lt;/code&gt;.&lt;br&gt;&#xA;Sinon → &lt;code&gt;Effect&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>02.03.02 — La machine à états du builder</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/02-action-chain-states/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/02-action-chain-states/</guid>
      <description>&lt;h1 id=&#34;020302la-machine-à-états-du-builder&#34;&gt;02.03.02 — La machine à états du builder&lt;a class=&#34;anchor&#34; href=&#34;#020302la-machine-%c3%a0-%c3%a9tats-du-builder&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Fichier source : &lt;a href=&#34;https://github.com/mojo-molotov/ocarina/blob/main/src/ocarina/dsl/testing_with_railway/internals/action_chain.py&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;src/ocarina/dsl/testing_with_railway/internals/action_chain.py&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;C&amp;rsquo;est ici qu&amp;rsquo;est implémentée &lt;em&gt;toute&lt;/em&gt; la mécanique ROP : le passage par quatre états successifs typés, qui interdit littéralement (au sens du &lt;em&gt;type-checker&lt;/em&gt;) toute fantaisie syntaxique. Le DSL est aussi son propre système immunitaire.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;vue-densemble&#34;&gt;Vue d&amp;rsquo;ensemble&lt;a class=&#34;anchor&#34; href=&#34;#vue-densemble&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;                      ┌─────────────────┐&#xA;   start(action)  →   │  ActionStart[T] │     un Action[T] = Thunk[Result[T]]&#xA;                      └────────┬────────┘&#xA;                               │ .failure(failure_handler)&#xA;                               ▼&#xA;                      ┌─────────────────┐&#xA;                      │ ActionFailure[T]│&#xA;                      └────────┬────────┘&#xA;                               │ .success(success_handler)&#xA;                               ▼&#xA;                      ┌─────────────────┐&#xA;                      │ ActionSuccess[T]│&#xA;                      └────────┬────────┘&#xA;                               │ .execute()   ── exécute action(), fire le handler&#xA;                               ▼&#xA;                      ┌─────────────────┐&#xA;                      │ ActionChain[T]  │     contient (has_failed, result)&#xA;                      └──────┬──────────┘&#xA;                             │ .then(next_action_or_start)&#xA;              ┌──────────────┴──────────────┐&#xA;              │                             │&#xA;   has_failed=True                   has_failed=False&#xA;              │                             │&#xA;              ▼                             ▼&#xA;   ┌──────────────────┐         ┌──────────────────┐&#xA;   │ NeutralAction-   │         │ ActionStart[T]   │  → cycle recommence&#xA;   │ Start[T]         │         │  (l&amp;#39;action suiv. │&#xA;   │ (rail d&amp;#39;échec :  │         │   sera exécutée) │&#xA;   │  toute la chaîne │         └──────────────────┘&#xA;   │  devient no-op,  │&#xA;   │ tout en gardant  │&#xA;   │ l&amp;#39;API fluide)    │&#xA;   └──────────────────┘&#xA;              │&#xA;              ▼ (.failure → .success → .execute, tout en no-op)&#xA;   ┌──────────────────┐&#xA;   │  ActionChain[T]  │   has_failed=True, result=&amp;lt;le Fail accumulé&amp;gt;&#xA;   └──────────────────┘&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;les-types-action-failurehandler-succhandler&#34;&gt;Les types &lt;code&gt;Action&lt;/code&gt;, &lt;code&gt;FailureHandler&lt;/code&gt;, &lt;code&gt;SuccHandler&lt;/code&gt;&lt;a class=&#34;anchor&#34; href=&#34;#les-types-action-failurehandler-succhandler&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;type&lt;/span&gt; Action[T]        &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; Thunk[Result[T]]      &lt;span style=&#34;color:#6272a4&#34;&gt;# () -&amp;gt; Result[T]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;type&lt;/span&gt; FailureHandler   &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; Callable[[Exception], &lt;span style=&#34;color:#ff79c6&#34;&gt;None&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;type&lt;/span&gt; SuccHandler      &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; Effect                &lt;span style=&#34;color:#6272a4&#34;&gt;# () -&amp;gt; None&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;Action[T]&lt;/code&gt; est un &lt;code&gt;Thunk&lt;/code&gt;&lt;/strong&gt;. Cela veut dire qu&amp;rsquo;au moment où &lt;code&gt;ActionStart(action)&lt;/code&gt; est appelé, &lt;strong&gt;rien n&amp;rsquo;est exécuté&lt;/strong&gt;. L&amp;rsquo;action est juste capturée.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;FailureHandler&lt;/code&gt; reçoit l&amp;rsquo;exception&lt;/strong&gt;, mais ne reçoit &lt;strong&gt;pas&lt;/strong&gt; le &lt;code&gt;Fail&lt;/code&gt; ni le &lt;code&gt;Result&lt;/code&gt;. C&amp;rsquo;est volontaire : 99% des handlers veulent tracer l&amp;rsquo;exception, prendre un screenshot, et c&amp;rsquo;est tout.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;SuccHandler&lt;/code&gt; est un &lt;code&gt;Effect&lt;/code&gt;&lt;/strong&gt; (sans argument). Idem : un handler de succès log un message statique, fait un screenshot, pas besoin du résultat.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;typestate-pattern-pourquoi-on-ne-peut-pas-se-tromper&#34;&gt;Typestate Pattern : pourquoi on ne peut pas se tromper&lt;a class=&#34;anchor&#34; href=&#34;#typestate-pattern-pourquoi-on-ne-peut-pas-se-tromper&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;L&amp;rsquo;enchaînement est &lt;strong&gt;strictement linéaire&lt;/strong&gt;. Chaque méthode renvoie un type différent, qui n&amp;rsquo;expose que la &lt;em&gt;suite logique&lt;/em&gt; de l&amp;rsquo;enchaînement :&lt;/p&gt;</description>
    </item>
    <item>
      <title>01.03 — KISS et complexité ostentatoire</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/01-philosophy/03-kiss-and-complexity/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/01-philosophy/03-kiss-and-complexity/</guid>
      <description>&lt;h1 id=&#34;0103kiss-et-complexité-ostentatoire&#34;&gt;01.03 — KISS et complexité ostentatoire&lt;a class=&#34;anchor&#34; href=&#34;#0103kiss-et-complexit%c3%a9-ostentatoire&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;h2 id=&#34;la-critique-reçue&#34;&gt;La critique reçue&lt;a class=&#34;anchor&#34; href=&#34;#la-critique-re%c3%a7ue&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Le premier retour public reçu par Ocarina, &lt;em&gt;systématique&lt;/em&gt; d&amp;rsquo;après l&amp;rsquo;auteur :&lt;/p&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;La première « &lt;em&gt;critique&lt;/em&gt; » a souvent été la même : « &lt;em&gt;Tu te vantes de quelque chose qui est très simple.&lt;/em&gt; »&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;p&gt;Le Holy Book y répond longuement. Trois piliers : le &lt;strong&gt;caractère opérant&lt;/strong&gt; de la simplicité, la &lt;strong&gt;distinction simple ≠ peu élaboré&lt;/strong&gt;, et le &lt;strong&gt;refus de toutes les contre-propositions « &lt;em&gt;créatives&lt;/em&gt; »&lt;/strong&gt; reçues.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Chapitre 02 — Ocarina, le framework</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/</guid>
      <description>&lt;h1 id=&#34;chapitre-02ocarina-le-framework&#34;&gt;Chapitre 02 — Ocarina, le framework&lt;a class=&#34;anchor&#34; href=&#34;#chapitre-02ocarina-le-framework&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Ce chapitre dépile l&amp;rsquo;intégralité du framework &lt;code&gt;ocarina&lt;/code&gt; (Python 3.14+, version 1.1.10) ainsi que du Railway Oriented Programming jusqu&amp;rsquo;aux plugins de reporting. Il est structuré comme un parcours en couches : du &lt;strong&gt;plus profond&lt;/strong&gt; (le type &lt;code&gt;Result[T]&lt;/code&gt;) vers le &lt;strong&gt;plus visible&lt;/strong&gt; (le &lt;code&gt;bootstrap&lt;/code&gt; qui démarre tout).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;plan-du-chapitre&#34;&gt;Plan du chapitre&lt;a class=&#34;anchor&#34; href=&#34;#plan-du-chapitre&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th style=&#34;text-align: center&#34;&gt;#&lt;/th&gt;&#xA;          &lt;th&gt;Sujet&lt;/th&gt;&#xA;          &lt;th&gt;Fichier ou dossier&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;01&lt;/td&gt;&#xA;          &lt;td&gt;Identité technique, dépendances, &lt;em&gt;toolchain&lt;/em&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/01-identity/&#34;&gt;&lt;code&gt;01-identity.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;02&lt;/td&gt;&#xA;          &lt;td&gt;Arborescence complète du module + schéma en couches&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/02-module-tree/&#34;&gt;&lt;code&gt;02-module-tree.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;03&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Railway Oriented Programming&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/&#34;&gt;&lt;code&gt;03-railway/&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;04&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Invariants&lt;/strong&gt; (validate, assertions, chain_validations)&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/04-invariants/&#34;&gt;&lt;code&gt;04-invariants/&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;05&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Orchestration&lt;/strong&gt; (Test → TestSuite → TestCampaign → TestCycle)&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/05-orchestration/&#34;&gt;&lt;code&gt;05-orchestration/&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;06&lt;/td&gt;&#xA;          &lt;td&gt;Cycle de vie d&amp;rsquo;un &lt;code&gt;Scenario&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/06-scenario/&#34;&gt;&lt;code&gt;06-scenario.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;07&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Watcher&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/07-watcher/&#34;&gt;&lt;code&gt;07-watcher.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;08&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;POMBase&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/08-pom-base/&#34;&gt;&lt;code&gt;08-pom-base.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;09&lt;/td&gt;&#xA;          &lt;td&gt;Ports &amp;amp; adapters (&lt;code&gt;ILogger&lt;/code&gt;, &lt;code&gt;ITakeScreenshot&lt;/code&gt;)&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/09-ports/&#34;&gt;&lt;code&gt;09-ports.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;10&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Infrastructure&lt;/strong&gt; (pool, builder, screenshotter, act counter, adapters Selenium)&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/10-infra/&#34;&gt;&lt;code&gt;10-infra/&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;11&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Couche opinionated&lt;/strong&gt; (CLI, loggers, plugins, bootstrap)&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/11-opinionated/&#34;&gt;&lt;code&gt;11-opinionated/&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;12&lt;/td&gt;&#xA;          &lt;td&gt;Custom types &amp;amp; custom errors&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/12-custom-types-errors/&#34;&gt;&lt;code&gt;12-custom-types-errors.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;lectures-connexes&#34;&gt;Lectures connexes&lt;a class=&#34;anchor&#34; href=&#34;#lectures-connexes&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Programmation fonctionnelle : &lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/&#34;&gt;&lt;code&gt;../03-functional/&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;Comment le framework se teste lui-même : &lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/04-internal-tests/&#34;&gt;&lt;code&gt;../04-internal-tests/&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;Exemples d&amp;rsquo;usage avec adapters projet : &lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/07-ocarina-example/&#34;&gt;&lt;code&gt;../07-ocarina-example/&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/08-ai-example/&#34;&gt;&lt;code&gt;../08-ai-example/&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;CI : &lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/10-cicd/02-ocarina-workflows/&#34;&gt;&lt;code&gt;../10-cicd/02-ocarina-workflows.md&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>Chapitre 02.03 — Railway Oriented Programming</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/</guid>
      <description>&lt;h1 id=&#34;chapitre-0203railway-oriented-programming&#34;&gt;Chapitre 02.03 — Railway Oriented Programming&lt;a class=&#34;anchor&#34; href=&#34;#chapitre-0203railway-oriented-programming&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Le cœur d&amp;rsquo;Ocarina. Tout le DSL repose sur cette mécanique : représenter le succès et l&amp;rsquo;échec comme deux &lt;em&gt;rails parallèles&lt;/em&gt;, faire qu&amp;rsquo;un échec &lt;em&gt;bascule&lt;/em&gt; le train sur le rail d&amp;rsquo;échec, et l&amp;rsquo;y fait rester (court-circuit), préserver la composition syntaxique pour que le scénario reste lisible.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;plan&#34;&gt;Plan&lt;a class=&#34;anchor&#34; href=&#34;#plan&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th style=&#34;text-align: center&#34;&gt;#&lt;/th&gt;&#xA;          &lt;th&gt;Fichier&lt;/th&gt;&#xA;          &lt;th&gt;Sujet&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;01&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/01-result/&#34;&gt;&lt;code&gt;01-result.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;Result[T] = Ok[T] | Fail&lt;/code&gt;, &lt;code&gt;is_ok&lt;/code&gt;/&lt;code&gt;is_fail&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;02&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/02-action-chain-states/&#34;&gt;&lt;code&gt;02-action-chain-states.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Machine à états &lt;code&gt;ActionStart → ActionFailure → ActionSuccess → ActionChain&lt;/code&gt;.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;03&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/03-neutral-rail/&#34;&gt;&lt;code&gt;03-neutral-rail.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Rail d&amp;rsquo;échec : &lt;code&gt;NeutralActionStart&lt;/code&gt; / &lt;code&gt;NeutralActionFailure&lt;/code&gt; / &lt;code&gt;NeutralActionSuccess&lt;/code&gt;.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;04&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/04-chain-actions-fold/&#34;&gt;&lt;code&gt;04-chain-actions-fold.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;ChainRunner[T]&lt;/code&gt; (thunk) + &lt;code&gt;chain_actions&lt;/code&gt; (fold).&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;05&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/05-create-act-hooks/&#34;&gt;&lt;code&gt;05-create-act-hooks.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;create_act&lt;/code&gt; et ses hooks (&lt;code&gt;on_failure&lt;/code&gt;, &lt;code&gt;on_run_effect&lt;/code&gt;, &lt;code&gt;act_counter_effect&lt;/code&gt;).&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;06&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/06-drive-page/&#34;&gt;&lt;code&gt;06-drive-page.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;drive_page&lt;/code&gt;, alias sémantique.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;07&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/07-match-page-when/&#34;&gt;&lt;code&gt;07-match-page-when.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;match_page&lt;/code&gt; / &lt;code&gt;when&lt;/code&gt; + politique d&amp;rsquo;exceptions.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;filiation&#34;&gt;Filiation&lt;a class=&#34;anchor&#34; href=&#34;#filiation&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;L&amp;rsquo;inspiration directe est le &lt;strong&gt;Railway Oriented Programming&lt;/strong&gt; popularisé par Scott Wlaschin (F#).&lt;/p&gt;</description>
    </item>
    <item>
      <title>01.04 — Citations et influences revendiquées</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/01-philosophy/04-citations-and-influences/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/01-philosophy/04-citations-and-influences/</guid>
      <description>&lt;h1 id=&#34;0104citations-et-influences-revendiquées&#34;&gt;01.04 — Citations et influences revendiquées&lt;a class=&#34;anchor&#34; href=&#34;#0104citations-et-influences-revendiqu%c3%a9es&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Les références citées dans le Holy Book ne sont pas neutres : elles fixent &lt;strong&gt;le cadre théorique&lt;/strong&gt; d&amp;rsquo;Ocarina. On les recoupe ici par grands axes, puis on en propose une lecture d&amp;rsquo;ensemble.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;axe-techniqueprogrammation-fonctionnelle-types-langages&#34;&gt;Axe technique — Programmation fonctionnelle, types, langages&lt;a class=&#34;anchor&#34; href=&#34;#axe-techniqueprogrammation-fonctionnelle-types-langages&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Influence&lt;/th&gt;&#xA;          &lt;th&gt;Origine&lt;/th&gt;&#xA;          &lt;th&gt;Rapport avec Ocarina&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Railway Oriented Programming (ROP)&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Scott Wlaschin (F#), pattern bien connu en programmation fonctionnelle&lt;/td&gt;&#xA;          &lt;td&gt;Le cœur du framework. &lt;code&gt;Result[T] = Ok[T] | Fail&lt;/code&gt;, &lt;em&gt;short-circuit&lt;/em&gt;, builder fluide. Voir &lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/&#34;&gt;&lt;code&gt;../02-ocarina/03-railway/&lt;/code&gt;&lt;/a&gt;.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;λ-calcul (1930)&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Alonzo Church&lt;/td&gt;&#xA;          &lt;td&gt;Cité comme l&amp;rsquo;invention qui rend possible la « &lt;em&gt;formalisation propre&lt;/em&gt; » qu&amp;rsquo;Ocarina poursuit : « &lt;em&gt;Ce que l&amp;rsquo;on pensait depuis les années 1930, &lt;strong&gt;depuis l&amp;rsquo;invention du λ-calcul&lt;/strong&gt;, est enfin scalable à l&amp;rsquo;échelle que l&amp;rsquo;on aurait toujours voulu lui donner.&lt;/em&gt; »&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;McCulloch &amp;amp; Pitts (1943)&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Première formalisation du neurone artificiel&lt;/td&gt;&#xA;          &lt;td&gt;Cité comme rappel que les &lt;em&gt;vrais&lt;/em&gt; progrès en IA sont anciens et continus, contre la hype récente.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Système de types Python (PEP 695)&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;PEP 695 (Python 3.12+)&lt;/td&gt;&#xA;          &lt;td&gt;Pré-requis pour le typage générique paramétrique qui structure Ocarina (&lt;code&gt;TestSuite[Driver]&lt;/code&gt;, &lt;code&gt;Result[T]&lt;/code&gt;, etc.). Voir &lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/06-pep-695-generics/&#34;&gt;&lt;code&gt;../03-functional/06-pep-695-generics.md&lt;/code&gt;&lt;/a&gt;.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;axe-culturelanti-narcissisme-simplicité-kiss-bien-compris&#34;&gt;Axe culturel — Anti-narcissisme, simplicité, KISS bien compris&lt;a class=&#34;anchor&#34; href=&#34;#axe-culturelanti-narcissisme-simplicit%c3%a9-kiss-bien-compris&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Influence&lt;/th&gt;&#xA;          &lt;th&gt;Citation&lt;/th&gt;&#xA;          &lt;th&gt;Pourquoi&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Terry Davis&lt;/strong&gt; (« &lt;em&gt;le programmeur le plus intelligent qui ait jamais existé&lt;/em&gt; »)&lt;/td&gt;&#xA;          &lt;td&gt;« &lt;em&gt;Un idiot admire la complexité, un génie admire la simplicité, un physicien essaie de simplifier…&lt;/em&gt; »&lt;/td&gt;&#xA;          &lt;td&gt;Argumentaire anti-complexité ostentatoire ; pierre angulaire du chapitre « &lt;em&gt;Premiers retours&lt;/em&gt; ».&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Lao-Tseu&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;« &lt;em&gt;Pour avoir de la connaissance, ajouter des choses chaque jour. Pour avoir de la sagesse, enlever des choses chaque jour.&lt;/em&gt; »&lt;/td&gt;&#xA;          &lt;td&gt;Démarche de retrait : ce qui reste après élimination.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Antoine de Saint-Exupéry&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;« &lt;em&gt;La perfection est atteinte non pas lorsqu&amp;rsquo;il n&amp;rsquo;y a plus rien à ajouter, mais lorsqu&amp;rsquo;il n&amp;rsquo;y a plus rien à retirer.&lt;/em&gt; »&lt;/td&gt;&#xA;          &lt;td&gt;Reformulation occidentale du précédent. Clos le chapitre « &lt;em&gt;Premiers scénarios&lt;/em&gt; ».&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Alan Watts&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;« &lt;em&gt;La meilleure façon de résoudre un problème est souvent d&amp;rsquo;en sortir.&lt;/em&gt; »&lt;/td&gt;&#xA;          &lt;td&gt;Cité en fin du chapitre « &lt;em&gt;Premiers jutsus&lt;/em&gt; » : légitime un design qui &lt;em&gt;refuse&lt;/em&gt; certaines fonctionnalités (réactivité, async). Légitime la sortie de l&amp;rsquo;écosystème des &lt;em&gt;trucs de geeks&lt;/em&gt;.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Rainer Maria Rilke&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;« &lt;em&gt;Pour l&amp;rsquo;instant, vivez les questions…&lt;/em&gt; »&lt;/td&gt;&#xA;          &lt;td&gt;Clos le chapitre « &lt;em&gt;Premiers pas&lt;/em&gt; ». Posture envers la pratique : la maîtrise vient par l&amp;rsquo;usage.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Marcel Proust&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;« &lt;em&gt;Le style (…) est une question non de technique, mais de vision.&lt;/em&gt; »&lt;/td&gt;&#xA;          &lt;td&gt;Clos le chapitre « &lt;em&gt;Extensibilité&lt;/em&gt; ». Justifie le refus d&amp;rsquo;imposer un DSL : la vision (POMs + actions) prime sur la technique (un format).&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;axe-politiquecode-souveraineté-anti-startup-nation&#34;&gt;Axe politique — Code, souveraineté, anti-startup-nation&lt;a class=&#34;anchor&#34; href=&#34;#axe-politiquecode-souverainet%c3%a9-anti-startup-nation&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Influence&lt;/th&gt;&#xA;          &lt;th&gt;Origine&lt;/th&gt;&#xA;          &lt;th&gt;Rapport avec Ocarina&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;&lt;em&gt;Code is Law&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Lawrence Lessig (1999), repris par Ethereum (2015) comme idéal positif&lt;/td&gt;&#xA;          &lt;td&gt;Cité comme la posture face à la « &lt;em&gt;gouvernance démocratique du code&lt;/em&gt; ». Le code est la donnée brute, auditable. Le projet revendique : « &lt;em&gt;De nouveau, avec l&amp;rsquo;IA, ce maillon qu&amp;rsquo;il manquait cruellement, crions-le, aussi fort que l&amp;rsquo;on criait &amp;ldquo;HACK THE PLANET&amp;rdquo; en 99 : &lt;strong&gt;CODE IS LAW.&lt;/strong&gt;&lt;/em&gt; »&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;DHH — &lt;em&gt;I won&amp;rsquo;t let you pay me for my open source&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;David Heinemeier Hansson, blog perso&lt;/td&gt;&#xA;          &lt;td&gt;Cité pour légitimer le refus de contributions non alignées (« &lt;em&gt;Fuck You&lt;/em&gt; » fait référence à la célèbre slide de DHH.)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Paul Graham — &lt;em&gt;Haters&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Essai PG (&lt;code&gt;paulgraham.com/fh.html&lt;/code&gt;)&lt;/td&gt;&#xA;          &lt;td&gt;Justifie la décision de « &lt;em&gt;ne JAMAIS perdre [son] temps à argumenter lorsque ce n&amp;rsquo;est pas la peine&lt;/em&gt; ».&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Yegor Bugayenko — &lt;em&gt;Prompt&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Citation « &lt;em&gt;Retry flaky blocks.&lt;/em&gt; »&lt;/td&gt;&#xA;          &lt;td&gt;Fond la politique &lt;code&gt;transient_errors&lt;/code&gt; + retries linéaires (&lt;code&gt;TestFlow&lt;/code&gt;). Lire aussi : &lt;em&gt;Angry Tests&lt;/em&gt;.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;The DAO hack (2016)&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Hack de The DAO sur Ethereum&lt;/td&gt;&#xA;          &lt;td&gt;Cité pour pointer que ce sont &lt;em&gt;les bugs&lt;/em&gt; (« &lt;em&gt;des satanés bugs, à cause de satanés dévs&lt;/em&gt; ») qui ont fait reculer l&amp;rsquo;idée de &lt;em&gt;Code is Law&lt;/em&gt;, d&amp;rsquo;où l&amp;rsquo;importance du typage et de la rigueur.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Lee Robinson (ex-Vercel)&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Décembre 2025 : remplacement de Sanity par des fichiers Markdown + IA chez Cursor&lt;/td&gt;&#xA;          &lt;td&gt;Soutient le « &lt;em&gt;retour à la donnée brute&lt;/em&gt; ».&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Cluely (Roy Lee)&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Cité pour illustrer le &lt;em&gt;bullshit&lt;/em&gt; entrepreneurial à éviter&lt;/td&gt;&#xA;          &lt;td&gt;Contraste explicite avec la philosophie Ocarina.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;axe-identitaire-underground&#34;&gt;Axe identitaire / &lt;em&gt;underground&lt;/em&gt;&lt;a class=&#34;anchor&#34; href=&#34;#axe-identitaire-underground&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Influence&lt;/th&gt;&#xA;          &lt;th&gt;Origine&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Lulzsec&lt;/strong&gt; — « &lt;em&gt;In the Lulzboat, salute, bitch, and show some respect.&lt;/em&gt; »&lt;/td&gt;&#xA;          &lt;td&gt;Antisec (YTCracker, 2011)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;« &lt;em&gt;We Can Do All What You Can&amp;rsquo;t Do&lt;/em&gt; »&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;YogyaCarderLink&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;YTCracker — &lt;em&gt;Robots Will Definitely Take Your Job&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Lien SoundCloud, musique de fond du chapitre « &lt;em&gt;Premiers retours&lt;/em&gt; »&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;« &lt;em&gt;HACK THE PLANET&lt;/em&gt; » (1999)&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Slogan emblématique de la scène hackers des années 1990 + Antisec (YTCracker, 2011)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Zone-H&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Site historique de defaces web&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;r/unixporn&lt;/strong&gt;, &lt;strong&gt;r/AntiTaff&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Subreddits&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;axe-ia-outillage-moderne&#34;&gt;Axe IA / outillage moderne&lt;a class=&#34;anchor&#34; href=&#34;#axe-ia-outillage-moderne&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Influence&lt;/th&gt;&#xA;          &lt;th&gt;Origine&lt;/th&gt;&#xA;          &lt;th&gt;Rapport avec Ocarina&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Claude Code&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Anthropic&lt;/td&gt;&#xA;          &lt;td&gt;Outillage de référence du projet IA (&lt;code&gt;ocarina-with-ai-example&lt;/code&gt;). Cité plusieurs fois comme « &lt;em&gt;pont&lt;/em&gt; » remplaçant les DSLs.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;IntelliCode (2018)&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Microsoft&lt;/td&gt;&#xA;          &lt;td&gt;Cité comme repère temporel (« &lt;em&gt;on y avait déjà goûté, avant même IntelliCode&lt;/em&gt; »).&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;R., savant fou du silo&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Anecdote personnelle (un collègue de 2013, plugin Emacs IA privé)&lt;/td&gt;&#xA;          &lt;td&gt;Rappel que l&amp;rsquo;IA générative (« &lt;em&gt;15 000 lignes à supprimer pour éviter d&amp;rsquo;en écrire 1000&lt;/em&gt; ») existait avant la hype publique.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Prisma, Vercel, Cursor&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Écosystème SaaS&lt;/td&gt;&#xA;          &lt;td&gt;Cités comme cas pratiques de &lt;em&gt;retour à la donnée brute&lt;/em&gt; assisté par IA.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;cohérence-densemble&#34;&gt;Cohérence d&amp;rsquo;ensemble&lt;a class=&#34;anchor&#34; href=&#34;#coh%c3%a9rence-densemble&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Toutes ces influences pointent vers &lt;strong&gt;trois axes convergents&lt;/strong&gt; :&lt;/p&gt;</description>
    </item>
    <item>
      <title>02.03.04 — chain_actions et le ChainRunner</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/04-chain-actions-fold/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/04-chain-actions-fold/</guid>
      <description>&lt;h1 id=&#34;020304chain_actions-et-le-chainrunner&#34;&gt;02.03.04 — &lt;code&gt;chain_actions&lt;/code&gt; et le &lt;code&gt;ChainRunner&lt;/code&gt;&lt;a class=&#34;anchor&#34; href=&#34;#020304chain_actions-et-le-chainrunner&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Fichier source : &lt;a href=&#34;https://github.com/mojo-molotov/ocarina/blob/main/src/ocarina/dsl/testing_with_railway/chain_actions.py&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;src/ocarina/dsl/testing_with_railway/chain_actions.py&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;C&amp;rsquo;est la primitive qui rend le DSL « &lt;em&gt;plat&lt;/em&gt; ». Sans elle, un scénario à N pas serait un escalier de &lt;code&gt;.then(...).failure(...).success(...).execute()&lt;/code&gt;. Avec elle, c&amp;rsquo;est une liste.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;parenthesis-hell&#34;&gt;« &lt;em&gt;Parenthesis hell&lt;/em&gt; »&lt;a class=&#34;anchor&#34; href=&#34;#parenthesis-hell&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Solution :&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;# Flat, readable syntax&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;runner &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; chain_actions(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    action1&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;failure(h1)&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;success(h2),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    action2&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;failure(h3)&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;success(h4),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    action3&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;failure(h5)&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;success(h6)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chain &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; runner&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;run()  &lt;span style=&#34;color:#6272a4&#34;&gt;# Execute when ready&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Benefits :&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Lazy evaluation&lt;/strong&gt; : Build chain without executing&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Flat syntax&lt;/strong&gt; : No deep nesting&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Automatic short-circuiting&lt;/strong&gt; : Stops on first failure&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Composability&lt;/strong&gt; : ChainRunner is a value&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/blockquote&gt;&lt;p&gt;&lt;em&gt;(Extrait de docstring.)&lt;/em&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Chapitre 02.04 — Invariants</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/04-invariants/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/04-invariants/</guid>
      <description>&lt;h1 id=&#34;chapitre-0204invariants&#34;&gt;Chapitre 02.04 — Invariants&lt;a class=&#34;anchor&#34; href=&#34;#chapitre-0204invariants&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Sous-DSL d&amp;rsquo;Ocarina dédié à l&amp;rsquo;expression d&amp;rsquo;invariants typés et composables. Utilisé partout : par la CLI, par les POMs, par les &lt;code&gt;custom_invariants/testing/&lt;/code&gt; qui valident la cohérence des suites avant exécution.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;plan&#34;&gt;Plan&lt;a class=&#34;anchor&#34; href=&#34;#plan&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th style=&#34;text-align: center&#34;&gt;#&lt;/th&gt;&#xA;          &lt;th&gt;Fichier&lt;/th&gt;&#xA;          &lt;th&gt;Sujet&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;01&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/04-invariants/01-validate-flow/&#34;&gt;&lt;code&gt;01-validate-flow.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Le flot complet &lt;code&gt;validate(value) → assert_that → execute → raise_if_invalid&lt;/code&gt; + la classe &lt;code&gt;_ValidationChain&lt;/code&gt;.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;02&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/04-invariants/02-assertions/&#34;&gt;&lt;code&gt;02-assertions.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Catalogue des assertions builtin (&lt;code&gt;is_str&lt;/code&gt;, &lt;code&gt;is_email&lt;/code&gt;, &lt;code&gt;is_positive&lt;/code&gt;, &lt;code&gt;is_in&lt;/code&gt;, &lt;code&gt;has_unique_elements&lt;/code&gt;, &lt;code&gt;each&lt;/code&gt;, &lt;code&gt;is_valid_filename&lt;/code&gt;, …).&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;03&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/04-invariants/03-otherwise-any-of/&#34;&gt;&lt;code&gt;03-otherwise-any-of.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;.otherwise(...)&lt;/code&gt; et la combinaison OR via &lt;code&gt;_any_of&lt;/code&gt;.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;04&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/04-invariants/04-then-chain-of-validations/&#34;&gt;&lt;code&gt;04-then-chain-of-validations.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;.then(new_value)&lt;/code&gt; et &lt;code&gt;chain_validations(...)&lt;/code&gt; pour la composition.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;05&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/04-invariants/05-business-vs-framework-validator/&#34;&gt;&lt;code&gt;05-business-vs-framework-validator.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;BusinessInvariantValidator&lt;/code&gt; vs &lt;code&gt;FrameworkInvariantValidator&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;06&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/04-invariants/06-invariant-errors/&#34;&gt;&lt;code&gt;06-invariant-errors.md&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;InvariantViolationError&lt;/code&gt;, &lt;code&gt;DuplicatesError&lt;/code&gt;, &lt;code&gt;AggregateInvariantViolationError&lt;/code&gt;.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;le-pourquoi-du-dsl-dinvariants&#34;&gt;Le pourquoi du DSL d&amp;rsquo;invariants&lt;a class=&#34;anchor&#34; href=&#34;#le-pourquoi-du-dsl-dinvariants&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Garde-fou avant exécution.&lt;/strong&gt; &lt;code&gt;TestSuite.__init__&lt;/code&gt; valide &lt;em&gt;avant&lt;/em&gt; de lancer quoi que ce soit que les noms / IDs des tests sont uniques, que &lt;code&gt;max_workers &amp;gt;= 1&lt;/code&gt;, etc.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Validation CLI.&lt;/strong&gt; Chaque flag a son &lt;code&gt;validate=lambda chain: chain.assert_that(...)&lt;/code&gt; dans le &lt;code&gt;CliStore&lt;/code&gt;. Les erreurs s&amp;rsquo;agrègent et sortent en un seul message d&amp;rsquo;erreur.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Validation côté POM.&lt;/strong&gt; Les actions de POM peuvent valider leurs paramètres (« &lt;em&gt;&lt;code&gt;retries&lt;/code&gt; doit être positif&lt;/em&gt; ») via &lt;code&gt;validate(retries, name=&amp;quot;retries&amp;quot;).assert_that(is_positive).execute().raise_if_invalid()&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Le Holy Book le résume :&lt;/p&gt;</description>
    </item>
    <item>
      <title>02.03.06 — drive_page</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/06-drive-page/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/06-drive-page/</guid>
      <description>&lt;h1 id=&#34;020306drive_page&#34;&gt;02.03.06 — &lt;code&gt;drive_page&lt;/code&gt;&lt;a class=&#34;anchor&#34; href=&#34;#020306drive_page&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Fichier source : &lt;a href=&#34;https://github.com/mojo-molotov/ocarina/blob/main/src/ocarina/opinionated/dsl/drive_page.py&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;src/ocarina/opinionated/dsl/drive_page.py&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;code&#34;&gt;Code&lt;a class=&#34;anchor&#34; href=&#34;#code&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;drive_page&lt;/span&gt;(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    first: ActionSuccess[TPOM], &lt;span style=&#34;color:#ff79c6&#34;&gt;*&lt;/span&gt;rest: ActionSuccess[TPOM]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;) &lt;span style=&#34;color:#ff79c6&#34;&gt;-&amp;gt;&lt;/span&gt; ChainRunner[TPOM]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; chain_actions(first, &lt;span style=&#34;color:#ff79c6&#34;&gt;*&lt;/span&gt;rest)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;C&amp;rsquo;est &lt;strong&gt;exactement&lt;/strong&gt; &lt;code&gt;chain_actions&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;pourquoi-cet-alias&#34;&gt;Pourquoi cet alias ?&lt;a class=&#34;anchor&#34; href=&#34;#pourquoi-cet-alias&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;h3 id=&#34;1-sémantique-je-prends-le-contrôle-d&#34;&gt;1. Sémantique : « &lt;em&gt;je prends le contrôle d&amp;rsquo;une page&lt;/em&gt; »&lt;a class=&#34;anchor&#34; href=&#34;#1-s%c3%a9mantique-je-prends-le-contr%c3%b4le-d&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;Citation du Holy Book (&lt;em&gt;Premiers scénarios&lt;/em&gt;) :&lt;/p&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;&lt;code&gt;drive_page&lt;/code&gt; exprime que l&amp;rsquo;on prend le contrôle d&amp;rsquo;&lt;em&gt;une&lt;/em&gt; page.&#xA;Toute &lt;em&gt;transition&lt;/em&gt; devient explicite par l&amp;rsquo;ouverture d&amp;rsquo;un nouveau &lt;code&gt;drive_page&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    drive_page(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        act(on_homepage, open_homepage)&lt;span style=&#34;color:#ff79c6&#34;&gt;...&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        act(on_homepage, verify_homepage)&lt;span style=&#34;color:#ff79c6&#34;&gt;...&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        act(on_homepage, click_cta)&lt;span style=&#34;color:#ff79c6&#34;&gt;...&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ),                                          &lt;span style=&#34;color:#6272a4&#34;&gt;# ⬅ fermeture du contrôle de la homepage&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    drive_page(                                 &lt;span style=&#34;color:#6272a4&#34;&gt;# ⬅ ouverture du contrôle de la page suivante&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        act(on_target_page, verify_target_page)&lt;span style=&#34;color:#ff79c6&#34;&gt;...&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;2-discipline&#34;&gt;2. Discipline&lt;a class=&#34;anchor&#34; href=&#34;#2-discipline&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;Mélanger des actes sur deux POMs différents dans un même &lt;code&gt;drive_page&lt;/code&gt; devient une erreur &lt;em&gt;mypy&lt;/em&gt; (cf. &lt;a href=&#34;https://mojo-molotov.github.io/from-ocarina-to-igor/fr/02-ocarina/03-railway/02-action-chain-states/&#34;&gt;&lt;code&gt;02-action-chain-states.md&lt;/code&gt;&lt;/a&gt;, section « &lt;em&gt;narrowing par &lt;code&gt;act()&lt;/code&gt;&lt;/em&gt; »). Cela force concrètement à respecter la sémantique.&lt;/p&gt;</description>
    </item>
    <item>
      <title>03.07 — Unions discriminées &#43; TypeGuard &#43; @final = unions « sealed »</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/07-discriminated-unions-typeguards/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/07-discriminated-unions-typeguards/</guid>
      <description>&lt;h1 id=&#34;0307unions-discriminées--typeguard--final--unions-sealed&#34;&gt;03.07 — Unions discriminées + TypeGuard + @final = unions « &lt;em&gt;sealed&lt;/em&gt; »&lt;a class=&#34;anchor&#34; href=&#34;#0307unions-discrimin%c3%a9es--typeguard--final--unions-sealed&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Le combo qui rend &lt;code&gt;Result[T]&lt;/code&gt; et &lt;code&gt;TestResult&lt;/code&gt; à la fois &lt;strong&gt;typés&lt;/strong&gt; et &lt;strong&gt;utilisables sans cast&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;union-discriminée&#34;&gt;Union discriminée&lt;a class=&#34;anchor&#34; href=&#34;#union-discrimin%c3%a9e&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@final&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@dataclass(frozen&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;Ok&lt;/span&gt;[T](_BaseResult):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    value: T&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error: &lt;span style=&#34;color:#ff79c6&#34;&gt;None&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;None&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@final&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@dataclass(frozen&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;Fail&lt;/span&gt;(_BaseResult):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error: Exception &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; field(default_factory&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;lambda&lt;/span&gt;: Exception(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Unknown error&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;type&lt;/span&gt; Result[T] &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; Ok[T] &lt;span style=&#34;color:#ff79c6&#34;&gt;|&lt;/span&gt; Fail&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;Deux constructeurs : &lt;code&gt;Ok[T]&lt;/code&gt; et &lt;code&gt;Fail&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Le &lt;em&gt;discriminant&lt;/em&gt; est l&amp;rsquo;&lt;em&gt;isinstance check&lt;/em&gt; (pas un champ comme &lt;code&gt;tag: Literal[&amp;quot;ok&amp;quot;, &amp;quot;fail&amp;quot;]&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;Les deux sont &lt;code&gt;@final&lt;/code&gt; : &lt;em&gt;aucun&lt;/em&gt; sous-type possible. → l&amp;rsquo;union est &lt;strong&gt;exhaustive&lt;/strong&gt;, donc « &lt;em&gt;sealed&lt;/em&gt; ».&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;narrowing-typeguard&#34;&gt;Narrowing, &lt;code&gt;TypeGuard&lt;/code&gt;&lt;a class=&#34;anchor&#34; href=&#34;#narrowing-typeguard&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;is_ok&lt;/span&gt;[T](result: Result[T]) &lt;span style=&#34;color:#ff79c6&#34;&gt;-&amp;gt;&lt;/span&gt; TypeGuard[Ok[T]]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;isinstance&lt;/span&gt;(result, Ok)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;is_fail&lt;/span&gt;[T](result: Result[T]) &lt;span style=&#34;color:#ff79c6&#34;&gt;-&amp;gt;&lt;/span&gt; TypeGuard[Fail]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;isinstance&lt;/span&gt;(result, Fail)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;handle_result&lt;/span&gt;(result: Result[&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;int&lt;/span&gt;]) &lt;span style=&#34;color:#ff79c6&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;str&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;if&lt;/span&gt; is_ok(result):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Got: &lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;{&lt;/span&gt;result&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;value&lt;span style=&#34;color:#f1fa8c&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&lt;/span&gt;          &lt;span style=&#34;color:#6272a4&#34;&gt;# mypy : result est Ok[int], donc .value existe&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;if&lt;/span&gt; is_fail(result):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Error: &lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;{&lt;/span&gt;result&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;error&lt;span style=&#34;color:#f1fa8c&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&lt;/span&gt;        &lt;span style=&#34;color:#6272a4&#34;&gt;# mypy : result est Fail, donc .error existe&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6272a4&#34;&gt;# mypy peut détecter que cette branche est inatteignable (exhaustivité)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;_baseresult&#34;&gt;&lt;code&gt;_BaseResult&lt;/code&gt;&lt;a class=&#34;anchor&#34; href=&#34;#_baseresult&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;_BaseResult&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error: Exception &lt;span style=&#34;color:#ff79c6&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Cette base permet d&amp;rsquo;accéder à &lt;code&gt;result.error&lt;/code&gt; &lt;strong&gt;sans narrower&lt;/strong&gt; :&lt;/p&gt;</description>
    </item>
    <item>
      <title>12.13 — Lambda-calcul, ROP, Haskell / F# / OCaml, monades</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/12-manifesto-deciphered/13-lambda-calculus-rop-origins/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/12-manifesto-deciphered/13-lambda-calculus-rop-origins/</guid>
      <description>&lt;h1 id=&#34;1213lambda-calcul-rop-haskell-f-ocaml-monades&#34;&gt;12.13 — Lambda-calcul, ROP, Haskell / F# / OCaml, monades&lt;a class=&#34;anchor&#34; href=&#34;#1213lambda-calcul-rop-haskell-f-ocaml-monades&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Ocarina n&amp;rsquo;invente rien sur le plan théorique. Il &lt;strong&gt;applique&lt;/strong&gt; : du &lt;strong&gt;lambda-calcul&lt;/strong&gt; d&amp;rsquo;Alonzo Church (1936) aux &lt;strong&gt;monades&lt;/strong&gt; d&amp;rsquo;Eugenio Moggi (1989) et Philip Wadler (1992-95), formalisé en tant que &lt;strong&gt;Railway Oriented Programming&lt;/strong&gt; par Scott Wlaschin (2014).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;1-lambda-calcul-church-1936&#34;&gt;1. Lambda-calcul (Church, 1936)&lt;a class=&#34;anchor&#34; href=&#34;#1-lambda-calcul-church-1936&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;h3 id=&#34;définition&#34;&gt;Définition&lt;a class=&#34;anchor&#34; href=&#34;#d%c3%a9finition&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;Le &lt;strong&gt;lambda-calcul&lt;/strong&gt; (λ-calcul) est un système formel inventé par &lt;strong&gt;Alonzo Church&lt;/strong&gt; (1903-1995) pour étudier la &lt;strong&gt;calculabilité&lt;/strong&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>12.15 — Typage, ISTQB, Reinforcement Learning, probes : pourquoi l&#39;IA marche dans Ocarina</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/12-manifesto-deciphered/15-typing-ai-rl-probes/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/12-manifesto-deciphered/15-typing-ai-rl-probes/</guid>
      <description>&lt;h1 id=&#34;1215typage-istqb-reinforcement-learning-probes-pourquoi-lia-marche-dans-ocarina&#34;&gt;12.15 — Typage, ISTQB, Reinforcement Learning, &lt;em&gt;probes&lt;/em&gt; : pourquoi l&amp;rsquo;IA marche dans Ocarina&lt;a class=&#34;anchor&#34; href=&#34;#1215typage-istqb-reinforcement-learning-probes-pourquoi-lia-marche-dans-ocarina&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Pourquoi tant d&amp;rsquo;&lt;strong&gt;obsession&lt;/strong&gt; pour le typage strict, la formalisation de chaque interface, l&amp;rsquo;alignement sur l&amp;rsquo;&lt;strong&gt;ISTQB&lt;/strong&gt;, le refus d&amp;rsquo;exécuter une assertion sans avoir &lt;em&gt;observé&lt;/em&gt; ? Le mécanisme est emprunté au &lt;strong&gt;Reinforcement Learning&lt;/strong&gt; : un agent ne progresse que sous &lt;strong&gt;contrainte&lt;/strong&gt; + &lt;strong&gt;signal de récompense&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;1-un-llm-nu-nest-quun-mauvais-collaborateur&#34;&gt;1. Un LLM nu n&amp;rsquo;est qu&amp;rsquo;un mauvais collaborateur&lt;a class=&#34;anchor&#34; href=&#34;#1-un-llm-nu-nest-quun-mauvais-collaborateur&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Un LLM sans environnement structuré est :&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
