Files
ng-eventually/.project/rules/nextgraph/surface-mirrors-the-sdk.md
T
Sylvain Duchesne e16fd6a707 docs: ce que le hook du SDK rend vraiment, la ou le depot disait un set nu
Six endroits affirmaient au present que `useShape` rend un `DeepSignalSet` nu.
C-est vrai de la revision citee, faux de celle contre laquelle ce paquet est
construit - et deux de ces six PORTAIENT une decision de provenance :

- `ShapeQuery kind=invention` etait justifie par "aucun type amont ne porte
  d-etat de chargement", alors que `isLoading` en porte un. Le kind tient, mais
  pour l-autre raison : ce qui n-a de contrepartie nulle part est le troisieme
  etat, la lecture ECHOUEE, parce qu-un `orm_start_graph` refuse n-est qu-un
  `console.error` et laisse une attente eternelle a tous les niveaux.
- l-annotation `announced-not-written` de `useShapeQuery` posait la meme
  premisse fausse. La direction annoncee ne bouge pas ; sa premisse si.

Ajoutee aussi l-instruction d-injection qui ne resolvait pas : l-export `.` de
`@ng-org/orm` pointe sur `core`, qui n-exporte aucun `useShape`. Il est sur
`/react` (export par defaut) ou `reactUseShape` sur `/all`.
2026-09-24 18:28:24 +02:00

7.4 KiB

name, summary, group, scope, created
name summary group scope created
surface-mirrors-the-sdk Publish the SDK's names, parameters and returns — a difference must be justified beside the code nextgraph local 2026-09-16

The published surface mirrors the SDK

Rule: What this package publishes exposes, as far as possible, functions of the same NAMES, taking the same PARAMETERS, returning the same VALUES as the target SDK. A difference is allowed — but it must be duly justified, and the best justification of all is that the difference is NextGraph's own direction, as announced by its developers. The justification lives in the symbol's provenance annotation, beside the code, never in a conversation or a prose document.

This is the surface-level sibling of no-divergence-from-nextgraph, which asks does the target do this? of the model and the semantics. That question can be answered correctly and this one still failed: a symbol may carry the target's semantics exactly and still be published under a name the target never uses, taking a parameter the target cannot express. An application does not consume semantics. It types a name, passes an argument, reads a return — those three are what it will have to unlearn.

Why. The abstract statement of this rule was available for weeks and changed nothing, so what follows is what actually happened, verified in the tree.

A name the target never uses. watchShape has zero occurrences in nextgraph-rs. Worse, it spends watch, a verb the ORM has already spent on signal observation — watch as watchDeepSignal in sdk/js/orm/src/connector/GraphOrmSubscription.ts, watchEffect in the Vue adapter. So the name is not merely absent upstream, it reads as something upstream already means. The target's stated name is useShapeQuery.

A parameter that had to be translated. Its scope is Scope = "public" | "protected" | "private" (packages/polyfill/src/model/types.ts) — three invented literals. The SDK's own Scope is { graphs?: string[] | string; subjects?: string[] } (sdk/js/orm/src/types.ts). Not equivalent, therefore not passable through: the polyfill has to translate one into the other, and that translation is what forced an entire home-grown read pipeline beneath it — scope resolution, document enumeration, a sync barrier, a batch read. A parameter that must be translated is the tell that a mechanism below it is about to become ours. The cost of a re-invented parameter is never the parameter.

A true citation attached to the wrong claim. readUnion has no counterpart upstream — it is N calls plus a batch policy — yet its head annotation reads kind=aligned level=2 ref=sdk/js/lib-wasm/src/lib.rs:sparql_query. That symbol exists and does what the annotation says it does. The citation is exact; the claim is false. A composition cannot be "aligned" on a single function. This is the tell to watch for, because it defeats the very thing annotations are for: a reader checks the citation, finds it correct, and moves on. The rest of the surface offers the honest form by contrast — useShape is annotated kind=passthrough level=3 and the cited symbol is the function it forwards to. (The annotation has since been split so that the enumeration and the failure policy are marked invention; the head claim of alignment is still there.)

The legitimate deviation, so nobody concludes every difference is a fault. watchShape returns a ShapeQuery shaped like TanStack Query's useQuery — { data, isPending, isSuccess, isError, error } — where the SDK's useShape returns a result carrying the data and a load state and no failure at all ({ data, promise, subscription, isLoading, nextPage, previousPage }; the revision cited above returned the collection on its own, and that difference is the anchor's, not this rule's). That is a real difference from what the SDK ships today, and it is justified: NextGraph's direction, as reported by its developers, is a useShapeQuery returning exactly that shape. Deviating toward the announced target is alignment, not divergence — it is the rest of the surface that will have to catch up.

The gap that same example exposed — closed by announced-not-written. A target stated by its developers but not yet written has no file:symbol to cite: useShapeQuery has zero occurrences in the tree. The taxonomy in no-divergence-from-nextgraph had no kind for it either — declared-not-wired needs a declaration, reserved-name needs a name present in the tree — so an author holding the strongest possible justification had only two bad moves left: cite an approximate symbol, which is precisely the readUnion failure, or declare invention, which understates the alignment and tells a later reader the shape is ours to change. The kind announced-not-written is the third move: in place of a symbol upstream it cites the record of the statement, and it names who made it and when.

// @provenance useShapeQuery kind=announced-not-written level=3 ref=.project/rules/nextgraph/surface-mirrors-the-sdk.md:useShapeQuery announced-by=nextgraph-developers@2026-09-16 - the SDK ships `useShape`, whose result carries data and a load state and no failure; the announced direction is a `useShapeQuery` returning a TanStack-shaped snapshot

This section is that record, and the annotation above points back at it. The statement it holds: NextGraph's direction is a useShapeQuery returning { data, isPending, isSuccess, isError, error }, reported from its developers and written down here on 2026-09-16 — the date the annotation carries, so a later reader can weigh how long the direction has been announced and still unwritten. An announcement nobody wrote down is hearsay: packages/polyfill/test/provenance.test.ts refuses an annotation of this kind whose record is missing, is a source file rather than prose, or no longer names the symbol.

How to apply.

  • Before naming a published symbol, find the target's own name and use it. If the target has not named it, check the verb is free at the target: one it already spends elsewhere is taken, and borrowing it says something false.
  • Prefer passing the target's type through to translating it. When a parameter cannot be passed through, stop and ask what will have to be built beneath it — that is the real decision, and it is being made by the parameter.
  • Return what the SDK returns, unless the difference is the target's announced direction — then say whose statement it is, in the annotation's announced-by field and against a record the reader can open. "Whose statement" is a field the test checks, not a remark.
  • "Duly justified" has a fixed cost: one annotation line, beside the code, naming what the target does, what was chosen instead, and why. The test is refutability — a reader must be able to check it by opening one file.
  • Check every citation against the CLAIM, not just against the tree. Same granularity on both sides: a function may cite a function; a composition, a pipeline or a policy cites nothing at level 2 and must say so. "The reference resolves" is not "the annotation is true".
  • Applies to what is published. An internal helper that claims to resemble the target falls under no-divergence-from-nextgraph; this rule is about the symbols an application types.

Pending, not done. Renaming watchShape to useShapeQuery and removing readUnion are decided and not yet applied. Read the two as live examples, not as history.