Summary

When working with an AI agent like Opencode on complex projects across multiple sessions, you face a fundamental problem:the context leak. The agent does not remember the previous session. Everything that was explained to them — the architecture, the conventions, the state of the backlog — is lost. Reconstructing this context each session is costly, slow, and a source of error.

This article sets out the artisanal strategy I built to solve this problem: a persistent governance system based on AsciiDoc files, with a dichotomyEager/Lazyto optimize context token consumption, and aessential end-of-session procedureto ensure continuity.

The Scene: Monday 21 April, 9:00

I reopen Opencode to resume my Gradle plugin.plantuml-plugin. Last night, I spent three hours discussing with the API key pool architecture agent — round-robin rotation, quota management, automatic fallback. This morning, the agent looks at me with goldfish eyes.

_ Hello, I am your Opencode assistant. How can I help you today? _

No — Ah yes, the API key pool, we were at the YAML structure. No — Attention,PlantumlManager`is a Kotlin singleton object, not a class. No — No, we decided yesterday that`SyntaxValidationResult`there remained a nested sealed class in`PlantumlService.

Everything has to be redone. Or rather: everything has to be re‑explained. I will spend the first twenty minutes of my session reconstructing a context that the agent already had in hand yesterday. Twenty minutes of burned tokens. Twenty minutes where I could be coding, but I am doing mandatory pedagogical work.

It’s not a bug in Opencode. It’s the very nature of conversational LLMs: between two sessions, the working memory iscompletely erased. The agent does not remember the previous mission, the decisions taken, the identified pitfalls, the code we wrote together.

I’ve experienced that dozens of times. On four simultaneous projects. With sessions that chain over weeks. I calculated: on average,30-40% of session timewas dedicated to recontextualizing the agent. At session 87 of the project`plantuml-plugin`, I cracked. I could no longer afford to explain for the tenth time that`AttemptEntry`is a top-level data class in`DiagramProcessor.kt`.

I needed a system. Not a hack. Real governance.

Genesis: From Chaos to Method

The Early Sessions: The Age of Darkness

My first project with Opencode,plantuml-plugin, started without any governance. I ask a question, the agent answers, we iterate, the session ends, and the next day we start from zero. It was session 1, then 2, then 3…​ up to session 62 where I realized I had lost cumulative hours re-explaining the same architecture.

At session 62, the numbers are there:198 unit tests pass, 42 functional tests validated, the plugin works. But the cognitive cost is unbearable. Each new session begins with a twenty-minute monologue on the project structure.

The Destroyed Episode of site.yml (Session 2, bakery-plugin)

The method also arises from a catastrophe. On the project`bakery-gradle`, at session 2, I ask the agent to modify the file`site.yml`. The agent, without checking whether the file is versioned, makes a`Write`complete that overwrites the content. Result: the real tokens (Firebase API keys, deployment secrets) are replaced with fake placeholders. The file wasn’t in git — it was in`.gitignore`to protect the secrets.

Without backup. Without`git restore`possible. I am stuck. I need to manually rebuild the configuration file, retrieve the tokens from my password managers, and put everything back together.

It is from this frustration that theAbsolute Rule 1b:

_ Never crusha config file with a`Write`complete when a`Edit`Partial suffices.Never replacesensitive values with dummy values.Check git check-ignore and `git ls-filesbefore any modification. _

This rule, now etched in stone in all my files`AGENT.adoc` et `INDEX.adoc`on four projects, was born from a real error that cost me an hour of manual work.

The Markdown → AsciiDoc Migration (Session 1, cheroliv.com)

On April 25, 2026, on`cheroliv.com`, I am making a radical decision: converting the entirety of Markdown governance to AsciiDoc. It’s not aesthetic. It’s functional. AsciiDoc offers a semantic structure that LLMs read better: hierarchical sections, typed tables, admonitions (NOTE, WARNING, CAUTION), machine-readable document attributes.

The session 1 of`cheroliv.com`formalize the structure :

  • Conversion of`AGENTS.md` en AGENT.adoc

  • Creating the specialized agents:`CODER.adoc`, SCRUM_MASTER.adoc, PLANTUML_DESIGNER.adoc

  • Creation of the Eager/Lazy structure:`INDEX.adoc`, SESSIONS_HISTORY.adoc, AGENT_SESSION_MANAGER.adoc, SESSION_CHECKLIST.adoc, PROCEDURES.adoc

Only one commit:`90975e9 refactor: migrate agent governance from Markdown to AsciiDoc`. And the site continues to operate.

@startuml
skinparam backgroundColor #FEFEFE
skinparam handwritten false

title Evolution of Sessions — From Session 1 to 150+
legend top
    |= Couleur |= Projet |
    | <#4CAF50> | cheroliv.com |
    | <#2196F3> | plantuml-plugin |
    | <#FF9800> | bakery-plugin |
    | <#9C27B0> | magic-stick |
endlegend

concise "Active Sessions" as S

@S
0 is "raw .md"
1 is "Migration\nAsciiDoc"
10 is "Eager/Lazy\nformalized"
62 is "Safety rule\n(site.yml)"
87 is "Cracking\ncontext"
109 is "Optimization\n-60% tokens"
133 is "133 sessions\n240 tests PASS"

S@0 -> S@1 : Session 1\n(cheroliv.com)
S@1 -> S@10
S@10 -> S@62 : Session 62\n(plantuml-plugin)
S@62 -> S@87 : Session 87\n(Cry 4 help)
S@87 -> S@109 : Session 109\n(API Key Pool)
S@109 -> S@133 : Session 133\n(Aujourd'hui)

@enduml

The timeline above illustrates the real progression. The tipping point is session 87: that’s where the frustration of repeated recontextualization exceeds the tolerance threshold, and the Eager/Lazy method ceases to be an idea and becomes an obligation.

The Strategy: Eager/Lazy in Depth

Philosophy : Computer Cache Applied to Cognition

My approach is directly inspired by computer cache management. Everything that iscritical and frequently usedmust be immediately accessibleEager). Everything that iscontextual or bulkymust be loaded on demandLazy).

Eager (Dashboard)

Lazy (Owner’s Manual)

Size

< 100 lines, < 10k tokens

Unlimited, detailed

Loading

Auto, at the beginning of the session

At the request of the agent

Content

Absolute rules, current mission, critical state

Session archives, complete history, detailed procedures, technical references

Role

Orient the agent immediately

Answer deep context questions

Eager Files: The Dashboard

These files live at the root of each project and are automatically loaded by the agent at the start of each session. They form thedashboard-- critical information, immediately accessible.

@startuml
skinparam defaultTextAlignment center
skinparam wrapWidth 200

package "Project Root (Eager - Auto-loaded)" {
    component "<b>AGENT.adoc</b>\nAbsolute rules\nStructure & Conventions" as AGENT
    component "<b>PROMPT_REPRISE.adoc</b>\nMission of session N\nSummary N-1" as PROMPT
    component "<b>INDEX.adoc</b>\nEntry point\nRules + Sessions" as INDEX
    component "<b>*_ESSENTIALS.adoc</b>\nCritical business context" as ESS
}

package ".agents/ (Lazy - Loaded on demand)" {
    component "<b>sessions/N-*.adoc</b>\nDetailed archives\nDecisions & Output" as SESS
    component "<b>SESSIONS_HISTORY.adoc</b>\nSummary table\nDate/Type/Score" as HIST
    component "<b>PROCEDURES.adoc</b>\nEnd-of-session templates\n6 steps\n" as PROC
    component "<b>*_REFERENCE.adoc</b>\nComplete architecture\nTechnical references" as REF
    component "<b>COMPLETED_TASKS_ARCHIVE</b>\nCompleted tasks\nBy month" as ARCH
    component "<b>AGENT_MODUS_OPERANDI.adoc</b>\nStrategy documentation\nMethodology" as MOD
    component "<b>*_REFERENCE.adoc</b>\nBoot tests, A/B partition\nSpecific contexts" as SPEC
}

AGENT --> PROMPT : "References"
AGENT --> INDEX : "References"
INDEX --> SESS : "Index"
INDEX --> HIST : "Index"
INDEX --> PROC : "Reference"
INDEX --> ARCH : "Reference"
INDEX --> REF : "Reference"
PROMPT --> SESS : "Archive N-1"
PROMPT --> ESS : "Business context N"

@enduml

AGENT.adoc-- The master file. On`cheroliv.com`, it is 200 lines long and contains :

  • The absolute rules of the project (no commit without permission, no`rm`without confirmation)

  • The project structure and code conventions

  • The essential commands (./gradlew serve, ./gradlew test)

  • The epics and the product backlog (prioritized user stories)

  • The cross-cutting quality criteria (accessibility, responsive, compatibility)

On`bakery-plugin`, Rule 0 is different :./gradlew -q publishToMavenLocal` mandatory after each source code change. Because testing the plugin without republishing the local JAR cost me an hour debugging code that wasn’t yet packaged.

PROMPT_REPRISE.adoc-- The mission of the current session. Updated at the end of each session, it contains:

  • The session number and the priority mission

  • The summary of the previous session (what has been done, what remains to be done)

  • The acceptance criteria of the current session

  • The specific technical reminders

.agents/INDEX.adocThe entry point. It summarizes the absolute rules, recent sessions, and especially theproject portfoliomanaged using the same methodology. To date, five projects are listed there:

----
----
----
| 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`** -- A recent addition (Session 109, plantuml-plugin) to further optimize the Eager context. Instead of loading 200 lines of business context on the API key pool, I load 50 lines of the essential, and the remaining 150 lines stay LAZY in`*_REFERENCE.adoc`.

Measured result: passage of**~25k tokens EAGER to ~10k tokens**(60% gain). The agent no longer needs energy-consuming reminders.

==== The Missing Link: `opencode.json

I must confess something I almost forgot to document. Above all these .adoc files, there is a tiny JSON file without which nothing works. It's called`opencode.json`and it is six lines. Literally six lines.

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

This file tells Opencode: "At startup, load`AGENT.adoc`Automatically. Without him, the agent is a blank page exactly as I described at the beginning of the article. With him, the agent already has in hand the absolute rules, the project architecture, and the essential commands — even before I say hello.

I discovered the importance of this file by chance. On`bakery-plugin`, it did not exist. I was wondering why the agent was systematically more 'lost' on this project than on the others. The absolute rules were well in`AGENT.adoc`— but`AGENT.adoc`It was never loaded. The agent only read what I told him to read, manually, each session. This was session 11 of`bakery-plugin`when I realized the absence of the`opencode.json`. I created it — and session 12 started like the others.

This file is so obvious to me now that I wasn't even thinking about it anymore. A classic mistake of a developer who knows their tool too well. Nowadays, I systematically create it *before`AGENT.adoc`. This is the first stone.

==== The Duality of `INDEX.adoc

Another subtlety that deserves to be clarified:`INDEX.adoc`lives in`.agents/`— a folder that I presented as LAZY. However, I list it as EAGER in all my tables. There is an apparent tension here.

The field reality: the files`.agents/INDEX.adoc`are automatically loaded correctly at the beginning of the session, just as`AGENT.adoc` et `PROMPT_REPRISE.adoc`. They are in`.agents/`for organizational reasons — not to invade the root — but their behavior is EAGER.

on`plantuml-plugin`, `INDEX.adoc`is 200 lines long and contains the absolute *complete* rules with their history (the lessons from past sessions), the EPICs with scores, and the project portfolio. It is the document the agent consults to know 'where we stand'. Sur`bakery-plugin`, it makes 150 lines with the roadmap and recent sessions.

The deliberate redundancy between`AGENT.adoc` et `INDEX.adoc`can be surprising. The absolute rules are present in both. Why? Because they fulfill two different roles: in`AGENT.adoc`, they are *explanatory* (the storytelling of the rule, the lesson learned) ; in`INDEX.adoc`, they are *executive* (the naked rule, without justification, for a quick consultation). The agent reads`AGENT.adoc`once to *understand*; he rereads`INDEX.adoc`for each session to *apply*. Two uses, two formats.

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

title Duality AGENT.adoc ←→ INDEX.adoc
left to right direction

rectangle "AGENT.adoc
(Root — EAGER)" as AGENT #E3F2FD {
  rectangle "📖 **Narrative Format**
The storytelling of the rule
the lesson learned, the contexte

Wait, "le contexte" translates to "the context". So correct:

📖 **Narrative Format**
The storytelling of the rule
the lesson learned, the context

Check: original third line: "la leçon apprise, le contexte". Yes translation: "the lesson learned, the context". Output that.

</think>

�📖 **Narrative Format**
The storytelling of the rule
the lesson learned, the context" as NARR
  rectangle "🏗️ **Complete Architecture**
Project structure, components
Detailed US backlog" as ARCHI
  rectangle "�📋 **Explanatory Rules**
Why the rule exists
Incident history" as EXPL
}

rectangle "INDEX.adoc\n(.agents/ — EAGER)" as INDEX #E8F5E9 {
  rectangle "�⚡ **Executive Format**
The naked rule, without justification
Quick consultation" as EXEC
  rectangle "📊 **Roadmap & EPICs**\nSummary table\nProgress, Score, Priority" as ROAD
  rectangle "�🌐 **Projects Portfolio**
Cross‑sectional view
5 synchronized projects" as PORT
}

AGENT --> INDEX : "Agent reads AGENT.adoc\nonce to understand"
INDEX --> AGENT : "Agent re-reads INDEX.adoc\n each session to **apply**"

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
----

This assumed redundancy is a design choice. It consumes about 50 extra lines of EAGER tokens — but it ensures that the agent always has the rules in view, even in the concise format that facilitates immediate obedience.

=== The LAZY Files: The Owner's Manual

These files live in`.agents/`and are read only when the agent needs them. They constitute the true wealth of the method, because they accumulate the project's knowledge without polluting the current context.

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

folder ".agents/" as ROOT {
  file "INDEX.adoc
(EAGER -- 200 lines)" as IDX #E8F5E9
  file "AGENT_SESSION_MANAGER.adoc
(Template session)" as ASM
  file "SESSION_CHECKLIST.adoc\n(When to change)" as CHK
  file "PROCEDURES.adoc\n(6 steps + LAZY/EAGER)" as PRO
  file "SESSIONS_HISTORY.adoc\n(All sessions)" as HIS

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

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

IDX --> SESS : "Indexes"
IDX --> HIS : "Indexes"
IDX --> ARCH : "Reference"

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

@enduml
----

The tree structure above shows the real structure of the folder`.agents/`on`plantuml-plugin`, the most mature project. Note the depth in three layers: root files (metadata), folder`sessions/`(chronological archives), and file`archives/`(aggregations and summaries). It is this depth that transforms governance from a simple TODO file into a**complete organizational memory**.

**.agents/sessions/{N}-{title}.adoc**-- The detailed archives of each session. Currently:

* `plantuml-plugin`:**133 archived sessions**(from session 1 to 133)
* `bakery-plugin`:**11 sessions**
* `magic-stick` : **23 sessions**
* `cheroliv.com` : **9 formal sessions**+ 7 pre-system sessions reconstructed retroactively

Each archive contains the full context of the session, the decisions made, the problems encountered and their resolution, the executed commands and their output.

**.agents/SESSIONS_HISTORY.adoc**-- A summary table of all sessions with a score. Example on`cheroliv.com`:

----

| -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

**.agents/COMPLETED_TASKS_ARCHIVE_{mois}.adoc**-- Completed tasks archived by month, to avoid overloading the active backlog. When a user story is finished, it moves here. The backlog remains readable: maximum 10 active items.

**.agents/PROCEDURES.adoc**-- Detailed templates of the end-of-session procedure. Long, but read only once by the agent when learning the method. Then the procedure becomes mechanical.

**.agents/AGENT_MODUS_OPERANDI.adoc**-- The complete strategic documentation. On`plantuml-plugin`, this file does**900+ lines**and is actually called`AGENT_METHODOLOGIES.adoc`— I changed the name between writing this article and its effective implementation. This kind of naming divergence is inevitable in an evolving handmade system. The important thing is the naming convention: if the file documents the *method*, it starts with`AGENT_`or an explicit prefix. It documents the Eager/Lazy methodology, the patterns to follow, the anti-patterns to avoid. It is LAZY because an agent does not need to reread the entire strategy in each session, only when there is ambiguity.

**`*_REFERENCE.adoc`** -- Project specific technical references. Sur`magic-stick`, two dense LAZY files:

* `AB_PARTITION_REFERENCE.adoc`(147 lines) -- GPT A/B partition architecture, scripts`update-system.sh`, estimated sizes, rollback mechanism
* `BOOT_TEST_REFERENCE.adoc`(144 lines) -- QEMU + VNC procedure to test boot of the ISO without physical hardware, BIOS/UEFI checklist, CI/CD limitations

On`plantuml-plugin`(Empty output)

* `ARCHITECTURE.adoc`(134 lines) -- Structure of the 11 data classes, points of attention (pitfalls to avoid), optimized test commands
* `API_KEY_POOL_REFERENCE.adoc`-- Full details of the key pool (LAZY while`ESSENTIALS`is EAGER)

== Specialized Agents: A Virtual Team

Governance is not limited to passive files. I have formalized**roles of specialized agents**in dedicated LAZY files, which define the expected workflow according to the task type.

|===
|Agent |File |Role |Project |**to code** |`CODER.adoc` |Implementation FTL/CSS/JS, semantic tags, accessibility criteria |cheroliv.com |**Scrum Master** |`SCRUM_MASTER.adoc` |US planning, sub-task breakdown, dependency detection |cheroliv.com |**PlantUML Designer** |`PLANTUML_DESIGNER.adoc` |Diagram creation, PUML syntax, JBake integration |cheroliv.com
|===

The file`CODER.adoc`on`cheroliv.com`contains concrete rules: _one`<h1>`per page_, _Prefix paths with`${content.rootpath}`_, _Declare language`<html lang="${content.lang!"fr"}">`_. These conventions, written once, are automatically respected by the agent since session 1.

The file`SCRUM_MASTER.adoc`imposes a deliverable structure :**Objective**, **Tasks**(coordinates with assignment),**Acceptance criteria**, **Risks**. When I ask for an action plan, the agent produces this structure without me having asked for it. The governance**program**the agent.

==== When Specialized Agents Become Indispensable

The creation of specialized agents follows a natural curve. At the beginning of a project, you don't need them —`AGENT.adoc`is more than enough. But when the project grows (let's say, beyond 20 sessions), two signals must alert you :

1. The agent mixes the conventions of two distinct fields (e.g., PlantUML syntax and CSS rules)
2. You spend more time correcting the agent on conventions that you have already explained to him 5 times.

On`cheroliv.com`, it happened during the session... 1. Yes, right from the start. Because this project is a website with three languages (FTL, CSS, JS), AsciiDoc content, and PlantUML diagrams — three domains that have nothing to do with each other. The CODER agent needs to know font sizes and media queries; the PLANTUML_DESIGNER agent needs to know the`@startuml`. Without separation, the CODER agent was proposing diagrams to me, and vice versa. The chaos.

On`jhipster-gradle-plugins`, I created two specialized agents adapted for Gradle plugin development:`PLUGIN_DEVELOPER.adoc` et `BACKLOG_MANAGER.adoc`. The first encodes all Kotlin/Gradle conventions (no`!!`python import sys

def main(): data = sys.stdin.read() parts = data.split('`') for i in range(len(parts)): if i % 2 == 0:  # outside backticks parts[i] = parts[i].replace("pour", "for").replace("les", "the").replace("modèles", "models") sys.stdout.write('`'.join(parts))

if __name__ == '__main__': main()`@TaskAction`for the tasks). The second knows that`persistence`must be stable before`assistant`doesn't start its development — a critical dependency in a monorepo.

The mistake not to make: create too many agents too early.`plantuml-plugin`It waited for session 108 before formalizing a specialized agent for the API key pool. Before that, the business context was contained in`AGENT.adoc`. The rule of thumb: a specialized agent is justified when its business domain exceeds 100 lines of documentation.

==== The Session Naming Convention

A detail that seems trivial but becomes critical when you reach 100 sessions. How to name the archive files?

I learned the hard way that a convention is necessary — four projects, four different formats at the start, and I got lost. Today, the convention I have settled on is:

----

{N}-{type}-{sujet-kebab-case}.adoc

Concrete examples :

* `1-chore-migration-gouvernance-agent.adoc`— session 1, type chore
* `10-solidification-tests.adoc`— session 10, without explicit type (the subject suffices)
* `036-debug-graphify-symlink-epic9.adoc`— session 36 with 3-digit number for sorting

The session number is the primary sorting criterion. Projects using three‑digit numbers (001, 036, 133) avoid lexical sorting problems when exceeding 99. This is what I now use on`magic-stick`:`001-init-projet.adoc`, `036-debug-graphify-symlink-epic9.adoc`.

The type is optional and derived from the session keywords (debug, feature, refactor, docs, chore, test). The subject in kebab-case is the most important part: it must allow retrieving a session without opening the file. If you wonder « which session was it where we fixed the timeout of the integration tests? », the answer is`124-fix-timeout-integration-test.adoc`.

For reconstructed historical sessions (projects born before governance), I use negative numbers. On`cheroliv.com`, the sessions -6 to 0 cover the entire pre-governance history of the project. And for the "undocumented" or lost sessions, I create an entry in`SESSIONS_HISTORY.adoc`without a matching archive, with a score`?`. It's more honest than pretending.

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

title Session Naming Convention
start

:Une session se termine;
note right: Trigger "end of session"

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 > 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'honnêteté\nplutôt que le vide
endif

stop
@enduml
----

==== TEST_COVERAGE_ANALYSIS.adoc` — Step 5 Dissected

Step 5 of the session end procedure is the most mysterious. It says 'Update`TEST_COVERAGE_ANALYSIS.adoc`if tests have been added or modified. » But what does this file look like ?

on`plantuml-plugin`, it has evolved from a few lines to a complete structure. Here is its stabilized form:

[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%
|===
----

The interest is not the file itself — it's the obligation to *note* what has changed. Without this step, after 50 sessions, you no longer know which tests cover what. The agent doesn't either. The file becomes the single source of truth for the project's test coverage.

For projects without traditional tests (like`magic-stick`who tests bash scripts), step 5 is replaced by`SCRIPT_VERIFICATION.adoc`. The mechanism is the same: a file that tracks the validation state of the scripts. Adapt step 5 to your project, but never skip it. It is the safety net that prevents silent regression.

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

title Duality AGENT.adoc ←→ INDEX.adoc
left to right direction

rectangle "AGENT.adoc\n(Root — EAGER)" as AGENT #E3F2FD {
  rectangle "📖 **Narrative Format**\nThe storytelling of the rule\nthe lesson learned, the context" as NARR
  rectangle "🏗️ **Complete Architecture**\nProject structure, components\nDetailed US backlog" as ARCHI
  rectangle "📋 **Explanatory Rules**\nWhy the rule exists\nHistory of the incident" as EXPL
}

rectangle "INDEX.adoc\n(.agents/ — EAGER)" as INDEX #E8F5E9 {
  rectangle "⚡ **Executive Format**\nThe bare rule, without justification\nQuick consultation" as EXEC
  rectangle "📊 **Roadmap & EPICs**\nSummary table\nProgress, Score, Priority" as ROAD
  rectangle "🌐 **Project Portfolio**\nCross-functional view\n5 synchronized projects" as PORT
}

AGENT --> INDEX : "Agent reads AGENT.adoc\nonce to **understand**"
INDEX --> AGENT : "Agent rereads INDEX.adoc\neach session to **apply**"

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
----

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

start

:Début session;
note right: L'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
----

The diagram above shows the full lifecycle of a session. The key point is the split after the EAGER loading: either the mission is clear enough to execute directly (80% of cases), or the agent loads the LAZY to resolve an ambiguity (20% of cases). It is this discrimination that saves tokens.

== The End-of-Session Procedure: The Golden Rule

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

folder ".agents/" as ROOT {
  file "INDEX.adoc\n(EAGER -- 200 lines)" as IDX #E8F5E9
  file "AGENT_SESSION_MANAGER.adoc\n(Template session)" as ASM
  file "SESSION_CHECKLIST.adoc\n(When to change)" as CHK
  file "PROCEDURES.adoc\n(6 steps + LAZY/EAGER)" as PRO
  file "SESSIONS_HISTORY.adoc\n(All sessions)" as HIS

  folder "sessions/" as SESS {
    file "1-chore-migration.adoc" as S1
    file "109-formalization-lazy.adoc" as S109 #FFECB3
    file "133-epic11-article.adoc" as S133
    file "... +130 others" as SMORE
  }

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

IDX --> SESS : "Index"
IDX --> HIS : "Index"
IDX --> ARCH : "Reference"

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

@enduml
----

Without this procedure, the Eager/Lazy strategy is useless. It is this that turns the session's work into persistent information. It executes**at the explicit request of the user**(keywords: "end of session", "I'm leaving", etc.), and it is**mandatory**-- no exception, no omission.

The file`SESSION_CHECKLIST.adoc`defines ideal session metrics:

* Duration: 15-30 minutes
* Modified files: 1-3 maximum
* LLM exchanges: 5-10 messages
* Context tokens: < 50k

And signs that you need to change session: _The LLM repeats errors already corrected_, _More than 3 files modified in parallel_, _Conversation > 50 messages_. The golden rule:**Better to have 5 sessions of 20 minutes than one session of 2 hours with debugging chaos.**

=== The Flux of the 6 Steps (Quietly)

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

start
:L'utilisateur dit "end of session";
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'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
----

=== Results of 150+ Sessions

Here is what this procedure gives when applied systematically to my four projects:

**plantuml-plugin**(empty)

* **133 sessions**since the beginning of the project
* **240/240 tests PASS**(100% coverage) -- EPICs 1-7 completed
* **57 Cucumber BDD scenarios**validated
* Safety rule on config files born from a real error (Session 2 bakery-plugin)

**bakery-plugin**</think>

* **11 sessions**in two weeks
* Supabase → Firebase migration completed (9 tests fixed)
* EPIC 6 (publishProfile) functional in production
* Rule 0 created:`publishToMavenLocal`mandatory after each modification

**magic-stick**:

* **23 sessions**to build a live Xubuntu system with A/B partition
* First ISO generated at session 10
* Formalized QEMU + VNC boot tests (LAZY documentation of 144 lines)
* Functional CI/CD on SourceForge

**cheroliv.com**:

* **9 formal sessions**+ reconstitution of 7 pre-system sessions
* Article 0101 (OpenCode PATH) published
* Article 0108 (this one) rewritten after analysis of its shortcomings
* Complete governance migrated from Markdown to AsciiDoc

=== The Final Checklist

After silent execution of the 6 steps, the agent must display a confirmation checklist:

✅ Procédure de fin de session exécutée 📋 Checklist :

**Absolute rule**: no step can be marked`[✅]`if the file has not actually been modified and verified

== Bootstrap Guide: Day 1, Session 0

You're convinced by the method. You want to apply it to a new project. Where to start?

I experienced this moment on April 28, 2026. I open Opencode on`jhipster-gradle-plugins`, my monorepo of two JHipster Gradle plugins. It's a project that already exists — the code is there, the Gradle tasks work. But the governance agent? Zero. Blank page. As`plantuml-plugin`at its session 1, months ago.

Here is the exact procedure I followed, and that I will follow for any new project. Note well the order — it is important.

[plantuml, format=svg, id=diag-bootstrap, alt="Flux de bootstrap en 6 étapes pour initialiser la gouvernance agent sur un nouveau projet"]
----
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam wrapWidth 250
skinparam activityBackgroundColor #E8F5E9

title Bootstrap Governance — Day 1, Session 0
start
:Étape 0\nCréer **opencode.json**\n(6 lignes, instructions: AGENT.adoc);
note right: Le pont qui charge\nAGENT.adoc automatiquement

:Étape 1\nCréer les dossiers\n**mkdir -p .agents/sessions/ .agents/archives/**;
note right: Les conteneurs vides\navant que l'agent écrive dedans

:Étape 2\nCréer **AGENT.adoc**\n(200 lignes, règles absolues);
note right: Le fichier maître\nStructure minimale v1

:Étape 3\nCréer **PROMPT_REPRISE.adoc**\nMission session 1 (max 70 lignes);
note right: Ce que l'agent doit\nfaire à la prochaine session

:Étape 4\nCréer **.agents/INDEX.adoc**\nRègles exécutives + roadmap;
note right: Point d'entrée EAGER\ndans le dossier LAZY

:Étape 5\nCréer les fichiers LAZY structurants\n6 fichiers : SESSIONS_HISTORY, CHECKLIST, etc.;
note right
  • SESSIONS_HISTORY.adoc
  • SESSION_CHECKLIST.adoc
  • PROCEDURES.adoc
  • AGENT_SESSION_MANAGER.adoc
  • TEST_COVERAGE_ANALYSIS.adoc
  • Agents spécialisés (si besoin)
end note

:Étape 6\nAjouter le projet au Portefeuille\nMettre à jour TOUS les INDEX.adoc existants;
note right: Maintenance transverse\nObligatoire mais fastidieuse

:✅ Bootstrap terminé\nSession 1 prête;
note right: 20 minutes investies\nDes centaines économisées

stop
@enduml
----

=== Step 0: Create `opencode.json

This is the first file. Not`AGENT.adoc`, not`INDEX.adoc`.`opencode.json`First, for a simple reason: if you create`AGENT.adoc`first, you will forget to create the bridge that loads it automatically. I did it on`bakery-plugin`, I know what I'm talking about.

=== Step 1: Create the Folders

[source,bash]
----
mkdir -p .agents/sessions .agents/archives
----

Two empty folders.`sessions/`will receive the archives of each session`archives/`will receive the monthly COMPLETED_TASKS_ARCHIVE. These folders must exist *before* the agent needs to write in them. An agent that must create the folder AND the file at the same time is an agent that can fail silently.

=== Step 2: Create `AGENT.adoc` — The Master File

Minimal structure for the first version (it will grow):

[source]
----
= {NOM_PROJET} — Directives Agent

[CAUTION]
----

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

title Session Naming Convention
start

:Une session se termine;
note right: Trigger "end of session"

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 > 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'honnêteté\nplutôt que le vide
endif

stop
@enduml
----

1. Read the entire file
2. VERIFY git ls-files
3. REQUEST confirmation
4. WAIT "yes

== Project

**Name**: ... **Stack**: ... **Documentation**: AsciiDoc

== Absolute Rules

=== 0. DEVELOPMENT ENVIRONMENT

Essential commands...

=== 1. COMMITS/GIT

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

start

:Début session;
note right: L'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
----

=== 1b. CONFIGURATION FILES — ABSOLUTE SAFETY RULE

Never crush...

=== 2. End-of-Session Tests

Formal prohibition...

=== 3. END OF SESSION PROCEDURE

The 6 mandatory steps...

== Context Management — LAZY/EAGER

Files EAGER / Files LAZY...

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

start
:L'utilisateur dit "end of session";
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'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
----

=== Step 3: Create `PROMPT_REPRISE.adoc` — The Mission Session 1

A file that explicitly says: "This is session 1, mission to define." Maximum 70 lines, with a Session 0 section (bootstrap summary) and a Session 1 section (priorities to define with the user).

=== Step 4 : Create `.agents/INDEX.adoc` — The Entry Point

The file that will contain the absolute rules (executive version) and the session table. For the bootstrap, it lists rules 0 to 3 in their concise format, the project portfolio (including the new project with a 🆕 emoji), and the empty roadmap ready to be filled.

=== Step 5: Create the Structuring LAZY Files

In order:

1. `.agents/SESSIONS_HISTORY.adoc`— a table with only session 0
2. `.agents/SESSION_CHECKLIST.adoc`— the template « When to change session
3. `.agents/PROCEDURES.adoc`— the complete procedure of the 6 steps + EAGER/LAZY
4. `.agents/AGENT_SESSION_MANAGER.adoc`— the archive template
5. `.agents/TEST_COVERAGE_ANALYSIS.adoc`— the test tracking table, empty at first

If your project has a complex business domain (like`jhipster-gradle-plugins`with its mono-repo persistence/assistant), create the specialized agents now:

1. `.agents/PLUGIN_DEVELOPER.adoc`— code conventions and the dependency boundary (if plugin)
2. `.agents/BACKLOG_MANAGER.adoc`— the planning structure and the identified risks

Do not create agents that you will not use. An agent without concrete conventions to encode is a dead file that pollutes.`.agents/`.

=== Step 6: Add the Project to the Portfolio of ALL Projects

It's the step we systematically forget. Each`INDEX.adoc`Each project contains a "Project Portfolio" table that lists all projects using the same methodology. When you create a new project, you must:

1. Add a line to the new project's portfolio (logic)
2. Add a line in the portfolio of ALL existing projects — yes, all

On my four (now five) projects, this means opening the`INDEX.adoc` de `magic-stick`, `bakery-gradle`, `cheroliv.com`, `plantuml-gradle`and add the line there`jhipster-gradle-plugins | Session 1 | ... | 2026-04-28 🆕`.

It's tedious. It's manual. It's also the only way to guarantee that, no matter what project you're working on, the agent knows what other projects exist and their status. At session 012 of`magic-stick`, the agent detected two inconsistencies in the portfolio —`bakery-gradle`had its COMPLETED_TASKS_ARCHIVE overdue, and`plantuml-gradle`He had a mismatch between his procedure documentation (5 steps) and his INDEX (6 steps). Without this cross‑table, these inconsistencies would have remained invisible.

[plantuml, format=svg, id=diag-portfolio-graph, alt="Graphe du portefeuille de projets — références croisées entre INDEX.adoc"]
----
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam nodeBackgroundColor #E3F2FD

title Project Portfolio — Cross References INDEX.adoc
node "**magic-stick**
Session 037
SCRIPT_VERIFICATION" as MS #E1BEE7
node "**bakery-gradle**\nSession 11\nTEST_COVERAGE" as BG #FFE0B2
node "**cheroliv.com**
Session 10
TEST_COVERAGE" as CH #C8E6C9
node "**plantuml-gradle**
Session 133
TEST_COVERAGE" as PG #BBDEFB
node "**jhipster-gradle**\nSession 1 🆕\nTEST_COVERAGE" as JG #FFCDD2

MS --> BG : INDEX.adoc référence
MS --> CH : INDEX.adoc référence
MS --> PG : INDEX.adoc référence
MS --> JG : INDEX.adoc référence 🆕

BG --> MS : INDEX.adoc référence
BG --> CH : INDEX.adoc référence
BG --> PG : INDEX.adoc référence
BG --> JG : INDEX.adoc référence 🆕

CH --> MS : INDEX.adoc référence
CH --> BG : INDEX.adoc référence
CH --> PG : INDEX.adoc référence
CH --> JG : INDEX.adoc référence 🆕

PG --> MS : INDEX.adoc référence
PG --> BG : INDEX.adoc référence
PG --> CH : INDEX.adoc référence
PG --> JG : INDEX.adoc référence 🆕

JG --> MS : INDEX.adoc référence
JG --> BG : INDEX.adoc référence
JG --> CH : INDEX.adoc référence
JG --> PG : INDEX.adoc référence

note bottom of JG
  Quand on ajoute un projet :
  • 4 INDEX.adoc à mettre à jour
  • 1 ligne par portefeuille
  • Coût : 5 minutes
end note

legend bottom
  |= Couleur |= Projet |
  | <#E1BEE7> | magic-stick — ISO Linux live |
  | <#FFE0B2> | bakery-gradle — Plugin JBake |
  | <#C8E6C9> | cheroliv.com — Site personnel |
  | <#BBDEFB> | plantuml-gradle — Plugin IA |
  | <#FFCDD2> | jhipster-gradle — Mono-repo JHipster |
endlegend

@enduml
----

I can hear you from here: "But that's duplication!" Yes. It's intentional duplication. Each`INDEX.adoc`is autonomous. If you open a session on`magic-stick`, the agent must know that`plantuml-gradle`It is at session 133 without having to open a file in another directory. That's the price of project independence — and it is 5 lines per portfolio.

=== What Bootstrap Costs

[plantuml, format=svg, id=diag-bootstrap, alt="Flux de bootstrap en 6 étapes pour initialiser la gouvernance agent sur un nouveau projet"]
----
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam wrapWidth 250
skinparam activityBackgroundColor #E8F5E9

title Bootstrap Governance — Day 1, Session 0
start
:Étape 0\nCréer **opencode.json**\n(6 lignes, instructions: AGENT.adoc);
note right: Le pont qui charge\nAGENT.adoc automatiquement

:Étape 1\nCréer les dossiers\n**mkdir -p .agents/sessions/ .agents/archives/**;
note right: Les conteneurs vides\navant que l'agent écrive dedans

:Étape 2\nCréer **AGENT.adoc**\n(200 lignes, règles absolues);
note right: Le fichier maître\nStructure minimale v1

:Étape 3\nCréer **PROMPT_REPRISE.adoc**\nMission session 1 (max 70 lignes);
note right: Ce que l'agent doit\nfaire à la prochaine session

:Étape 4\nCréer **.agents/INDEX.adoc**\nRègles exécutives + roadmap;
note right: Point d'entrée EAGER\ndans le dossier LAZY

:Étape 5\nCréer les fichiers LAZY structurants\n6 fichiers : SESSIONS_HISTORY, CHECKLIST, etc.;
note right
  • SESSIONS_HISTORY.adoc
  • SESSION_CHECKLIST.adoc
  • PROCEDURES.adoc
  • AGENT_SESSION_MANAGER.adoc
  • TEST_COVERAGE_ANALYSIS.adoc
  • Agents spécialisés (si besoin)
end note

:Étape 6\nAjouter le projet au Portefeuille\nMettre à jour TOUS les INDEX.adoc existants;
note right: Maintenance transverse\nObligatoire mais fastidieuse

:✅ Bootstrap terminé\nSession 1 prête;
note right: 20 minutes investies\nDes centaines économisées

stop
@enduml
----

on`jhipster-gradle-plugins`, this bootstrap took me exactly 18 minutes — of`mkdir .agents/`at the last`INDEX.adoc`updated in the portfolio of`magic-stick`. Session 1, which will follow, will start with an agent who already knows the structure of the mono-repo, the Gradle commands, and the critical boundary between`persistence/`(lightweight) and`assistant/`(heavy). Twenty minutes well spent.

== The 4 (now 5) Projects, 5 Governances, 1 Method

The Eager/Lazy system is not a copy‑paste boilerplate. Each project has adapted the method to its specificities.

=== cheroliv.com : The Personal Site

**Specificity**: editorial content, WCAG 2.1 AA accessibility, static JBake **Adaptation**: Six prioritized epics (P0-P4), specialized agents (CODER, SCRUM_MASTER, PLANTUML_DESIGNER), cross-cutting acceptance criteria on accessibility. **Iconic rule** : `./gradlew serve`mandatory, formal prohibition of the script`jbake.sh`external.

=== bakery-gradle : The Multi-Purpose Plugin

**Specificity**: Plugin Gradle with publishing tasks, Firebase code generation, YAML parsing. **Adaptation**: Rule 0 (publishToMavenLocal), safety rule on config files strengthened by the incident of`site.yml`, EPIC 9 and 10 on the multi-file configuration. **Emblematic rule**:`publishToMavenLocal`after each modification of the plugin's source code.

=== plantuml-gradle : the AI plugin

**Specificité**: LangChain4j integration, generation of PlantUML diagrams via LLM, tests with cloud API keys. **Adaptation**: Dense LAZY documentation (ARCHITECTURE, API_KEY_POOL_REFERENCE, DATASET_FINETUNING), numbered EPICs (1-11 completed, 107+ in progress), optimized EAGER/LAZY separation (60% token gain). **Emblematic rule**: Files`*_ESSENTIALS.adoc`(50 lines) vs`*_REFERENCE.adoc`(unlimited) for the API key pool.

=== magic-stick: The Live System

**Specificity**: Build of Linux live ISO (Xubuntu), GPT A/B partitioning, CI/CD with SourceForge. **Adaptation**: Complex technical LAZY references (AB_PARTITION, BOOT_TEST), SCRIPT_VERIFICATION.adoc as specific step 5 (no traditional tests, but verification of bash scripts). **Emblematic rule**:`isoTestAB`skipped in CI (non privileged runners), tests reserved for local environments with Docker`--privileged`.

== Absolute Cross Rules

Some critical rules that appear in the file`AGENT.adoc`Eager and apply to all sessions on all projects:

**Development environment**

* �✅ Use the project-specific command`./gradlew serve`, `./gradlew functionalTest`, etc.)
* �❌ Forbidden to use unversioned external scripts

**Git**

* �✅ Read-only allowed (`git status`, `git diff`, `git log`)
* �❌`git add`, `git commit`, `git push`forbidden without explicit permission
* ❌`git commit --amend`forbidden except meticulously respected conditions

**Configuration Files**

* �❌ Never overwrite a config file with a`Write`complete when a`Edit`partial is enough
* ❌ Never replace sensitive values with dummy values
* Check`git check-ignore` et `git ls-files`before any modification

**Tests**

* �❌ Never run tests in end-of-session procedure without explicit permission

**Forbidden Tools**

* ❌`TodoWrite` et `Task`-- governance is done via the AsciiDoc files, not via external tools

== Anti-Patterns: What 150+ Sessions Taught Me

In hindsight, some mistakes have become such predictable patterns that I can list them as anti‑patterns — traps into which any new project will likely fall. Here they are, ordered by frequency.

[plantuml, format=svg, id=diag-antipatterns, alt="Les 7 anti-patterns de la gouvernance agent — arbre des pièges à éviter"]
----
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam wrapWidth 180

title The 7 Anti-Patterns — What 150+ Sessions Taught Me
left to right direction

rectangle "⚠️ ANTI-PATTERNS" as ROOT #FFCDD2 {

  together {
    card "**1. Agent without**\n**opencode.json**" as AP1 #FFEBEE {
      (AGENT.adoc jamais chargé)
      (→ 20 min perdues/session)
    }

    card "**2. Too Many Agents**\n**Too Early**" as AP2 #FFEBEE {
      (5 agents stubs vides)
      (→ L'agent hésite)
      (→ Seuil : 100 lignes\nou 5 règles concrètes)
    }

    card "**3. PROMPT_REPRISE**
**Ghost**" as AP3 #FFEBEE {
      (Mission a dérivé)
      (→ PROMPT_REPRISE\nne reflète pas la réalité)
    }
  }

  together {
    card "**4. Archive**\n**Empty**" as AP4 #FFEBEE {
      (Template rempli de\nplaceholders "TODO")
      (→ « à compléter plus tard »\nn'arrive jamais)
    }

    card "**5. Portfolio**\n**Ghost**" as AP5 #FFEBEE {
      (Nouveau projet créé)
      (→ Pas ajouté aux\n4 autres INDEX.adoc)
      (→ Agent croit avoir\n4 projets, en fait 5)
    }

    card "**6. Redundancy**\n**Hidden**" as AP6 #FFEBEE {
      (Même backlog copié-collé)
      (→ AGENT.adoc et INDEX.adoc\ndivergent)
      (→ Règle : INDEX.adoc\n= source de vérité)
    }
  }

  card "7. Too Long Session" as AP7 #FFEBEE {
    (2h, 85 messages, 12 fichiers)
    (→ LLM répète erreurs corrigées)
    (→ Aurait dû splitter il y a 45 min)
  }
}

note right of AP7
  **Règle d'Or**
  5 × 20 min
  >
  1 × 2 heures

  Respecter SESSION_CHECKLIST
end note

@enduml
----

=== Anti-Pattern 1 : The Agent without `opencode.json

It's the number one mistake. You wrote a magnificent`AGENT.adoc`of 200 lines, but it is never automatically loaded. The agent starts bare. You spend 20 minutes re‑contextualizing it — exactly what the method is supposed to avoid.

*Symptom* : The agent asks basic questions about the project structure while everything is in`AGENT.adoc`. *Correction* : Create`opencode.json`with the block`instructions: ["AGENT.adoc"]`. Check that the file exists in Opencode's working directory.

=== Anti-Pattern 2 : Too Many Agents Too Soon

In session 2 of your project, you create 5 specialized agents. None have real content, they are all stubs. Result:`.agents/`is cluttered with empty files, and the agent hesitates on which to load.

*Symptom*: Agent files containing only "To be defined" or an empty structure of 10 lines. *Correction*: A specialized agent is justified when its business domain exceeds 100 lines or it encodes at least 5 concrete rules. Below, the content fits in`AGENT.adoc`.

=== Anti-Pattern 3: The Ghost PROMPT_REPRISE

`PROMPT_REPRISE.adoc`is being updated... but only at the end of the session, when the agent runs the procedure. In the meantime, the session's actual mission has drifted — we fixed an unexpected bug instead of implementing the planned feature. the`PROMPT_REPRISE.adoc`end-of-session does not reflect what *really* happened.

*Symptom* : The "Priorities" section of`PROMPT_REPRISE.adoc`mentions a feature that hasn't been touched, while you spent the session on a critical bug. *Correction*: Update`PROMPT_REPRISE.adoc`in real time when the session deviates from its initial mission. Do not wait for the end-of-session procedure to document the change of direction. 30 seconds of editing during the session are worth more than a`PROMPT_REPRISE`lying.

=== Anti-Pattern 4 : The Empty Archive

The end-of-session procedure creates the archive... but the agent, eager to display their checklist, fills the template with placeholders.`{detail}`becomes « Detail to be completed later ». This « later » never arrives.

*Symptom*: Session archives containing the words "TODO", "to complete", or empty sections. *Correction*: The absolute rule says that no step can be marked [✅] if the file has not actually been modified. Apply it to yourself: reread the archive before displaying the checklist. If a section is empty, fill it in now.

=== Anti-Pattern 5 : The Ghost Portfolio

You are creating a new project with perfect governance. But you forget to add it to the portfolio of other projects. Three weeks later, you open a session on`magic-stick`and the agent tells you that you have 4 projects. You have 5. The agent doesn't know that.

*Symptom* : The counting of projects in portfolios does not match reality. *Correction* : Script the wallet update, or at minimum maintain a post-bootstrap checklist that includes 'Update the wallet for all existing projects'. This is the most tedious step of the method, and therefore the most often omitted.

[plantuml, format=svg, id=diag-portfolio-graph, alt="Graphe du portefeuille de projets — références croisées entre INDEX.adoc"]
----
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam nodeBackgroundColor #E3F2FD

title Project Portfolio — Cross-References INDEX.adoc
node "**magic-stick**\nSession 037\nSCRIPT_VERIFICATION" as MS #E1BEE7
node "**bakery-gradle**\nSession 11\nTEST_COVERAGE" as BG #FFE0B2
node "**cheroliv.com**\nSession 10\nTEST_COVERAGE" as CH #C8E6C9
node "**plantuml-gradle**\nSession 133\nTEST_COVERAGE" as PG #BBDEFB
node "**jhipster-gradle**\nSession 1 🆕\nTEST_COVERAGE" as JG #FFCDD2

MS --> BG : INDEX.adoc référence
MS --> CH : INDEX.adoc référence
MS --> PG : INDEX.adoc référence
MS --> JG : INDEX.adoc référence 🆕

BG --> MS : INDEX.adoc référence
BG --> CH : INDEX.adoc référence
BG --> PG : INDEX.adoc référence
BG --> JG : INDEX.adoc référence 🆕

CH --> MS : INDEX.adoc référence
CH --> BG : INDEX.adoc référence
CH --> PG : INDEX.adoc référence
CH --> JG : INDEX.adoc référence 🆕

PG --> MS : INDEX.adoc référence
PG --> BG : INDEX.adoc référence
PG --> CH : INDEX.adoc référence
PG --> JG : INDEX.adoc référence 🆕

JG --> MS : INDEX.adoc référence
JG --> BG : INDEX.adoc référence
JG --> CH : INDEX.adoc référence
JG --> PG : INDEX.adoc référence

note bottom of JG
  Quand on ajoute un projet :
  • 4 INDEX.adoc à mettre à jour
  • 1 ligne par portefeuille
  • Coût : 5 minutes
end note

legend bottom
  |= Couleur |= Projet |
  | <#E1BEE7> | magic-stick — ISO Linux live |
  | <#FFE0B2> | bakery-gradle — Plugin JBake |
  | <#C8E6C9> | cheroliv.com — Site personnel |
  | <#BBDEFB> | plantuml-gradle — Plugin IA |
  | <#FFCDD2> | jhipster-gradle — Mono-repo JHipster |
endlegend

@enduml
----

You copy-paste the same backlog of 50 lines in`AGENT.adoc` et `INDEX.adoc`. At the next session, you update one but not the other. Your two EAGER files conflict.

*Symptom*: differences between the EPICs listed in`AGENT.adoc`and those in`INDEX.adoc`. *Correction* : Redundancy must be *assumed and bounded*.`AGENT.adoc`contains the detailed backlog with user stories`INDEX.adoc`contains ONLY the summary table of EPICs (name, progress, priority). If the two diverge, it's`INDEX.adoc`which is considered authoritative — because it is the one that is updated at the end of each session. Document this rule in your`AGENT.adoc`In case of divergence between `AGENT.adoc` and `INDEX.adoc`, `INDEX.adoc` is the source of truth.

=== Anti-Pattern 7: The Overly Long Session

You ignore the signals of`SESSION_CHECKLIST.adoc`. 2 hours, 85 messages, 12 files modified. The agent is looping, as are you. You should have switched session 45 minutes ago.

*Symptom*: The LLM repeats errors already corrected, the context tokens exceed 80k, you have modified both`persistence/` et `assistant/`in the same session. *Correction* : the`SESSION_CHECKLIST.adoc`exists for a reason. Respect it. The golden rule is not a suggestion. 5 sessions of 20 minutes > 1 session of 2 hours.

== Why AsciiDoc ?

I chose AsciiDoc for several pragmatic reasons that have a direct impact on governance efficiency:

1. **Rich semantic structure**: sections, tables, admonitions, document attributes. An agent reads a structured document better than a block of text.
2. **Document attributes** (`:jbake-type:`, `:jbake-status:`) that allow defining machine- and human-readable metadata.
3. **Compatibility with JBake**: my static site is generated by JBake, which natively processes AsciiDoc. Governance files and blog posts share the same format. My blog post *on* governance is written in the same format as governance itself.
4. **Longevity**: AsciiDoc is a proven technical documentation format, with a stable specification.

== Result: A seamless continuity

Since I set up this system, switching from one Opencode session to another has become seamless. The agent picks up exactly where I left it, without me having to recontextualize anything.

The decisions made in session 3 are accessible in session 133. The backlog remains consistent across five simultaneous projects. Security rules (especially regarding git and configuration files) are respected because they are ubiquitous in the Eager file.

The numbers speak:

* **150+ archived sessions**in total
* **60% of EAGER tokens saved**after optimization (Session 109)
* **No recall needed**on the business context of the API key pool
* **100% of tests PASS**on plantuml-plugin (240/240)
* **A single catastrophe**(Session 2 bakery-plugin) which gave rise to the absolute safety rule

It's a**artisanal system**, built with the tools of the trade (AsciiDoc, git, Gradle), without dependence on a proprietary platform. It reflects my fundamental conviction:**A credible developer builds and uses his own tools**.

== Links

* My site : [cheroliv.com](https://cheroliv.com)
* The project`bakery-gradle`: [github.com/cheroliv/bakery-gradle-plugin](https://github.com/cheroliv/bakery-gradle-plugin)
* The project`plantuml-gradle`: [github.com/cheroliv/plantuml-gradle-plugin](https://github.com/cheroliv/plantuml-gradle-plugin)
* The project`magic-stick`: [github.com/cheroliv/magic-stick](https://github.com/cheroliv/magic-stick)
* The project`cheroliv.com`: [github.com/cheroliv/cheroliv.github.io](https://github.com/cheroliv/cheroliv.github.io)

---

*The code we write for ourselves is the laboratory of the code we teach to others.*

**Git**

* ✅ Read-only access permitted`git status`, `git diff`, `git log`)
* ❌`git add`, `git commit`, `git push`prohibited without explicit permission
* ❌`git commit --amend`prohibited unless conditions are meticulously respected

**Configuration Files**

* ❌ Never overwrite a config file with a`Write`complete when a`Edit`partial is enough
* ❌ Never replace sensitive values with dummy values
* ❌ Verify`git check-ignore` et `git ls-files`before any modification

**Tests**

* ❌ Never run tests in end-of-session procedure without explicit permission

**Forbidden Tools**

* ❌`TodoWrite` et `Task`-- governance is done via the AsciiDoc files, not via external tools

== Anti-Patterns: What 150+ Sessions Taught Me

In hindsight, some mistakes have become so predictable patterns that I can list them as anti-patterns — pitfalls into which any new project is likely to fall. Here they are, listed in order of frequency.

[plantuml, format=svg, id=diag-antipatterns, alt="Les 7 anti-patterns de la gouvernance agent — arbre des pièges à éviter"]
----
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam wrapWidth 180

title The 7 Anti-Patterns — What 150+ Sessions Taught Me
left to right direction

rectangle "⚠️ ANTI-PATTERNS" as ROOT #FFCDD2 {

  together {
    card "**1. Agent without**\n**opencode.json**" as AP1 #FFEBEE {
      (AGENT.adoc jamais chargé)
      (→ 20 min perdues/session)
    }

    card "**2. Too Many Agents**\n**Too Soon**" as AP2 #FFEBEE {
      (5 agents stubs vides)
      (→ L'agent hésite)
      (→ Seuil : 100 lignes\nou 5 règles concrètes)
    }

    card "**3. RESUME_PROMPT**\n**Ghost**" as AP3 #FFEBEE {
      (Mission a dérivé)
      (→ PROMPT_REPRISE\nne reflète pas la réalité)
    }
  }

  together {
    card "**4. Archive**\n**Empty**" as AP4 #FFEBEE {
      (Template rempli de\nplaceholders "TODO")
      (→ « à compléter plus tard »\nn'arrive jamais)
    }

    card "**5. Portfolio**\n**Ghost**" as AP5 #FFEBEE {
      (Nouveau projet créé)
      (→ Pas ajouté aux\n4 autres INDEX.adoc)
      (→ Agent croit avoir\n4 projets, en fait 5)
    }

    card "**6. Hidden Redundancy**" as AP6 #FFEBEE {
      (Même backlog copié-collé)
      (→ AGENT.adoc et INDEX.adoc\ndivergent)
      (→ Règle : INDEX.adoc\n= source de vérité)
    }
  }

  card "**7. Session Too**\n**Long**" as AP7 #FFEBEE {
    (2h, 85 messages, 12 fichiers)
    (→ LLM répète erreurs corrigées)
    (→ Aurait dû splitter il y a 45 min)
  }
}

note right of AP7
  **Règle d'Or**
  5 × 20 min
  >
  1 × 2 heures

  Respecter SESSION_CHECKLIST
end note

@enduml
----

=== Anti-Pattern 1: The Agent without `opencode.json

It's the number one error. You wrote a magnificent`AGENT.adoc`of 200 lines, but it is never loaded automatically. The agent starts naked. You spend 20 minutes recontextualizing it — exactly what the method is supposed to avoid.

*Symptom* : The agent asks basic questions about the project structure while everything is in`AGENT.adoc`. *Correction*: Create`opencode.json`with the block`instructions: ["AGENT.adoc"]`. Verify that the file exists in Opencode's working directory.

=== Anti-Pattern 2: Too Many Agents Too Early

During session 2 of your project, you create 5 specialized agents. None have any real content, they are all stubs. Result:`.agents/`is polluted with empty files, and the agent hesitates on which to load.

*Symptom* : Agent files containing only "To be defined" or an empty structure of 10 lines. *Correction* : A specialized agent is justified when its business domain exceeds 100 lines or when it encodes at least 5 concrete rules. Below, the content fits in`AGENT.adoc`.

=== Anti-Pattern 3: The Ghost PROMPT_REPRISE

`PROMPT_REPRISE.adoc`is updated... but only at the end of the session, when the agent executes the procedure. Meanwhile, the actual mission of the session has drifted — we fixed an unexpected bug instead of implementing the planned feature. The`PROMPT_REPRISE.adoc`end of session does not reflect what *really* happened.

*Symptom*: The "Priorities" section of`PROMPT_REPRISE.adoc`mentions a feature that hasn't been touched, while you spent the session on a critical bug. *Correction* : Update`PROMPT_REPRISE.adoc`in real time when the session deviates from its initial mission. Do not wait for the end-of-session procedure to document the change of direction. 30 seconds of editing during the session is better than a`PROMPT_REPRISE`lying.

=== Anti-Pattern 4 : The Empty Archive

The end-of-session procedure creates the archive... but the agent, eager to display his checklist, fills the template with placeholders.`{detail}`becomes "Detail to be completed later". This "later" never arrives.

*Symptom* : Session archives containing the words « TODO », « to complete », or empty sections. *Correction* : The absolute rule says that no step can be marked [✅] if the file has not actually been changed. Apply it to yourself: reread the archive before displaying the checklist. If a section is empty, fill it in now.

=== Anti-Pattern 5: The Ghost Portfolio

You create a new project with perfect governance. But you forget to add it to the portfolio of the other projects. Three weeks later, you open a session on`magic-stick`and the agent tells you that you have 4 projects. You have 5. The agent does not know it.

*Symptom* : The counting of projects in the portfolios does not match reality. *Correction* : Script the wallet update, or at least maintain a post-bootstrap checklist that includes 'Update the wallet of all existing projects'. This is the most tedious step of the method, and thus the most often omitted.

=== Anti-Pattern 6: Hidden Redundancy

You copy-paste the same 50-line backlog into`AGENT.adoc` et `INDEX.adoc`. At the next session, you update one but not the other. Your two EAGER files contradict each other.

*Symptom* : Discrepancies between the EPICs listed in`AGENT.adoc`and those in`INDEX.adoc`. *Correction* : Redundancy must be *assumed and bounded*.`AGENT.adoc`contains the detailed backlog with user stories.`INDEX.adoc`contains ONLY the summary table of EPICs (name, progress, priority). If the two diverge, it's`INDEX.adoc`that is authoritative — because it is the one that is updated at the end of each session. Document this rule in your`AGENT.adoc` In case of discrepancy between AGENT.adoc and INDEX.adoc, INDEX.adoc is the source of truth.

=== Anti-Pattern 7 : The Overly Long Session

You ignore the signals of`SESSION_CHECKLIST.adoc`. 2 hours, 85 messages, 12 files modified. The agent is looping, you too. You should have changed session 45 minutes ago.

*Symptom* : The LLM repeats already corrected errors, the context tokens exceed 80k, you have modified both`persistence/` et `assistant/`in the same session. *Correction* : the`SESSION_CHECKLIST.adoc`exists for a reason. Respect it. The golden rule is not a suggestion. 5 sessions of 20 minutes > 1 session of 2 hours.

== Why AsciiDoc?

I chose AsciiDoc for several pragmatic reasons that directly impact the efficiency of governance:

1. **Rich semantic structure**: sections, tables, admonitions, document attributes. An agent reads a structured document better than plain text.
2. **Document attributes**(`:jbake-type:`, `:jbake-status:`) that allow defining machine- and human-readable metadata.
3. **Compatibility with JBake**my static site is generated by JBake, which natively processes AsciiDoc. Governance files and blog posts share the same format. My blog post *on* governance is written in the same format as governance itself.
4. **Longevity**: AsciiDoc is a proven technical documentation format, with a stable specification.

== Result: A Seamless Continuity

Since I set up this system, switching from one Opencode session to another has become fluid. The agent picks up exactly where I left off, without me having to recontextualize anything.

The decisions taken in session 3 are accessible from session 133. The backlog remains consistent across five concurrent projects. The security rules (especially regarding git and config files) are respected because they are pervasive in the Eager file.

The numbers speak:

* **150+ archived sessions**in total
* **60% of EAGER tokens saved**after optimization (Session 109)
* **No callback needed**on the business context of the API key pool
* **100% of tests PASS**on plantuml-plugin (240/240)
* **A single catastrophe**(Session 2 bakery-plugin) which gave rise to the absolute safety rule

It's a**artisanal system**, built with the tools of the trade (AsciiDoc, git, Gradle), without dependence on a proprietary platform. It reflects my fundamental conviction:**A credible developer builds and uses his own tools.**.

== Links

* My site: [cheroliv.com](https://cheroliv.com)
* The project`bakery-gradle`: [github.com/cheroliv/bakery-gradle-plugin](https://github.com/cheroliv/bakery-gradle-plugin)
* The project`plantuml-gradle`: [github.com/cheroliv/plantuml-gradle-plugin](https://github.com/cheroliv/plantuml-gradle-plugin)
* The project`magic-stick`: [github.com/cheroliv/magic-stick](https://github.com/cheroliv/magic-stick)
* The project`cheroliv.com`: [github.com/cheroliv/cheroliv.github.io](https://github.com/cheroliv/cheroliv.github.io)

---

*The code we write for ourselves is the laboratory of the code we teach to others.*

Related articles