feat!: useShapeQuery lit par la requete de forme du SDK

This commit is contained in:
Sylvain Duchesne
2026-09-21 11:41:31 +02:00
parent a5e553e65b
commit 77e78ec81d
29 changed files with 1190 additions and 971 deletions
@@ -33,4 +33,22 @@ So this change takes the one reactive read that works and puts it on the path th
## Progress
- Blocker confirmed LIFTED before writing anything: the deleted bug leaf's premise was the pinned packages, and `RdfOrmSubscription.getOrCreate` is reachable at `@ng-org/orm@0.1.2-alpha.21`.
- Read the doctrine first (`surface-mirrors-the-sdk`, `no-divergence-from-nextgraph`, `knowledge_what-a-read-scope-is-upstream`), then the SDK's installed typings to establish what the shape query offers: `readyPromise` (pending vs ready-and-empty), `signalObject`, `addChangeListener`, `close`.
- Established, by reading `dist/connector/RdfOrmSubscription.js`, that `orm_start_graph` failing is caught and only `console.error`'d and that `readyPromise` is built with `resolve` alone. So the ONLY real error channel on this path is the query refusing to open; `isError` is wired to that and the rest is recorded rather than invented (no timeout was added).
- Chose injection over a runtime import: the package never hard-imports the SDK, and `useShape` is React's hook, unusable from an observable. `configure({ ormSubscription })` mirrors the `ng` / `useShape` fields beside it, and `RdfOrmSubscription.getOrCreate` is assignable to it with no wrapper (probed with `tsc` before committing to the type).
- Rewrote both suites against a new `test/orm-fake.ts` - a small engine honouring the two scope axes the way `schema_shape_to_sparql` does, so the scope tests still prove something. Nothing deleted: 7 -> 11 and 12 -> 15 tests.
- The e2e harness now injects the REAL ORM, so the two `useShapeQuery` journeys measure the deployed broker. First run died in the broker login (a transient before any assertion); the second passed 42/42.
## Result
**Done.** `useShapeQuery` reads through the SDK's shape query (`RdfOrmSubscription.getOrCreate`, injected as `configure({ ormSubscription })`; absent, the read publishes `isError` naming it). Scope resolution, the `ensureReposOpen` barrier, `readUnion` and the `@type` filter are gone; `graphs`/`subjects`/`did:ng:i` reach the engine verbatim. The observable, snapshot, state tracking and capability filter stay ours. `data` items are the shape's own objects and `shapeType` is `ShapeType<T>`. **`isError` stays**, wired to the one real failure - the query refusing to open. A start the ENGINE refuses is swallowed upstream, so it reads `isPending` for ever: recorded in code and contract, no timeout invented. `userStoreDoc` deleted; `liveStartWithConfig` retired. `1.0.0-dev.6`, major.
**Files.** `packages/polyfill/` src (7), test (4, incl. new `orm-fake.ts`), e2e (4), `package.json`, `README.md`; `docs/{api-contract,internal-contract}.md`; the contract leaf. Out of boundary, deliberately: `examples/notebook/` + `bun.lock` - the change silently broke the reference consumer.
**Gate.** `bun test` 408 pass / 0 fail; both `tsc` exit 0; lint 0 ERROR; `42 passed, 0 failed, 42 total - batch 3.3 min`.
**Surprises.** VERIFIED: `listMyEntityDocs` is NOT dead - its own suite and an e2e journey call it. VERIFIED: `bun.lock` was stale before this; `bun install` synced it.
**Follow-ups.** `readUnion` keeps two `index-deposit.ts` callers (T01.f). `knowledge_what-the-orm-writes-and-deletes-upstream.md` links the deleted bug leaf. `watchShape` survives as a stale name in ~10 src comments.
@@ -47,4 +47,5 @@ The polyfill's published surface has drifted from the SDK's: invented names, inv
- T01.b — deletion is answered at level 3 and fully wired: `DeepSignalSet.delete` -> a remove patch -> `graph_orm_update` -> `SparqlBuilder::remove_object`, which removes the SHAPE's predicates, not the subject; no document deletion exists at any level. `getObjects` returns a DETACHED clone; `insertObject` throws without `@graph`. Proposals: publish `OrmSubscription` as-is (the read filter applies to `signalObject`), publish NEITHER `DiscreteOrmSubscription` (JSON-CRDT, no `@graph`, nothing for a per-document filter to read) NOR `ngSession` (hands out the SDK handle and the session). MEASURED: `useShape` is still broken live, and the bug leaf's mechanism was FALSE - the deployment is AHEAD of our pinned `@ng-org/*`, its `orm_start_graph` takes `config` BEFORE the callback, so the five-argument client lands its callback in the wrong slot. T01.d's blocker STANDS. Also VERIFIED: ORM writes bypass `sparql_update` entirely, so the emulated write guard never sees an ORM add or delete.
- T01.c - `useShapeQuery` takes the SDK's `Scope`, re-exported as a passthrough. Our three literals became `StoreType`, internal only: VERIFIED they are upstream's own `store_type`, so only the NAME was invented. A store is now named by its REFERENCE (`privateStore()` / `protectedStore()` / `publicStore()`), and `createEntityDoc(store?)` takes one, private when omitted, as `doc_create` does. `listMyEntityDocs`, `resolveScopeGraph` and `resolveWriteGraph` unpublished, still internal - T01.d removes the read path's last caller. VERIFIED: public and protected share one store id here, so the reference must be the index document. `1.0.0-dev.5`.
- Package refresh (2026-09-21) - `@ng-org/*` moved to web alpha.14 / orm alpha.21 / shex-orm alpha.9 / alien-deepsignals alpha.13. The live ORM read now STARTS against the deployed broker: `6 passed, 0 failed, 6 declared`, ready in 16ms, delete reached the document. `bug_useshape-live-read-needs-a-newer-broker` DELETED - the deployment was never behind, our packages were. T01.d's blocker LIFTS. Also surfaced: `OrmSubscription` is now `RdfOrmSubscription` (T01.e's proposal names the old one); `Scope.graphs` is REQUIRED and its `[]` means the EMPTY set while `subjects: []` means NO filtering - the two axes read `[]` in opposite directions, which T01.d must not get wrong; six e2e files imported `ng-e2e-helpers` without the polyfill declaring it, fixed as `workspace:*`.
- T01.d - `useShapeQuery` reads through `RdfOrmSubscription.getOrCreate`, injected as `configure({ ormSubscription })`; absent, the read publishes `isError` naming it. Scope resolution, the `ensureReposOpen` barrier, `readUnion` and the `@type` filter are gone from that path; `graphs`/`subjects`/`did:ng:i` reach the engine verbatim. The observable, snapshot, state and capability filter stay ours. `isError` KEPT, wired to the one real failure (the query refusing to open). A start the ENGINE refuses is swallowed upstream, so it reads `isPending` for ever - recorded in code and contract, no timeout invented. `userStoreDoc` and `liveStartWithConfig` deleted. VERIFIED: `listMyEntityDocs` is NOT dead, its own suite and an e2e journey call it. The change silently broke `examples/notebook/`, repaired out of boundary and deliberately. `1.0.0-dev.6`, major, 42/42 e2e.