Ukrayna'da tarım dronları ordu envanterinde

Ukrayna’da Rusya ile süren savaşta askeri mühendisler tarafından güncellenen tarım dronları, cephe hattında mühimmat taşıma ve insani yardım ulaştırma gibi görevlerde kullanılmaya başlandı. Dronlar 3 kategoriye ayrılırken, Türk savunma sanayisi ile iş birliği vurgulandı.

Three weeks after I said CLAUDE.md writes itself, it added 4 more rules without me

A thesis, three weeks later

On April 28th, I published an article on DEV.to that made four claims about a CLAUDE.md file — the one that constrains the coding agent at each session — and ended with this sentence: “the CLAUDE.md is never finished, and that’s precisely why it works” (4 incidents, 4 rules: how my CLAUDE.md wrote itself). That was a thesis, not a metaphor. Three weeks passed. The file added four rules without me.

What I mean is that I didn’t write them on a day I sat down to write rules. I received them on the days an incident had produced them, and all I had to do was record them before they evaporated in the flow of the project. The difference, on paper, seems thin. In the practice of a solo dev piloting an agent in production, it’s doctrinal.

One clarification before the list: this article’s title almost said “five rules.” live-snapshot-cache.md was committed on April 25th, three days before the pivot article was published. It doesn’t count. I’d rather have the honest number than the comfortable rounding.

The audit, measured by git

No narrative without raw material. Here is what git log --diff-filter=A --follow on .claude/rules/ returns between April 28th 2026 (publication of the pivot article) and May 21st 2026 (today) — four new files strictly post-publication.

cache-auth-contract.md — committed May 2nd. Born from a technical debt audit, not a production crash. It’s a Friday late afternoon. Niran is settled two desks away, headphones on, a closed burger box in the corner. I’m going through docs/dette/AUDIT-2026-04-30.md section D-20 on the right screen, code on the left. Reading through getCachedFormateurs, I understand that the unstable_cache is shared across all users — session not propagable. If someone exposes this function via an API route without a guard, it’s a silent RBAC leak. I look up to talk to Niran about it. He removes his headphones, listens, says “Yeah, that bites.” He puts them back on. The rule gets written that evening.

// .claude/rules/cache-auth-contract.md — anti-pattern to prohibit

// Flaw: no guard
export async function GET() {
  const formateurs = await getCachedFormateurs()
  return Response.json(formateurs)
}

// Correct
export async function GET(req: NextRequest) {
  const supabase = await createSupabaseServer()
  const { data: { user } } = await supabase.auth.getUser()
  if (!user) return new Response('Unauthorized', { status: 401 })
  const profile = await getUserProfile(user)
  if (!canAccess(profile, 'communication')) return new Response('Forbidden', { status: 403 })
  const formateurs = await getCachedFormateurs()
  return Response.json(formateurs)
}

inscrit-nom-prenom-required.md — committed May 14th. “Hm, it’s buggy.” — Catherine, two hours earlier. “But it’s a quick fix.” The daily drift probe sonde_contacts_orphelins_inscrits surfaced an inscrit-status contact with an empty first name — a child named Loubna, imported from Airtable where the first name lived in a separate unmapped column. The grep that followed found sixteen similar cases. What would have broken regular attendance tracking (Cannot read properties of undefined) gets caught by a Postgres CHECK constraint that closes the incident class at the root.

-- .claude/rules/inscrit-nom-prenom-required.md
CHECK (
  statut <> 'inscrit'
  OR (
    nom IS NOT NULL AND nom <> ''
    AND prenom IS NOT NULL AND prenom <> ''
  )
)

Without this CHECK, the rule stays textual in CLAUDE.md and the next import brings back a seventeenth case before the next probe. With it, the INSERT fails, and the import surfaces the problem at the source.

contrat-formation.md — committed May 16th, in the wake of ADR-0068. It’s the longest rule, because the professional training contract is a Snapshot where every column carries its guarantee of immutability. motivation_code, text_version, cases_cochees, pdf_storage_path — frozen at generation, never recalculated retroactively. An evolution of the contract is never a rewrite of the Snapshot, it’s a new event with a new text_version. The rule exists because the three-year Qualiopi audit rests entirely on the immutability of the generated PDF and the associated trainee signature — a retroactive recalculation would be enough to make the file indefensible.

hybrid-snapshot-live-reset.md — committed May 19th, two days before this article. Before sending the fifty-three Phase 2 re-enrollment SMS messages, a pre-flight audit surfaced that one token out of the fifty-three was consumed — created in test mode that morning, clicked, used_at non-null. If the Phase 2 SMS went out as-is, the link /r/<short_code> would return a 410 Gone, the contact loses their conversion, the support ticket lands at end of day. The generateTokenForContact helper was resurrecting the object (frozen identity Snapshot) but forgetting to reset the Live usage marker. Fix commit 07ed02d. The rule names the pattern, sets it against R6 Live / Snapshot / Cache of the toolkit, of which it is the project-specific extension.

The rule that couldn’t have been written before

Let’s go back to the second rule, Catherine’s and Loubna’s. Sure, I could have, on March 21st 2026 the day the first CLAUDE.md was created, abstractly written “an enrolled contact must have a first and last name”. But that rule wouldn’t have held, because it would have been read, nodded at, and would never have produced a Postgres CHECK constraint. The rule that holds isn’t the moral statement, it’s the material mechanism — the audit SQL that must always return zero, the migration that closes the incident class at the root.

-- DB coherence audit — must always return 0
SELECT COUNT(*) FROM contacts
WHERE statut = 'inscrit'
  AND ((nom IS NULL OR nom = '') OR (prenom IS NULL OR prenom = ''));

To produce that SQL, you needed the incident. To write the Why paragraph of the rule (which names the sixteen patched contacts, the Airtable origin, the probe that surfaced case-zero), you had to have lived through the widening. No “I write my doctrine on day one” produces that level of specificity. The rule isn’t a drafted precept, it’s a hardened scar.

Four observations about sedimentation

Four things become visible when you line up the four rules and look at them from a distance.

First, none of the four could have been written before their incident. Not because I lacked imagination on March 21st, but because the material precision of a useful rule comes from the encounter with a concrete case. A CHECK constraint, a tunnel mapping to DREETS paper boxes, a used_at reset in the same transaction as the SELECT — details that operate, that abstraction would never have produced.

Second, all of them cite a commit, a migration, a session log, or an ADR. No floating rules. I learned this traceability in the pivot article, but I hadn’t measured it as a mechanism. Today I do: if the rule doesn’t carry its material anchor, it doesn’t do its job. The agent can read it, the human reader too, and both can trace back to the incident if needed.

Third, three out of four prohibit an anti-pattern, the fourth freezes a Snapshot. The negative rule dominates, exactly as #20 predicted. The abstract positive rule (use Server Components by default) gets read and forgotten. The anchored negative rule (a getOr* helper that returns a Snapshot without resetting Live markers silently introduces a dead link at the next reuse) gets read and remembered because it carries its consequence.

Fourth, and this is the observation that changes the status of the CLAUDE.md, I didn’t invent these rules, I received them. The distinction sounds rhetorical, it isn’t. Inventing a rule assumes you imagine it then write it. Receiving a rule assumes an incident produced it and you record it before it evaporates. In the first regime, the file is a solitary writing act that claims exhaustiveness. In the second, the file is a sedimentation device that demands maintaining a holding space — an open notebook, a regular review session, a git log grep at short intervals. The work is no longer to write, it’s to catch.

Why it works now

Whatever we think about documentation best practices, a CLAUDE.md written in one sitting at project start doesn’t hold. It ages in two weeks, it accumulates rules that nobody invokes, and the agent ends up reading it mechanically without loading it into working memory. The CLAUDE.md that holds doesn’t age — it sediments. Each incident deposits its layer, the file carries the material memory of the project rather than its imagined documentation.

Three weeks of post-#20 practice materially confirm the pivot article’s thesis. But they add a nuance that #20 hadn’t formulated: for the file to sediment, there must be something that solicits it. A daily drift probe, a monthly debt audit, a sending pre-flight that asks “are all fifty-three tokens actually active?” — these are the devices that produce the incidents that produce the rules. Without them, the file stays on its naive day-one version, and the project drifts in silence.

Coda

A CLAUDE.md that no longer writes itself is a file that no longer works — either because the project is dead, or because the devices that solicit the incident have disappeared. Three weeks after publishing the thesis, I can verify it on raw material: four rules, four incidents, four Why paragraphs that couldn’t have been written before. The file kept writing itself while I was doing something else. But I also know now what keeps it alive — and what would be enough to kill it if I stopped paying attention.

If you maintain a CLAUDE.md on a project where you’re piloting an agent in production, ask yourself the material question: what has it added without you in the last three weeks? If the answer is nothing, it’s probably not the doctrine that’s run dry. It’s the device that produces incidents that’s gone dark.

Sequel to 4 incidents, 4 rules: how my CLAUDE.md wrote itself (April 28th, 2026). Measurements at 23 days’ distance, verified on .claude/rules/ of the Rembrandt repo — 18 rule files currently active, 4 strictly post-pivot. No Counterpart Toolkit in this sequel — that topic lives in a separate series.

Why On-Device AI Is Quietly Winning Over Cloud Inference — Three Reasons You Didn’t See Coming

I noticed something odd a few months ago. Several engineers I respect — people building serious AI pipelines, not hobbyists — quietly shifted from API-based inference back toward running models locally. Not because of some principled stance. Not because they read a blog post. Because they hit real problems and local inference solved them faster than any API change could.

Nobody announced this. There was no “local AI is back” wave on Twitter. It just… happened.

That got me thinking: if experienced engineers are making this choice in silence, the reasons probably aren’t the ones being loudly debated. It’s not “privacy is important” in the abstract. It’s specific, concrete pain points that don’t make good conference talks but absolutely dictate engineering decisions.

Here are the three that actually moved the needle.

Reason 1: The Regulatory Pressure Nobody Talks About Openly

Everyone vaguely knows that GDPR exists. Fewer people have internalized what it means when your AI system processes user data through a third-party cloud endpoint.

When you send a user’s screen content, text input, or behavioral data to a cloud inference API, you’ve just created a data transfer to a third-party processor. Under GDPR Article 28, that processor needs a Data Processing Agreement. Under GDPR Chapter V, if that server is outside the EU, you need Standard Contractual Clauses or an adequacy decision. Under China’s PIPL, cross-border data transfer requires a government-filed security assessment for anything above certain thresholds.

This is not hypothetical. GDPR enforcement has been escalating steadily — the Irish DPC alone fined Meta €1.2 billion in May 2023 for EU-US data transfer violations. CCPA enforcement in California continues to expand. China’s Personal Information Protection Law (PIPL), in effect since November 2021, is tightening cross-border data transfer requirements with mandatory security assessments.

Here’s the trap developers fall into: your AI vendor’s privacy policy is not your compliance shield.

When your application sends data to an inference API and something goes wrong, regulators look at you — the data controller — not the API provider. The fact that the API provider has good security practices is relevant but not sufficient. You still need to demonstrate lawful basis, purpose limitation, data minimization, and cross-border transfer compliance for every single inference call that processes personal data.

For applications involving GUI automation, document processing, customer service interactions, or anything that touches user-generated content — that’s basically every inference call.

Running inference on-device eliminates this exposure cleanly. The data never leaves the user’s hardware. There’s no cross-border transfer. The DPA requirement with an AI vendor disappears. The compliance surface collapses dramatically.

I’ve watched legal teams add 3-6 months to product timelines trying to untangle the regulatory implications of cloud inference for EU or China deployments. On-device inference sidesteps the entire conversation. For teams that ship to regulated markets, that timeline compression is worth a lot.

[IMAGE: A diagram showing data flow comparison — cloud inference with multiple regulatory checkpoints (GDPR, CCPA, PIPL) vs. on-device inference where data stays local]

Reason 2: Latency Isn’t Just About Speed — It’s About Determinism

The average latency numbers for cloud inference look reasonable. Sub-200ms for most major providers, often well under 100ms for smaller models. When someone benchmarks cloud inference, those are the numbers they publish.

The number that actually matters for production systems is P99. Or even P99.9.

Cloud inference latency is variable in ways that are difficult to predict and nearly impossible to bound. A 50ms average can have a 2000ms P99 due to cold starts, regional capacity fluctuations, network path changes, or provider-side throttling. This isn’t a criticism of cloud providers — it’s inherent to shared infrastructure at scale.

For many applications, this variability is fine. A chatbot that occasionally takes 2 seconds instead of 0.2 seconds is annoying but functional.

For GUI automation agents, variability kills reliability.

When an agent is navigating a UI — clicking buttons, reading screen state, deciding what to do next — it’s executing a feedback loop. Each inference call determines the next action, which changes the screen state, which feeds back into the next inference call. The entire loop depends on predictable timing. If one inference step takes 20x longer than expected, the agent may be acting on stale screen state, may miss UI transitions, or may time out waiting for an action to complete.

This isn’t a latency optimization problem. It’s a determinism problem. The agent needs to be able to reason about timing as part of its control logic.

On-device inference gives you P99 you can actually plan around. On Apple Silicon with appropriate quantization, you get consistent throughput that’s bounded by local hardware — not by whatever is happening on a shared inference cluster on the other side of the planet. You can profile it, characterize it, and build your agent’s timing assumptions around real measurements.

For GUI automation specifically, the reliability improvement from this determinism is often more impactful than the raw latency numbers suggest. We’ve observed this pattern repeatedly: switching from cloud inference to on-device inference doesn’t just make an agent faster — it makes it work in scenarios where it was previously failing intermittently and unpredictably.

[IMAGE: A latency distribution graph comparing cloud inference (wide spread, long tail) vs. on-device inference (tight distribution, predictable P99)]

Reason 3: The Cost Crossover Most People Missed

This one requires some arithmetic, but it’s worth doing.

Cloud inference pricing has been dropping steadily. For context, GPT-4-class inference that cost $0.03/1K tokens in 2023 is now available at a fraction of that from multiple providers. For many use cases, cloud inference is cheap.

But “cheap per call” and “cheap at scale” are different calculations.

Three things happened in the last 18 months that changed the math for on-device inference:

First: W4A8 and W8A8 quantization techniques matured significantly. A model running W4A8 quantization on Apple Silicon achieves quality within a few percentage points of full-precision while running at dramatically higher throughput. This isn’t theoretical — it’s in production, measurable, and reproducible.

Second: Apple M4 silicon arrived with a substantially improved Neural Engine and memory bandwidth profile. A 4B quantized model on Apple Silicon now achieves throughput that would have required a much larger machine a year ago.

Third: The “zero marginal cost” nature of on-device inference becomes meaningful at enterprise scale.

Here’s the calculation people miss: for applications where inference is happening continuously — monitoring, automation agents, real-time assistance — the cost per hour of cloud inference adds up in a way that the per-call pricing obscures.

If you’re running an autonomous agent that makes 10 inference calls per minute during active use, and a user is active for 6 hours per day, that’s 3,600 inference calls per day per user. At even $0.001 per call (which is optimistic for capable models), that’s $3.60/user/day — $1,314/user/year. For a B2B product with 500 users, you’re looking at $657,000/year in pure inference costs, scaling linearly with usage.

The break-even against on-device depends on hardware costs and usage patterns, but for enterprise deployments with heavy inference usage, the crossover typically arrives in 12-18 months. After that point, every inference call is essentially free.

This doesn’t mean on-device always wins on cost — for bursty, low-volume use cases, cloud inference is clearly more economical. But for continuous-use automation and monitoring applications, the TCO calculation has quietly flipped, and many teams haven’t updated their mental model to account for it.

What This Means for Builders

None of this means cloud inference is going away. Cloud inference will remain the right choice for many workloads — burst capacity, the largest models, multi-modal tasks that require more than local hardware can provide, and anywhere the regulatory and latency considerations I’ve described don’t apply.

But the decision is no longer “cloud by default, local if you’re weird about privacy.” The calculus is more nuanced now:

  • If you process personal data from users in the EU, California, or China, you need to do the compliance math honestly before assuming cloud inference is viable.
  • If you’re building agent loops where timing matters, P99 latency from cloud inference may be silently causing reliability failures you’re attributing to other causes.
  • If you have sustained, high-volume inference at enterprise scale, you may be past the cost crossover already and not realize it.

The engineers I mentioned at the start didn’t arrive at local inference through ideology. They arrived through debugging. They found the compliance lawyers, the intermittent timeouts, the bills that didn’t look right.

That’s usually how actual engineering decisions get made.

A Project Worth Watching

One example of this shift playing out in practice: Mano-P, an open-source GUI-VLA agent from MiningLamp Technology that runs fully on-device (Apache 2.0, GitHub).

The performance numbers are interesting as a concrete data point for what on-device inference can actually deliver today: Mano-P 1.0-4B running on Apple M5 Pro (64GB, Cider SDK) achieves ~80 tokens/s decode with W8A16 quantization; enabling W8A8 activation quantization speeds up prefill by ~12.7%. The 72B evaluation configuration (not open-sourced — used for benchmarking only) reached 58.2% on the OSWorld benchmark (proprietary model category). The open-source 4B version is what developers actually deploy and run locally.

If you’re building in the GUI automation or edge agent space and want to see what current hardware can actually do, it’s worth a look:

brew tap Mininglamp-AI/tap && brew install mano-cua

[IMAGE: Screenshot of Mano-P running an on-device GUI task on a MacBook, showing the agent interface and live task execution]

The quiet shift I noticed among those engineers isn’t a trend piece. It’s just people solving real problems with the best available tools — and the best available tools for a growing set of problems now happen to run locally.

That’s worth paying attention to.

Trois semaines après avoir dit que mon CLAUDE.md s’écrivait tout seul, il a ajouté 4 règles sans moi

Une thèse, trois semaines plus tard

Le 28 avril, j’ai publié sur DEV.to un article qui affirmait quatre choses à propos d’un fichier CLAUDE.md — celui qui contraint l’agent de codage à chaque session — et qui finissait par cette phrase : « le CLAUDE.md n’est jamais fini, et c’est précisément pour ça qu’il marche » (4 incidents, 4 règles : comment mon CLAUDE.md s’est écrit tout seul). C’était une thèse, pas une métaphore. Trois semaines ont passé. Le fichier a ajouté quatre règles sans moi.

Je veux dire par là que je ne les ai pas écrites le jour où je me suis assis pour écrire des règles. Je les ai accueillies les jours où un incident les avait produites, et où je n’avais plus qu’à les noter avant qu’elles s’évaporent dans la marche du projet. La différence, sur le papier, paraît mince. Dans la pratique d’un dev solo qui pilote un agent en production, elle est doctrinale.

Une précision avant d’entrer dans la liste : le titre de cet article a failli dire « cinq règles ». live-snapshot-cache.md a été commité le 25 avril, trois jours avant la publication de l’article-pivot. Elle ne compte pas. Je préfère l’honnêteté du chiffre exact au confort de l’arrondi.

Le bilan, mesuré par git

Pas de récit possible sans la matière brute. Voici ce que git log --diff-filter=A --follow sur .claude/rules/ retourne entre le 28 avril 2026 (publication de l’article-pivot) et le 21 mai 2026 (aujourd’hui) — quatre fichiers nouveaux strictement post-publication.

cache-auth-contract.md — committé le 2 mai. Né d’un audit de dette technique, pas d’un crash en prod. C’est un vendredi en fin d’après-midi. Niran est posé à deux bureaux de là, casque sur les oreilles, une boîte de burgers fermée dans l’angle. Je parcours docs/dette/AUDIT-2026-04-30.md section D-20 sur l’écran de droite, le code sur l’écran de gauche. En relisant getCachedFormateurs, je comprends que le cache unstable_cache est mutualisé entre tous les utilisateurs — session non propagable. Si quelqu’un expose cette fonction via une route API sans guard, c’est une fuite RBAC silencieuse. Je lève la tête pour en parler à Niran. Il retire son casque, écoute, dit « Ah oui, ça mord. » Il remet le casque. La règle est rédigée ce soir-là.

// .claude/rules/cache-auth-contract.md — anti-pattern à interdire

// Faille : pas de guard
export async function GET() {
  const formateurs = await getCachedFormateurs()
  return Response.json(formateurs)
}

// Correct
export async function GET(req: NextRequest) {
  const supabase = await createSupabaseServer()
  const { data: { user } } = await supabase.auth.getUser()
  if (!user) return new Response('Unauthorized', { status: 401 })
  const profile = await getUserProfile(user)
  if (!canAccess(profile, 'communication')) return new Response('Forbidden', { status: 403 })
  const formateurs = await getCachedFormateurs()
  return Response.json(formateurs)
}

inscrit-nom-prenom-required.md — committé le 14 mai. « Hum, ça bug. » — Catherine, deux heures avant. « Mais c’est vite corrigé. » La sonde quotidienne sonde_contacts_orphelins_inscrits a remonté un contact statut='inscrit' avec le prénom vide — l’enfant Loubna, importé d’un Airtable où le prénom vivait dans une colonne séparée non mappée. Le grep qui suit relève seize cas similaires. Ce qui aurait pété l’émargement régulier (Cannot read properties of undefined) tombe dans une CHECK constraint Postgres qui ferme la classe à la racine.

-- .claude/rules/inscrit-nom-prenom-required.md
CHECK (
  statut <> 'inscrit'
  OR (
    nom IS NOT NULL AND nom <> ''
    AND prenom IS NOT NULL AND prenom <> ''
  )
)

Sans cette CHECK, la règle reste textuelle dans CLAUDE.md et l’import suivant ramènera un dix-septième cas avant la prochaine sonde. Avec, l’INSERT échoue, l’import remonte le problème à la source.

contrat-formation.md — committé le 16 mai, dans le sillage d’ADR-0068. C’est la règle la plus longue, parce que le contrat de formation professionnelle est un Snapshot dont chaque colonne porte sa garantie d’immutabilité. motivation_code, text_version, cases_cochees, pdf_storage_path — figés à la génération, jamais recalculés rétroactivement. Une évolution du contrat n’est jamais une réécriture du Snapshot, c’est un nouvel événement avec une nouvelle text_version. La règle existe parce que l’audit Qualiopi trois ans repose entièrement sur l’immutabilité du PDF généré et de la signature stagiaire associée — un recalcul rétroactif suffirait à rendre le dossier indéfendable.

hybrid-snapshot-live-reset.md — committé le 19 mai, deux jours avant cet article. Avant l’envoi des cinquante-trois SMS de Phase 2 réinscription, un audit pré-flight remonte qu’un token sur les cinquante-trois est consommé — créé en mode test le matin, cliqué, used_at non null. Si le SMS Phase 2 part tel quel, le lien /r/<short_code> renvoie un 410 Gone, le contact perd sa conversion, le ticket support tombe en fin de journée. Le helper generateTokenForContact ressuscitait l’objet (Snapshot d’identité figé) mais oubliait de reset le marker Live d’usage. Fix commit 07ed02d. La règle nomme le pattern, l’oppose à R6 Live / Snapshot / Cache du toolkit dont elle est l’extension projet-spécifique.

La règle qui n’aurait pas pu être écrite avant

Reprenons la deuxième règle, celle de Catherine et de Loubna. Certes, j’aurais pu, le 21 mars 2026 jour de création du premier CLAUDE.md, écrire abstraitement « un contact inscrit doit avoir un nom et un prénom ». Mais cette règle-là n’aurait pas tenu, parce qu’elle aurait été lue, hochée de la tête, et n’aurait jamais produit une CHECK constraint Postgres. La règle qui tient n’est pas l’énoncé moral, c’est le mécanisme matériel — le SQL d’audit qui doit toujours retourner zéro, la migration qui ferme la classe d’incident à la racine.

-- audit DB de cohérence — doit toujours retourner 0
SELECT COUNT(*) FROM contacts
WHERE statut = 'inscrit'
  AND ((nom IS NULL OR nom = '') OR (prenom IS NULL OR prenom = ''));

Pour produire ce SQL, il fallait l’incident. Pour rédiger le paragraphe Pourquoi de la règle (qui mentionne par leur nom les seize contacts patchés, l’origine Airtable, la sonde qui a remonté le cas-zéro), il fallait avoir traversé l’élargissement. Aucun « j’écris ma doctrine au jour 1 » ne produit ce niveau de spécificité. La règle n’est pas un précepte rédigé, c’est une cicatrice durcie.

Quatre constats sur la sédimentation

Quatre choses se voient quand on aligne les quatre règles et qu’on les regarde de loin.

Premièrement, aucune des quatre n’aurait pu être écrite avant son incident. Pas parce que je manquais d’imagination le 21 mars, mais parce que la précision matérielle d’une règle utile vient de la rencontre avec un cas concret. Une CHECK constraint, un mapping tunnel vers cases papier DREETS, un reset de used_at dans la même transaction que le SELECT — autant de détails opérants que l’abstraction n’aurait jamais produits.

Deuxièmement, toutes citent un commit, une migration, un session log ou un ADR. Aucune règle flottante. Cette traçabilité, je l’ai apprise dans l’article-pivot, mais je ne l’avais pas mesurée comme une mécanique. Aujourd’hui je la mesure : si la règle ne porte pas son ancrage matériel, elle ne fait pas son travail. L’agent peut la lire, le lecteur humain aussi, et l’un comme l’autre peuvent remonter à l’incident en cas de doute.

Troisièmement, trois sur quatre interdisent un anti-pattern, la quatrième fige un Snapshot. La règle négative domine, exactement comme #20 le prédisait. La règle positive abstraite (utilisez Server Components par défaut) se lit et s’oublie. La règle négative ancrée (un helper getOr* qui retourne un Snapshot sans reset des markers Live introduit silencieusement un lien dead à la prochaine réutilisation) se lit et se retient parce qu’elle porte sa conséquence.

Quatrièmement, et c’est le constat qui change le statut du CLAUDE.md, je n’ai pas inventé ces règles, je les ai accueillies. La distinction paraît rhétorique, elle ne l’est pas. Inventer une règle suppose qu’on l’imagine puis qu’on l’écrit. Accueillir une règle suppose qu’un incident l’a produite et qu’on la note avant qu’elle s’évapore. Dans le premier régime, le fichier est un acte d’écriture solitaire qui prétend à l’exhaustivité. Dans le second, le fichier est un dispositif de sédimentation qui exige de tenir un sas — un cahier ouvert, une session de bilan régulière, un grep git log à intervalle court. Le travail n’est plus d’écrire, c’est d’attraper.

Pourquoi ça marche maintenant

Quoi que nous puissions penser des bonnes pratiques de documentation, un CLAUDE.md rédigé d’un trait au démarrage d’un projet ne tient pas. Il vieillit en deux semaines, il accumule des règles que personne ne convoque, et l’agent finit par le lire mécaniquement sans en charger la mémoire opérante. Le CLAUDE.md qui tient, lui, ne vieillit pas — il sédimente. Chaque incident dépose sa couche, le fichier porte la mémoire matérielle du projet plutôt que sa documentation imaginée.

Trois semaines de pratique post-#20 confirment matériellement la thèse de l’article-pivot. Mais elles ajoutent une nuance que #20 n’avait pas formulée : pour que le fichier sédimente, encore faut-il qu’il y ait quelque chose qui le sollicite. Une sonde drift quotidienne, un audit dette mensuel, un pré-flight d’envoi qui demande « est-ce que les cinquante-trois tokens sont bien actifs ? » — ce sont ces dispositifs qui produisent les incidents qui produisent les règles. Sans eux, le fichier reste sur sa version naïve du jour 1, et le projet dérive en silence.

Coda

Un CLAUDE.md qui ne s’écrit plus est un fichier qui ne fonctionne plus — soit parce que le projet est mort, soit parce que les dispositifs qui sollicitent l’incident ont disparu. Trois semaines après avoir publié la thèse, je peux la vérifier sur la matière brute : quatre règles, quatre incidents, quatre paragraphes Pourquoi qui ne pouvaient être rédigés avant. Le fichier a continué de s’écrire pendant que je faisais autre chose. Mais je sais aussi, maintenant, ce qui le maintient vivant — et ce qui suffirait à le tuer si je le perdais de vue.

Si vous tenez un CLAUDE.md sur un projet où vous pilotez un agent en production, posez-vous la question matérielle : qu’a-t-il ajouté sans vous depuis trois semaines ? Si la réponse est rien, ce n’est probablement pas la doctrine qui s’est tarie. C’est le dispositif qui produit les incidents qui s’est éteint.

Suite de 4 incidents, 4 règles : comment mon CLAUDE.md s’est écrit tout seul (28/04/2026). Mesures à 23 jours d’écart, vérifiées sur .claude/rules/ du repo Rembrandt, 18 fichiers de règles projet actuellement, 4 strictement post-pivot. Pas de Counterpart Toolkit dans cette séquelle — ce sujet vit dans une autre série.