30f6263db5
Amorce le système `concept` dans ce dépôt et ouvre `app-contract` — la frontière entre cette bibliothèque et les applications qui la consomment. C'est un contrat **inter-dépôts** et ce dépôt en est le FOURNISSEUR : les applications vivent ailleurs et tireront `sdk-surface` d'ici. D'où le type `contract_`, ses cinq sections obligatoires, et l'inscription dans `.project/contracts.yaml` — c'est l'inscription qui publie. Trois feuilles : - **`contract_sdk-surface`** — l'engagement, écrit du point de vue de l'appelant. Ce qu'il peut tenir pour acquis : permissif en entrée et précis en sortie ; toute référence rendue est NUE, aucun appel ne rend jamais de clé ; lire est la possession, écrire est la propriété ; donner à lire est un seul acte et le destinataire n'appelle rien ; un dépôt s'adresse à une inbox, jamais à un document ; `ensureIdentity()` est toute la connexion ; et `configure` est le seul appel qu'il supprimera. Ce qu'il ne doit PAS tenir pour acquis, dit aussi crûment : aucune confidentialité, rien de « par lecteur » sur un document public, aucune révocation, aucune écriture déléguée, et les références ne voyagent que dans un déploiement. - **`rule_would-the-caller-unlearn-it`** — le test qui décide de tout : est-ce que ceci ferait apprendre à l'appelant quelque chose qu'il devra DÉSAPPRENDRE ? Avec les deux tells que la revue de ces jours-ci a rendus concrets : une exception nommée cesse d'en être une dès qu'on la publie, et un symbole gardé parce qu'il était là n'est pas une décision. - **`knowledge_what-an-app-deletes-at-migration`** — les deux destins d'un symbole publié, le cas intermédiaire d'`ensureIdentity` (substance jetée, site d'appel conservé), et le fait que la liste de suppression n'est plus portée par un chemin d'import depuis la fusion des entrées : une garantie mécanique remplacée par une garantie documentaire, dont seule la moitié est tenue par un test. Le vocabulaire du concept fixe trois termes que ce projet a déjà payé cher : `reference` (jamais « lien »), `ReadCap`, `polyfill-era`. `lint` est conformant. Reste à décider : ce dépôt n'a pas de `CLAUDE.md` racine, donc l'`AGENTS.md` généré n'est chargé nulle part.
22 lines
3.0 KiB
Markdown
22 lines
3.0 KiB
Markdown
---
|
|
type: rule
|
|
summary: Before publishing anything, ask whether a caller would have to unlearn it — that outranks cost, latency and convenience
|
|
---
|
|
|
|
# Would the caller have to UNLEARN it?
|
|
|
|
**Rule:** Before adding, keeping or changing anything on the published surface, ask: *would an application coding against this learn something it has to **unlearn** at migration?* If yes, it is a deviation — whatever it buys in cost, latency or ergonomics. Both halves are binding: the **surface** must be as close as possible to the future SDK, and the **implementation** as close as possible to what NextGraph actually plans. Where upstream's behaviour is known, it is a specification, not a reference.
|
|
|
|
"Known" is narrow: read in `nextgraph-rs`, 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.
|
|
|
|
**Why:** this library's entire value is that an application keeps its code. A layer that teaches a false model destroys exactly what it was built to produce, and it does so silently: nothing fails, the application simply learns a habit that has no successor. Two instances, both caught only by asking the question — *"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 and which would have made applications tag their deposits, for nothing.
|
|
|
|
**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 (usually the lever is *who* pays and *when*). If the cost is genuinely unsolvable, say so rather than bending the model quietly.
|
|
|
|
**How to apply:** the tell is a symbol that makes the caller handle something the target will never hand it — a key, an inbox address, a store id, its own identity. Two secondary tells, both of which have produced real holes here:
|
|
|
|
- **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; inertia has repeatedly left published what nothing calls.
|
|
|
|
Applies to the published surface first, but also to internal choices that shape it: an emulation whose relation the target cannot express will surface as a habit sooner or later. When a deviation is genuinely necessary, it must be **deliberate, documented and invisible to the caller** — what is forbidden is the silent one, adopted because it was convenient.
|