Summary

When working with an AI agent like Opencode on complex projects across multiple sessions, one faces a fundamental problem:context leak. The agent does not remember the previous session. Everything we explained — the architecture, the conventions, the backlog state — is lost. Rebuilding this context every session is costly, slow, and a source of error.

This article presents the handcrafted strategy I built to solve this problem: a persistent governance system based on AsciiDoc files, with aEager/Lazydichotomy to optimize context token consumption, and anessential end-of-session procedureto ensure continuity.

The Scene: Monday, April 21, 9:00 AM

I reopen Opencode to resume my Gradle plugin`plantuml-plugin`. Last night, I spent three hours discussing the API key pool architecture with the 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 — Oh right, the API key pool, we were at the YAML structure. No — Careful,PlantumlManager`is a Kotlin singleton object, not a class. No — No, we decided yesterday that`SyntaxValidationResult`remained a sealed class nested in`PlantumlService.

Everything has to be redone. Or rather: everything has to be re-explained. I’m going to spend the first twenty minutes of my session reconstructing a context that the agent already had in its hands yesterday. Twenty minutes of burned tokens. Twenty minutes where I could be coding, but instead, I’m doing mandatory pedagogy.

This isn’t an Opencode bug. It is the very nature of conversational LLMs: between two sessions, the working memory iscompletely erased. The agent doesn’t remember the previous mission, the decisions made, the traps identified, or the code we wrote together.

I’ve experienced this dozens of times. Across four simultaneous projects. With sessions stretching over weeks. I calculated: on average,30 to 40% of session timewas spent re-contextualizing the agent. By session 87 of project`plantuml-plugin`, I snapped. 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 First Sessions: The Dark Ages

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 scratch. It was session 1, then 2, then 3…​ until 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 passing, 42 functional tests validated, the plugin works. But the cognitive cost is unbearable. Every new session begins with a twenty-minute monologue on the project structure.

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

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

No backup. No`git restore`possible. I’m stuck. I have to manually rebuild the configuration file, find the tokens in my password managers, and piece everything back together.

From this frustration was bornAbsolute Rule 1b:

_ NEVER overwritea config file with a`Write`complete overwrite when a`Edit`partial one suffices.NEVER replacesensitive values with fake values.Verify git check-ignore and git ls-filesbefore any modification. _

This rule, now etched in stone in all my`AGENT.adoc` et `INDEX.adoc`files across 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 make a radical decision: convert the entire governance from Markdown to AsciiDoc. It’s not about aesthetics. It’s functional. AsciiDoc offers a semantic structure that LLMs read better: hierarchical sections, typed tables, admonitions (NOTE, WARNING, CAUTION), and machine-readable document attributes.

Session 1 of`cheroliv.com`formalizes the structure:

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

  • Creation of 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

A single commit:`90975e9 refactor: migrate agent governance from Markdown to AsciiDoc`. And the site continues to function.

Timeline de croissance des sessions sur les 4 projets

The timeline above illustrates the actual progression. The tipping point is session 87: that’s when the frustration of repeated re-contextualization exceeds the tolerance threshold, and the Eager/Lazy method stops being 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 accessible (Eager). Everything that iscontextual or voluminousmust be loaded on demand (Lazy).

Eager (Dashboard)

Lazy (Owner’s Manual)

Size

< 100 lines, < 10k tokens

Unlimited, detailed

Loading

Auto, at session start

On agent request

Content

Absolute rules, current mission, critical state

Session archives, full history, detailed procedures, technical references

Role

Immediately orient the agent

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.

Architecture Eager/Lazy des fichiers de gouvernance

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

  • The project’s absolute rules (no commits without permission, no`rm`without confirmation)

  • Project structure and code conventions

  • Essential commands (./gradlew serve, ./gradlew test)

  • Epics and product backlog (prioritized user stories)

  • Cross-cutting quality criteria (accessibility, responsive, compatibility)

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

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

  • The session number and priority mission

  • Summary of the previous session (what was done, what remains)

  • Acceptance criteria for the current session

  • Specific technical reminders

.agents/INDEX.adoc-- The entry point. It summarizes absolute rules, recent sessions, and above all, theproject portfoliomanaged with the same methodology. To date, five projects are listed:

----
| 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 Eager context. Instead of loading 200 lines of business context on the API key pool, I load 50 lines of essentials, and the other 150 lines remain LAZY in`*_REFERENCE.adoc`.

Measured result: move from**~25k EAGER tokens 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 long. 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 it, the agent is a blank page, exactly as I described at the beginning of the article. With it, the agent already has the absolute rules, the project architecture, and the essential commands in hand — before I even say hello.

I discovered the importance of this file by chance. On`bakery-plugin`, it didn't exist. I wondered why the agent was consistently more "lost" on this project than on others. The absolute rules were indeed in`AGENT.adoc`— but`AGENT.adoc`was never loaded. The agent only read what I told it to read, manually, every session. It was session 11 of`bakery-plugin`when I realized the`opencode.json`was missing. I created it — and session 12 started like the others.

This file is so obvious to me now that I didn't even think of it. A classic developer's error of knowing the tool too well. Today, I systematically create it *before*`AGENT.adoc`. It is the first stone.

==== The Duality of `INDEX.adoc`

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

Field reality:`.agents/INDEX.adoc`files are indeed loaded automatically at the start of the session, just like`AGENT.adoc` et `PROMPT_REPRISE.adoc`. They are in`.agents/`for organizational reasons — not to clutter the root — but their behavior is EAGER.

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

The intentional redundancy between`AGENT.adoc` et `INDEX.adoc`might be surprising. 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 bare rule, without justification, for quick consultation). The agent reads`AGENT.adoc`once to *understand*; it re-reads`INDEX.adoc`every 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 Dualité AGENT.adoc ←→ INDEX.adoc

left to right direction

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

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

AGENT --> INDEX : "Agent lit AGENT.adoc\n1 fois pour **comprendre**"
INDEX --> AGENT : "Agent relit INDEX.adoc\nchaque session pour **appliquer**"

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 ~50 additional lines of EAGER tokens — but it guarantees the agent always has the rules before its eyes, including in the concise format that facilitates immediate obedience.

=== LAZY Files: The Owner's Manual

These files live in`.agents/`and are only read when the agent needs them. They constitute the true wealth of the method, as they accumulate project 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\n(EAGER -- 200 lignes)" as IDX #E8F5E9
  file "AGENT_SESSION_MANAGER.adoc\n(Template session)" as ASM
  file "SESSION_CHECKLIST.adoc\n(Quand changer)" as CHK
  file "PROCEDURES.adoc\n(6 étapes + LAZY/EAGER)" as PRO
  file "SESSIONS_HISTORY.adoc\n(Toutes sessions)" as HIS

  folder "sessions/" as SESS {
    file "1-chore-migration.adoc" as S1
    file "109-formalisation-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 : "Indexe"
IDX --> HIS : "Indexe"
IDX --> ARCH : "Référence"

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

@enduml
----

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

**`.agents/sessions/{N}-{title}.adoc`**-- 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 retroactively reconstructed

Each archive contains the full context of the session, decisions made, problems encountered and their resolution, commands executed 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_{month}.adoc-- Completed tasks archived by month, so as not to overload the active backlog. When a user story is finished, it migrates 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 it learns the method. Afterwards, the procedure becomes mechanical.

.agents/AGENT_MODUS_OPERANDI.adoc-- Complete strategic documentation. On`plantuml-plugin`, this file is900+ linesand is actually named`AGENT_METHODOLOGIES.adoc`— I changed the name between writing this article and the effective implementation. This kind of naming divergence is inevitable in a handcrafted system that evolves. 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, patterns to follow, and anti-patterns to avoid. It is LAZY because an agent doesn’t need to re-read the whole strategy every session, only when there is ambiguity.

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

  • AB_PARTITION_REFERENCE.adoc(147 lines) — GPT A/B partition architecture,`update-system.sh`scripts, estimated sizes, rollback mechanism

  • BOOT_TEST_REFERENCE.adoc(144 lines) — QEMU + VNC procedure to test ISO boot without physical hardware, BIOS/UEFI checklist, CI/CD limitations

On`plantuml-plugin`:

  • ARCHITECTURE.adoc(134 lines) — Structure of the 11 data classes, points of attention (traps to avoid), optimized test commands

  • API_KEY_POOL_REFERENCE.adoc-- Complete details of the key pool (LAZY while`ESSENTIALS`is EAGER)

Specialized Agents: A Virtual Team

Governance is not limited to passive files. I’ve formalizedspecialized agent rolesin dedicated LAZY files, which define the expected workflow according to the task type.

Agent

File

Role

Project

CODER

CODER.adoc

FTL/CSS/JS implementation, semantic tags, accessibility criteria

cheroliv.com

SCRUM Master

SCRUM_MASTER.adoc

US planning, breakdown into sub-tasks, 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: Only one`<h1>`per page, Prefix paths with`${content.rootpath}`, Declare language`<html lang="${content.lang!"fr"}">`. These conventions, written once, have been automatically respected by the agent since session 1.

The file`SCRUM_MASTER.adoc`imposes a deliverable structure:Objective, Tasks(ordered with assignment),Acceptance Criteria, Risks. When I ask for an action plan, the agent produces this structure without me asking for it. Governanceprogramsthe agent.

When Specialized Agents Become Indispensable

The creation of specialized agents follows a natural curve. At the start of a project, you don’t need them —`AGENT.adoc`is largely sufficient. But when the project grows (say, beyond 20 sessions), two signals should alert you:

  1. The agent mixes conventions from two distinct domains (e.g., PlantUML syntax and CSS rules)

  2. You spend more time correcting the agent on conventions you’ve already explained 5 times

On`cheroliv.com`, it happened at session…​ 1. Yes, 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`syntax. Without separation, the CODER agent suggested diagrams to me, and vice versa. Chaos.

On`jhipster-gradle-plugins`, I created two specialized agents adapted to Gradle plugin development:`PLUGIN_DEVELOPER.adoc` et BACKLOG_MANAGER.adoc. The first encodes all Kotlin/Gradle conventions (no`!!, data classes for models,@TaskAction`for tasks). The second knows that`persistence`must be stable before`assistant`starts its development — a critical dependency in a mono-repo.

The mistake to avoid: creating too many agents too early.plantuml-plugin`waited until session 108 before formalizing a specialized agent for the API key pool. Before that, the business context fit in`AGENT.adoc. The empirical rule: a specialized agent is justified when its business domain exceeds 100 lines of documentation.

Session Naming Convention

A detail that seems futile but becomes critical when reaching 100 sessions. How to name archive files?

I learned the hard way that a convention is necessary — four projects, four different formats at the start, and I couldn’t find anything. Today, the convention I’ve stabilized 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 (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 3-digit numbers (001, 036, 133) avoid lexicographical sorting issues 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 session keywords (debug, feature, refactor, docs, chore, test). The subject in kebab-case is the most important part: it must allow finding a session without opening the file. If you wonder "which session was it where we fixed the integration test timeout?", the answer is`124-fix-timeout-integration-test.adoc`.

For reconstructed historical sessions (projects born before governance), I use negative numbers. On`cheroliv.com`, sessions -6 to 0 cover the entire pre-governance history of the project. And for "undocumented" or lost sessions, I create an entry in`SESSIONS_HISTORY.adoc`without a corresponding 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 Convention de Nommage des Sessions

start

:Une session se termine;
note right: Trigger "fin de 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 end-of-session procedure is the most mysterious. It says "Update`TEST_COVERAGE_ANALYSIS.adoc`if tests were added or modified." But what does this file look like?

On`plantuml-plugin`, it 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 value is not in the file itself — it's the obligation to *note* what changed. Without this step, after 50 sessions, you no longer know which tests cover what. Neither does the agent. The file becomes the single source of truth for the project's test coverage.

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

If your project has *no* tests — neither unit, nor functional, nor script — create the empty file anyway with a section "To do: define a test strategy." It's a bookmark that will remind your future self that this subject hasn't been addressed.

[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 complete life cycle of a session. The key point is the bifurcation after EAGER loading: either the mission is clear enough to execute directly (80% of cases), or the agent loads LAZY data to resolve an ambiguity (20% of cases). This discrimination is what saves tokens.

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

=== Why It Is Essential

Without this procedure, the Eager/Lazy strategy is useless. This is what transforms the session's work into persistent information. It is executed**upon the user's explicit request**(keywords: "end of session", "I'm leaving", etc.), and it is**mandatory**-- no exceptions, no omissions.

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

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

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

=== The 6-Step Flow (Silently)

[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 "fin de 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, applied systematically across my four projects, yielded:

**plantuml-plugin**:

* **133 sessions**since the project start
* **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**:

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

**magic-stick**:

* **23 sessions**to build a live Xubuntu system with A/B partition
* First ISO generated at session 10
* QEMU + VNC boot tests formalized (144-line LAZY documentation)
* SourceForge CI/CD functional

**cheroliv.com**:

* **9 formal sessions**+ reconstruction of 7 pre-system sessions
* Article 0101 (OpenCode PATH) published
* Article 0108 (this one) rewritten after analyzing its gaps
* 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 :
[✅] 1. Archive session N créée
[✅] 2. PROMPT_REPRISE.adoc mis à jour pour session N+1
[✅] 3. SESSIONS_HISTORY.adoc mis à jour
[✅] 4. INDEX.adoc mis à jour
[✅] 5. TEST_COVERAGE_ANALYSIS.adoc mis à jour (si applicable)
[✅] 6. COMPLETED_TASKS_ARCHIVE.adoc mis à jour

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

The Bootstrap Guide: Day 1, Session 0

You are 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 mono-repo of two JHipster Gradle plugins. It’s a project that already exists — the code is there, the Gradle tasks work. But agent governance? Zero. Blank page. Like`plantuml-plugin`at its session 1, months ago.

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

Flux de bootstrap en 6 étapes pour initialiser la gouvernance agent sur un nouveau projet

Step 0: Create opencode.json

This is the first file. Not`AGENT.adoc`, not`INDEX.adoc`.opencode.json`first, for one 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 Folders

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 to them. An agent that has to create the folder AND the file at the same time is an agent that might fail silently.

Step 2: Create AGENT.adoc — The Master File

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

= {NOM_PROJET} — Directives Agent

[CAUTION]

MANDATORY STOPbefore rm, Write, deletion:

  1. READ the file in full

  2. VERIFY git ls-files

  3. ASK for confirmation

  4. WAIT for "yes"

Project

Name: …​ Stack: …​ Documentation: AsciiDoc

Absolute Rules

0. DEV ENVIRONMENT

Essential commands…​

1. COMMITS/GIT

Formal prohibition…​

1b. CONFIGURATION FILES — ABSOLUTE SAFETY RULE

Never overwrite…​

2. END-OF-SESSION TESTS

Formal prohibition…​

3. END-OF-SESSION PROCEDURE

The 6 mandatory steps…​

Context Management — LAZY/EAGER

EAGER files / LAZY files…​

This minimal template allows the agent to start. The rich version — with project structure, key components, EPICs, backlog — will come at session 1, when the agent already has the basic rules in hand and can help you enrich the document.

Step 3: Create PROMPT_REPRISE.adoc — Session 1 Mission

A file that explicitly says: "This is session 1, mission to be defined." Maximum 70 lines, with a Session 0 section (bootstrap summary) and a Session 1 section (priorities to be defined 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 Structuring LAZY Files

In order:

  1. .agents/SESSIONS_HISTORY.adoc— a table with only session 0

  2. .agents/SESSION_CHECKLIST.adoc— the "When to change session" template

  3. .agents/PROCEDURES.adoc— the complete 6-step procedure + EAGER/LAZY

  4. .agents/AGENT_SESSION_MANAGER.adoc— the archive template

  5. .agents/TEST_COVERAGE_ANALYSIS.adoc— the test tracking table, empty at the start

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

  1. .agents/PLUGIN_DEVELOPER.adoc— code conventions and dependency boundary (if plugin)

  2. .agents/BACKLOG_MANAGER.adoc— planning structure and identified risks

Do not create agents 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

This is the step that is systematically forgotten. Every`INDEX.adoc`of every 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 (logical)

  2. Add a line to the portfolio of ALL existing projects — yes, all of them

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

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

Graphe du portefeuille de projets — références croisées entre INDEX.adoc

I can hear you now: "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`is at session 133 without having to open a file in another directory. That is the price of independence between projects — and it is 5 lines per portfolio.

What the Bootstrap Costs

All this takes 20 minutes. Twenty minutes once, so as to never lose twenty again at the start of every session. The ROI is immediate: from session 2 on, the agent picks up exactly where you left session 1.

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

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

The Eager/Lazy system is not a copy-paste boilerplate. Each project 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. Emblematic Rule:`./gradlew serve`mandatory, formal prohibition of external`jbake.sh`scripts.

bakery-gradle: The Multi-Purpose Plugin

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

plantuml-gradle: The AI Plugin

Specificity: LangChain4j integration, PlantUML diagram generation 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:`*_ESSENTIALS.adoc`files (50 lines) vs`*_REFERENCE.adoc`(unlimited) for the API key pool.

magic-stick: The Live System

Specificity: Live Linux ISO build (Xubuntu), GPT A/B partitioning, CI/CD with SourceForge. Adaptation: Complex LAZY technical references (AB_PARTITION, BOOT_TEST), SCRIPT_VERIFICATION.adoc as a specific step 5 (no traditional tests, but bash script verification). Emblematic Ruleskipped in CI (non-privileged runners), tests reserved for local environments with Docker`isoTestAB`.`--privileged`Cross-Cutting Absolute Rules

A few critical rules that appear in the Eager

file and apply to all sessions across all projects:`AGENT.adoc`Dev Environment

✅ Use the project-specific command (

  • , etc.)./gradlew serve, ./gradlew functionalTest❌ Prohibited to use non-versioned external scripts

  • Git

✅ Read-only allowed (

  • )git status, git diff, git log

  • prohibited without explicit permission`git add`, git commit, git push

  • prohibited except under meticulously respected conditions`git commit --amend`Configuration Files

❌ Never overwrite a config file with a

  • complete overwrite when a`Write`partial one suffices`Edit`❌ Never replace sensitive values with fake values

  • ❌ Verify

  • before any modification`git check-ignore` et `git ls-files`Tests

❌ Never run tests during the end-of-session procedure without explicit permission

  • Forbidden Tools

  •  — governance is done via AsciiDoc files, not via external tools`TodoWrite` et `Task`Anti-Patterns: What 150+ Sessions Taught Me

In hindsight, certain errors have become patterns so predictable that I can list them as anti-patterns — traps that every new project will likely fall into. Here they are, ranked by frequency.

Anti-Pattern 1: The Agent without opencode.json

Les 7 anti-patterns de la gouvernance agent — arbre des pièges à éviter

This is the number one error. You’ve written a magnificent

of 200 lines, but it’s never loaded automatically. The agent starts naked. You spend 20 minutes re-contextualizing it — exactly what the method is supposed to avoid.AGENT.adocSymptom : The agent asks basic questions about the project structure even though everything is in

At session 2 of your project, you create 5 specialized agents. None have real content, they are all stubs. Result:

AGENT.adocCorrection : Create with the`opencode.json`block. Verify that the file exists in the Opencode working directory.`instructions: ["AGENT.adoc"]`Anti-Pattern 2: Too Many Agents Too Soon

is polluted with empty files, and the agent hesitates on which one to load..agents/Symptom : Agent files containing only "To be defined" or a 10-line empty structure.

Correction : A specialized agent is justified when its business domain exceeds 100 lines or it encodes at least 5 concrete rules. Below that, the content fits in .`AGENT.adoc`Anti-Pattern 3: The Ghost PROMPT_REPRISE

is updated…​ but only at the end of the session, when the agent executes the procedure. Meanwhile, the session’s actual mission has drifted — we fixed an unforeseen bug instead of implementing the planned feature. The

PROMPT_REPRISE.adoc`end-of-session summary does not reflect what really happened.`PROMPT_REPRISE.adocSymptom : The "Priorities" section of

mentions a feature that wasn’t touched, while you spent the session on a critical bug.PROMPT_REPRISE.adocCorrection : Update in real-time when the session drifts from its initial mission. Do not wait for the end-of-session procedure to document the change in direction. 30 seconds of editing during the session are better than a`PROMPT_REPRISE.adoc`lying summary.`PROMPT_REPRISE`Anti-Pattern 4: The Empty Archive

The end-of-session procedure creates the archive…​ but the agent, eager to display its checklist, fills the template with placeholders.

becomes "Details to be completed later." This "later" never comes.{detail}Symptom : Session archives containing the words "TODO", "to be completed", or empty sections.

Correction : The absolute rule says no step can be marked [✅] if the file has not been effectively modified. Apply it to yourself: re-read the archive before displaying the checklist. If a section is empty, fill it 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 other projects. Three weeks later, you open a session on

and the agent tells you that you have 4 projects. You have 5. The agent doesn’t know.magic-stickSymptom : The project count in portfolios does not match reality.

Correction : Script the portfolio update, or at minimum maintain a post-bootstrap checklist that includes "Update the portfolio of all existing projects." This is the most tedious step of the method, and therefore the most frequently omitted. Anti-Pattern 6: Hidden Redundancy

You copy-paste the same 50-line backlog into

  1. In the next session, you update one but not the other. Your two EAGER files contradict each other.AGENT.adoc et INDEX.adocSymptom : Divergences between EPICs listed in

and those in`AGENT.adoc`.INDEX.adocCorrection : Redundancy must be assumed and bounded. contains the detailed backlog with user stories.AGENT.adoc`contains ONLY the summary table of EPICs (name, progress, priority). If the two diverge,`INDEX.adoc`is the authority — because it’s the one updated every end-of-session. Document this rule in your`INDEX.adoc: "In case of divergence between AGENT.adoc and INDEX.adoc, INDEX.adoc is the source of truth."`AGENT.adoc`Anti-Pattern 7: The Session Too Long

You ignore the signals of the

  1. 2 hours, 85 messages, 12 files modified. The agent is looping, so are you. You should have changed sessions 45 minutes ago.SESSION_CHECKLIST.adocSymptom : The LLM repeats errors already corrected, context tokens exceed 80k, you modified both

in the same session.persistence/ et assistant/Correction : The exists for a reason. Respect it. The golden rule is not a suggestion. 5 sessions of 20 minutes > 1 session of 2 hours.`SESSION_CHECKLIST.adoc`Why AsciiDoc?

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

Rich semantic structure

  1. : sections, tables, admonitions, document attributes. An agent reads a structured document better than a wall of text.Document attributes

  2. () which allow defining metadata readable by both machine and human.:jbake-type:, `:jbake-status:`Compatibility with JBake

  3. : 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 the governance itself.Longevity

  4. : AsciiDoc is a proven technical documentation format with a stable specification.Result: Seamless Continuity

Since I put this system in place, moving from one Opencode session to another has become fluid. The agent picks up exactly where I left off, without me having to re-contextualize anything.

Decisions made in session 3 are accessible in session 133. The backlog remains consistent across five simultaneous projects. Security rules (especially on git and config files) are respected because they are omnipresent in the Eager file.

The numbers speak:

150+ archived sessions

  • in total60% of EAGER tokens saved

  • after optimization (Session 109)Zero reminders necessary

  • regarding the business context of the API key pool100% of tests PASS

  • on plantuml-plugin (240/240)A single catastrophe

  • (Session 2 bakery-plugin) which gave birth to the absolute safety ruleIt is a

handcrafted system, built with the tools of the trade (AsciiDoc, git, Gradle), without dependency on a proprietary platform. It reflects my fundamental conviction:a credible developer builds and uses their own tools.Links

My site: [cheroliv.com](https://cheroliv.com)


Le code qu’on écrit pour soi est le laboratoire du code qu’on enseigne aux autres.

Related articles