fix: ShapeObservable rejoint la liste de suppression et le contrat dit le trou de refetch
ShapeObservable portait l'annotation honnete kind=invention level=none ref=none mais siegeait sous l'entete SDK-SHAPED qui promet un equivalent cible pour chaque symbole. Il passe sous la barriere POLYFILL-ERA, toujours exporte (des applications l'ecrivent : examples/notebook, e2e/polyfill-entry.ts). ShapeQuery reste SDK-SHAPED, son enregistrement existe. Ce n'est pas un adaptateur de framework : il porte le filtre de capacites et la republication a l'arrivee d'une capacite, deux emulations du portefeuille partage. Il disparait donc avec lui, migration couplee et non suppression independante. Le contrat enonce aussi que refetch() n'a aucun equivalent enregistre : les cinq champs annonces ne le comptent pas. C'est un fait sur l'enregistrement, pas sur TanStack ni sur les intentions de NextGraph. PATCH, par le precedent du 2026-09-28 : aucune signature ne change. Version 1.0.0-dev.13 -> 1.0.0-dev.14, entree dans le contrat concept et dans docs/api-contract.md section 14, dans le meme commit.
This commit is contained in:
@@ -149,6 +149,10 @@ export function init(...args: any[]): any; // likewise — not the `init` p
|
|||||||
export function initNg(...args: any[]): any;
|
export function initNg(...args: any[]): any;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**`ShapeObservable` is on the deletion list, and it goes WITH the shared wallet, not before it.** It is not a framework adapter: it carries the capability filter (`getSnapshot()` returns a view filtered by the capabilities held) and the capability-arrival re-publish (a subscription that re-publishes when a capability arrives). A capability arrives mid-session only because the wallet is shared; in the target an identity holds its own wallet and its capabilities from the start, so there is nothing to filter and no arrival to re-publish on. The announced form, a hook returning `{ data, isPending, isSuccess, isError, error }`, has nowhere to hang such a subscription, because the target does not need one. The type stays exported and you may write it down; what you cannot do is plan to drop it on its own ahead of the rest of the shared-wallet code.
|
||||||
|
|
||||||
|
**`refetch()` has NO RECORDED COUNTERPART.** It is the only published way out of a read that is stuck pending. The announcement recorded in this repository lists five fields, `{ data, isPending, isSuccess, isError, error }`, and `refetch` is not among them. That is a statement about the RECORD, nothing more: TanStack Query's own `useQuery` does return a `refetch`, so a successor may well exist, but this repository holds no record of one and cannot name what an application leaning on `refetch()` would migrate onto. Treat it as an open migration point, not as a call that has a mapped replacement.
|
||||||
|
|
||||||
## Guarantees
|
## Guarantees
|
||||||
|
|
||||||
Every entry accepts `NuriLike` and validates at the door; what it returns is a precise `Nuri`. No type guard is published.
|
Every entry accepts `NuriLike` and validates at the door; what it returns is a precise `Nuri`. No type guard is published.
|
||||||
@@ -283,11 +287,13 @@ What each level means here, in this package's own terms:
|
|||||||
- **minor** — a symbol is added and nothing existing moves (`inbox.readSyncedForDocument` arrived this way).
|
- **minor** — a symbol is added and nothing existing moves (`inbox.readSyncedForDocument` arrived this way).
|
||||||
- **patch** — a fix that changes neither the published surface nor anything above under `## Guarantees`.
|
- **patch** — a fix that changes neither the published surface nor anything above under `## Guarantees`.
|
||||||
|
|
||||||
**A tag says where it comes from.** A release cut on `main` carries a **full version** (`1.0.0`), and the three rules above govern what changes between two full versions. Work still on a branch carries a **pre-release** of the version it is heading for (`1.0.0-dev.13`), which sorts *below* that version by construction - so you can pin what exists today while the tag itself tells you the surface has not been released and may still move before it is. Between two pre-releases of the same version nothing is promised: re-pull and read this leaf again. When the branch lands, the full version appears alongside; the pre-release keeps resolving, so no reference you pinned is ever withdrawn from under you.
|
**A tag says where it comes from.** A release cut on `main` carries a **full version** (`1.0.0`), and the three rules above govern what changes between two full versions. Work still on a branch carries a **pre-release** of the version it is heading for (`1.0.0-dev.14`), which sorts *below* that version by construction - so you can pin what exists today while the tag itself tells you the surface has not been released and may still move before it is. Between two pre-releases of the same version nothing is promised: re-pull and read this leaf again. When the branch lands, the full version appears alongside; the pre-release keeps resolving, so no reference you pinned is ever withdrawn from under you.
|
||||||
|
|
||||||
**Tags carry the package name**, because this repository publishes more than one engagement and their versions move independently: `polyfill/v1.0.0-dev.13` is this package, `ng-e2e-helpers/v...` is the other one. A bare `v...` tag would say nothing about which surface it froze the day the two diverge - which is the day one of them takes a major and the other does not.
|
**Tags carry the package name**, because this repository publishes more than one engagement and their versions move independently: `polyfill/v1.0.0-dev.14` is this package, `ng-e2e-helpers/v...` is the other one. A bare `v...` tag would say nothing about which surface it froze the day the two diverge - which is the day one of them takes a major and the other does not.
|
||||||
|
|
||||||
`1.0.0` is a baseline, not a claim of maturity: it is the number that makes your pin mean something. Nothing was released before it, so none of the changes named above is a bump from anything - but the next release very likely is a major. What exists today is `1.0.0-dev.13`, on a branch: pin that string exactly, and anchor your `usage_` leaf's `against:` on it - `against: @ng-eventually/polyfill@1.0.0-dev.13`, the string you pinned, never the version it is heading for.
|
`1.0.0` is a baseline, not a claim of maturity: it is the number that makes your pin mean something. Nothing was released before it, so none of the changes named above is a bump from anything - but the next release very likely is a major. What exists today is `1.0.0-dev.14`, on a branch: pin that string exactly, and anchor your `usage_` leaf's `against:` on it - `against: @ng-eventually/polyfill@1.0.0-dev.14`, the string you pinned, never the version it is heading for.
|
||||||
|
|
||||||
|
`1.0.0-dev.14` is a **patch** (2026-10-01): `ShapeObservable` moved from the entry's SDK-SHAPED section to its POLYFILL-ERA one, and `## Surface` now states that `refetch()` has no recorded counterpart. No signature changed - same name, same shape, still exported from this one entry - so nothing under `## Guarantees` moved. The type was already annotated `kind=invention level=none ref=none` (no upstream observable exists), under a heading that promises a target counterpart for every symbol it lists. It stays exported because applications genuinely write the type down. What the move records is that it is not a framework adapter: it carries the capability filter and the capability-arrival re-publish, both of which exist only because one wallet is shared, so it is deleted when the shared wallet is, as one coupled migration. `ShapeQuery` stays SDK-SHAPED: its record exists and states `{ data, isPending, isSuccess, isError, error }` field for field.
|
||||||
|
|
||||||
`1.0.0-dev.13` is a **patch**: `NgLike`, `UseShapeLike`, `OrmSubscriptionLike`, `GetObjectsLike` and `InsertObjectLike` moved from the entry's SDK-SHAPED section to its POLYFILL-ERA one, beside `EventuallyConfig`, whose fields they type. No signature changed - same five names, same five shapes, all still exported from this one entry - so nothing under `## Surface` or `## Guarantees` moved, which is the patch/major line this leaf draws itself. What changed is classification only: each was already honestly annotated `kind=invention level=none ref=none` (no target counterpart, at any level), sitting under a heading that promises one for every symbol it lists, because each exists solely to describe what `configure` receives and `configure` was already on the deletion list. An application that already understood it would stop typing these five the day it deletes its `configure()` call was not misled about behaviour; this patch only makes the surface say so, instead of implying the opposite.
|
`1.0.0-dev.13` is a **patch**: `NgLike`, `UseShapeLike`, `OrmSubscriptionLike`, `GetObjectsLike` and `InsertObjectLike` moved from the entry's SDK-SHAPED section to its POLYFILL-ERA one, beside `EventuallyConfig`, whose fields they type. No signature changed - same five names, same five shapes, all still exported from this one entry - so nothing under `## Surface` or `## Guarantees` moved, which is the patch/major line this leaf draws itself. What changed is classification only: each was already honestly annotated `kind=invention level=none ref=none` (no target counterpart, at any level), sitting under a heading that promises one for every symbol it lists, because each exists solely to describe what `configure` receives and `configure` was already on the deletion list. An application that already understood it would stop typing these five the day it deletes its `configure()` call was not misled about behaviour; this patch only makes the surface say so, instead of implying the opposite.
|
||||||
|
|
||||||
|
|||||||
@@ -794,6 +794,8 @@ Each one's warrant: `Nuri` is what every reference-returning call returns and `N
|
|||||||
|
|
||||||
**These five moved out of this list in `1.0.0-dev.13` (2026-09-28), into the entry's POLYFILL-ERA block beside `EventuallyConfig` - a PATCH, not a removal: same five names, same five shapes, still exported from this one entry.** Each was already annotated `kind=invention level=none ref=none` (honestly - none has a target counterpart at any level), which had always sat oddly under the entry's SDK-SHAPED heading ("a target counterpart for every symbol"). All five exist only to describe what `configure` receives, and `configure` / `EventuallyConfig` were already on the deletion list (§ 1: "NO COUNTERPART, by design... `configure` / `configureStoreRegistry` are deleted"). The move corrects which list tells a consumer their fate at migration; it changes nothing under `## Surface` or `## Guarantees` in the concept contract, so it is a patch by that leaf's own `## Change policy`.
|
**These five moved out of this list in `1.0.0-dev.13` (2026-09-28), into the entry's POLYFILL-ERA block beside `EventuallyConfig` - a PATCH, not a removal: same five names, same five shapes, still exported from this one entry.** Each was already annotated `kind=invention level=none ref=none` (honestly - none has a target counterpart at any level), which had always sat oddly under the entry's SDK-SHAPED heading ("a target counterpart for every symbol"). All five exist only to describe what `configure` receives, and `configure` / `EventuallyConfig` were already on the deletion list (§ 1: "NO COUNTERPART, by design... `configure` / `configureStoreRegistry` are deleted"). The move corrects which list tells a consumer their fate at migration; it changes nothing under `## Surface` or `## Guarantees` in the concept contract, so it is a patch by that leaf's own `## Change policy`.
|
||||||
|
|
||||||
|
**`ShapeObservable` moved the same way in `1.0.0-dev.14` (2026-10-01) - a PATCH again: same name, same shape, still exported.** It is annotated `kind=invention level=none ref=none` (no upstream observable exists; the record behind `ShapeQuery` describes a snapshot shape, not an observable), so it sat wrongly under the SDK-SHAPED heading. `ShapeQuery` stays there: its record exists and states `{ data, isPending, isSuccess, isError, error }` field for field. The type stays exported because applications write it down (`examples/notebook/app.ts`, `e2e/polyfill-entry.ts`). It is not a framework adapter: it carries the capability filter (`getSnapshot()` returns a filtered view) and the capability-arrival re-publish (a `getCaps().onChange` subscription owned by the observable's own lifecycle). A capability arrives mid-session only because the wallet is shared; in the target an identity holds its own wallet and capabilities from the start, so there is nothing to filter and no arrival to re-publish on. It therefore dies exactly when the shared wallet dies - a COUPLED migration, not an independent symbol removal - and a TanStack-shaped hook returning a snapshot has nowhere to hang such a subscription, because the target does not need one. `refetch()` lives on it and is the only published way out of a read stuck pending; the recorded announcement lists five fields and `refetch` is not among them, so it goes with NO RECORDED COUNTERPART. That is a statement about the record, not about TanStack Query (whose `useQuery` does return a `refetch`) nor about NextGraph's intentions.
|
||||||
|
|
||||||
Two types the blanket export published are now internal, each because **nothing published names it**:
|
Two types the blanket export published are now internal, each because **nothing published names it**:
|
||||||
|
|
||||||
- **`ReadCap`** — no published signature takes or returns one. Its users are two private helpers of `surface/inbox.ts` (`capsSeenIn`, `capOfPayload`) and the emulated registers. Publishing it advertised a value a consumer has no published call to obtain, and deliberately so: `linkTo` was removed precisely for handing one out (§ 0 of `readcap-and-nuri-model.md`), and `mintCap` is unreachable from outside (§ 11). The only use a consumer could make of it is a cast — which is what the surface's permissive-in / precise-out design exists to make unnecessary.
|
- **`ReadCap`** — no published signature takes or returns one. Its users are two private helpers of `surface/inbox.ts` (`capsSeenIn`, `capOfPayload`) and the emulated registers. Publishing it advertised a value a consumer has no published call to obtain, and deliberately so: `linkTo` was removed precisely for handing one out (§ 0 of `readcap-and-nuri-model.md`), and `mintCap` is unreachable from outside (§ 11). The only use a consumer could make of it is a cast — which is what the surface's permissive-in / precise-out design exists to make unnecessary.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ng-eventually/polyfill",
|
"name": "@ng-eventually/polyfill",
|
||||||
"version": "1.0.0-dev.13",
|
"version": "1.0.0-dev.14",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Polyfill of the NextGraph JS SDK over @ng-org/web + @ng-org/orm, with emulated capabilities and inbox. Drop-in; remove at migration.",
|
"description": "Polyfill of the NextGraph JS SDK over @ng-org/web + @ng-org/orm, with emulated capabilities and inbox. Drop-in; remove at migration.",
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
|
|||||||
@@ -118,7 +118,9 @@
|
|||||||
export type { Nuri, NuriLike, PrincipalId } from "./model/types";
|
export type { Nuri, NuriLike, PrincipalId } from "./model/types";
|
||||||
export { useShape } from "./surface/use-shape";
|
export { useShape } from "./surface/use-shape";
|
||||||
export { useShapeQuery } from "./surface/use-shape-query";
|
export { useShapeQuery } from "./surface/use-shape-query";
|
||||||
export type { ShapeQuery, ShapeObservable } from "./surface/use-shape-query";
|
export type { ShapeQuery } from "./surface/use-shape-query";
|
||||||
|
// `ShapeObservable` is exported from the POLYFILL-ERA block below, beside `configure`:
|
||||||
|
// it is `kind=invention level=none ref=none` and carries shared-wallet emulation.
|
||||||
// The ORM's one-shot read and its subscription-free write - WRAPPED, at upstream's own
|
// The ORM's one-shot read and its subscription-free write - WRAPPED, at upstream's own
|
||||||
// names and signatures, never re-exported. `surface/orm.ts` says what each wrapper adds,
|
// names and signatures, never re-exported. `surface/orm.ts` says what each wrapper adds,
|
||||||
// and which neighbours of theirs in `@ng-org/orm`'s entry are deliberately not here
|
// and which neighbours of theirs in `@ng-org/orm`'s entry are deliberately not here
|
||||||
@@ -195,6 +197,32 @@ export type {
|
|||||||
GetObjectsLike,
|
GetObjectsLike,
|
||||||
InsertObjectLike,
|
InsertObjectLike,
|
||||||
} from "./model/types";
|
} from "./model/types";
|
||||||
|
// `ShapeObservable` - what `useShapeQuery` returns - moved down here on 2026-10-01. It is
|
||||||
|
// `kind=invention level=none ref=none` (no upstream observable exists; the record behind
|
||||||
|
// `ShapeQuery` describes a SNAPSHOT shape, not an observable), so it never belonged under
|
||||||
|
// the SDK-SHAPED heading. It stays EXPORTED: applications genuinely write the type down
|
||||||
|
// (`examples/notebook/app.ts` holds one in a variable, returns it and takes it as a
|
||||||
|
// parameter; `e2e/polyfill-entry.ts` annotates it). Only the documenting section changes.
|
||||||
|
//
|
||||||
|
// It is NOT a framework adapter. It carries two pieces of shared-wallet emulation:
|
||||||
|
// - the CAPABILITY FILTER - `getSnapshot()` returns a view filtered by the capabilities
|
||||||
|
// held (`use-shape-query.ts`, `filterReadable` under `caps.isEnforcing()`);
|
||||||
|
// - the CAPABILITY-ARRIVAL RE-PUBLISH - a `getCaps().onChange(...)` subscription owned
|
||||||
|
// by the observable's own lifecycle and released with it.
|
||||||
|
// A capability arrives MID-SESSION only because the wallet is shared. In the target an
|
||||||
|
// identity holds its own wallet and its capabilities from the start: nothing to filter,
|
||||||
|
// no arrival to re-publish on. So `ShapeObservable` dies exactly WHEN THE SHARED WALLET
|
||||||
|
// DIES - a COUPLED migration with the shared wallet, not an independent symbol removal.
|
||||||
|
// Deleting the type and "using the hook" is not a step that stands alone.
|
||||||
|
//
|
||||||
|
// The announced form cannot carry what ours carries: a TanStack-shaped hook returning a
|
||||||
|
// snapshot has nowhere to hang a capability-arrival subscription, because the target
|
||||||
|
// does not need one.
|
||||||
|
//
|
||||||
|
// `refetch()` lives on it, and is the ONLY published way out of a read stuck pending.
|
||||||
|
// The recorded announcement lists five fields, `{ data, isPending, isSuccess, isError,
|
||||||
|
// error }`, and `refetch` is not among them: it goes with NO RECORDED COUNTERPART.
|
||||||
|
export type { ShapeObservable } from "./surface/use-shape-query";
|
||||||
// `RegistrySession` went with `getSession` (2026-08-12): it was published for exactly one
|
// `RegistrySession` went with `getSession` (2026-08-12): it was published for exactly one
|
||||||
// reason — an application typed the session thunk it injected with it — and a published
|
// reason — an application typed the session thunk it injected with it — and a published
|
||||||
// type whose signature is gone is a promise about the target that nothing keeps. Upstream a
|
// type whose signature is gone is a promise about the target that nothing keeps. Upstream a
|
||||||
|
|||||||
Reference in New Issue
Block a user