Files
ng-eventually/.project/concepts/app-contract/rule_no-divergence-from-nextgraph.md
T
Sylvain Duchesne 33b96fdc8d docs(concept): la règle interdit la divergence, elle ne la met plus en balance
La feuille testait ce que l'APPELANT apprendrait. Le propriétaire du projet a énoncé la
règle plus large : rester au plus près de NextGraph, et n'admettre aucune implémentation
qui en diverge — que l'appelant s'en aperçoive ou non.

L'ordre des deux questions est ce qui a manqué. Sur la fusion de `readUnion`, posée en
premier, « l'appelant devra-t-il désapprendre ? » ne tranchait pas : « une entité par
document » est une bonne pratique par ailleurs, alors que désapprendrait-il au juste ? Le
raisonnement a piétiné des heures là-dessus. Posée en premier, « la cible fait-elle ça ? »
a demandé un regard : le niveau 1 rend les sujets réels, et l'ORM du niveau 3 porte `@id`
ET `@graph` sur chaque objet en fabriquant le premier quand on l'omet. Divergence, fin.

« Devra-t-il désapprendre ? » reste, mais mesure la gravité d'une divergence inévitable —
jamais son autorisation. Et un tell est ajouté, celui qui a produit ce défaut : une
recommandation que le code impose au lieu de la guider, en rendant l'autre disposition
invisible.
2026-08-10 14:51:17 +02:00

3.5 KiB

type, summary
type summary
rule Never implement anything that diverges from NextGraph — ask "does the target do this?" first, and only then how badly a caller would be misled

No divergence from NextGraph

Rule: Never implement anything that diverges from NextGraph. At every choice — a published signature as much as an internal mechanism — the first question is does the target do this? Verified in nextgraph-rs, or stated by its author. If the target does it differently, we do it their way, whatever that costs. Only where the target answers nothing at all do we invent, and then deliberately, documented, and named as a bet.

"Known" is narrow: read at the source, or stated by its author. Never inferred from what an npm package happens to expose, and never inferred from an absent implementation"the engine does not do X" says nothing about whether the target will.

The second question measures gravity, not permission: would an application coding against this have to unlearn it? Use it to rank what to fix first, and to judge an unavoidable divergence. Never use it to authorise one.

Why the order matters — it is the failure this rule was rewritten for. readUnion folded every triple of a document into one bag keyed by the document, so two entities written under two subjects came back merged and one written under another subject came back relabelled, silently. Asked the second question first, the answer was ambiguous: one entity per document is good placement practice anyway, so what exactly would a caller unlearn? The reasoning stalled there for hours. Asked the first question, it took one look: level 1 returns real subjects, and level 3's ORM carries @id and @graph on every object and generates the former when omitted — several objects per graph is the designed case. Divergence, done, no debate about perception.

Earlier instances, all of the same shape: "every document has a native inbox", written from general reasoning, false, and already an implementation; and a per-document inbox pointed at its owner's inbox to absorb a measured cost, emulating a many-to-one relation the target cannot express.

The pressure to deviate never announces itself as one. It arrives as a cost, a latency, an ergonomic wrinkle — all real, all legitimate. That disguise is what makes it dangerous. When shape and cost conflict: keep the shape and attack the cost elsewhere (the lever is usually who pays and when). If the cost is genuinely unsolvable, say so rather than bending the model quietly.

How to apply. The tells, each of which has produced a real hole here:

  • A recommendation enforced by the code. Ours may guide placement; it may not make the other arrangement invisible. A read path that silently normalises what it did not expect is the signature.
  • A symbol that makes the caller handle what the target will never hand it — a document's key, an inbox address, a store id, its own identity.
  • A named exception stops being one the moment it is published. A door documented as "only this internal caller uses it" is a door any application can open; the note is not a mechanism. Move it out of the published surface instead.
  • A symbol kept because it was already there is not a decision. At every surface change, re-ask whether an application still needs each neighbouring symbol.

When a divergence is genuinely unavoidable it must be deliberate, documented and invisible to the caller. What is forbidden is the silent one, adopted because it was convenient.