diff --git a/.project/concepts/app-contract/knowledge_what-a-read-scope-is-upstream.md b/.project/concepts/app-contract/knowledge_what-a-read-scope-is-upstream.md index 22330cb..057a80e 100644 --- a/.project/concepts/app-contract/knowledge_what-a-read-scope-is-upstream.md +++ b/.project/concepts/app-contract/knowledge_what-a-read-scope-is-upstream.md @@ -1,12 +1,12 @@ --- type: knowledge summary: What the target offers for reading many objects — a graph is one document, a store's graph holds only its containment triples, and scoping a read by store is not expressible at all -last_checked: 2026-09-21 +last_checked: 2026-09-24 --- # What a read scope is upstream -Read at the source in `nextgraph-rs` (`213338f6`). Every claim points at a symbol or a module rather than a line, so `git grep` settles any doubt after the code moves. The question answered here is the one a caller actually asks: **how do I ask for many objects at once, and what can the request say?** +Read at the source in `nextgraph-rs` (`213338f6`), which declares OLDER releases than this repo installs - the `ANCHOR` in `packages/polyfill/test/provenance.test.ts` holds the gap and checks both its ends. Every claim points at a symbol or a module rather than a line, so `git grep` settles any doubt after the code moves. The question answered here is the one a caller actually asks: **how do I ask for many objects at once, and what can the request say?** ## The type, and the two axes it filters on @@ -51,9 +51,15 @@ That is `declared-not-wired` in the taxonomy of [[no-divergence-from-nextgraph]] `query_quads_for_shape` seeds the caller's subject list as the pending set of the **root** shape; every nested shape gets its subjects from what the root query discovered, not from the caller. The emitted filter is `FILTER(?s IN (…))` over root-subject IRIs. -## The engine takes more than the surface hands it +## How far `where`, `orderBy` and `pageSize` are known to travel -`OrmConfig` (`engine/net/src/orm.rs`) carries `where_`, `order_by`, `select`, `page_size` and `max_active_pages`, and `schema_shape_to_sparql` accepts a where config, an order-by config and a `(limit, offset)` pair — it emits `ORDER BY`, `LIMIT` and `OFFSET` from them. But `Verifier::start_orm` (`engine/verifier/src/orm/graph/initialize.rs`) builds its config from `json!({})` behind a `// TODO`, so the config every query reads is always empty: **no caller can reach any of it**. The richness is real and unreachable. +`OrmConfig` (`engine/net/src/orm.rs`) carries `where_`, `order_by`, `select`, `page_size` and `max_active_pages`; `OrmConfig::from_json` parses all five and refuses a `pageSize` greater than zero without an `orderBy`; and every one of them is consumed downstream - `schema_shape_to_sparql` takes the where config, the order-by config and a `(limit, offset)` pair and emits `FILTER`, `ORDER BY`, `LIMIT` and `OFFSET` from them, while `initialize.rs` drives its paging window and its page eviction from `page_size` and `max_active_pages`. The config machinery is implemented, not stubbed. + +One hop is missing, at the ENTRY: `Verifier::start_orm` takes no config argument at all - `request_processor.rs` calls it with three - so it builds one from `json!({})` behind a `// TODO`. `OrmConfig::from_json` names the missing hop in its own TODO, *"Use json in libwasm context"*, and that is exactly what is absent there: `orm_start_graph` (`sdk/js/lib-wasm/src/lib.rs`) declares FIVE parameters at this commit, with no slot for a config. + +**That absence describes `213338f6` and nothing later, and the installed releases are past it.** `@ng-org/web@0.1.2-alpha.14` ships `orm_start_graph` with SIX parameters, `config` at index 4, and `@ng-org/orm@0.1.2-alpha.21` calls it with six, passing its whole options object into that slot - both read in the shipped artifacts, not inferred. So at the releases this repo installs the config LEAVES level 3 and is ACCEPTED at level 2. Whether the engine behind that binding feeds it to `from_json` is **settled by nothing reachable**: the shipped wasm carries no source, and this tree is demonstrably older than the binding it would be asked about. Only a live measurement answers it, and none has been made. + +Reading the `json!({})` as *"level 1 discards the richness"* is inference from an absent implementation, which [[no-divergence-from-nextgraph]] forbids - and it was written here once, as *"no caller can reach any of it"*. ## "Not ready" and "ready and empty" are distinguishable — one level down diff --git a/.project/concepts/app-contract/knowledge_what-the-orm-writes-and-deletes-upstream.md b/.project/concepts/app-contract/knowledge_what-the-orm-writes-and-deletes-upstream.md index c740249..769ca22 100644 --- a/.project/concepts/app-contract/knowledge_what-the-orm-writes-and-deletes-upstream.md +++ b/.project/concepts/app-contract/knowledge_what-the-orm-writes-and-deletes-upstream.md @@ -1,12 +1,12 @@ --- type: knowledge summary: What the target offers for writing and removing — deletion is a SET MUTATION wired end to end, it removes the shape's predicates rather than the subject, and the ORM's writes never pass through `sparql_update` -last_checked: 2026-09-21 +last_checked: 2026-09-24 --- # What the ORM writes and deletes upstream -Read at the source in `nextgraph-rs` (`213338f697df15afc086c042f4bab1bffd01aa04`), which declares `@ng-org/orm@0.1.2-alpha.18`, `@ng-org/web@0.1.2-alpha.13`, `@ng-org/shex-orm@0.1.2-alpha.8` and `@ng-org/alien-deepsignals@0.1.2-alpha.11`. `packages/polyfill` installs `@ng-org/orm@0.1.2-alpha.21`, `@ng-org/web@0.1.2-alpha.14`, `@ng-org/shex-orm@0.1.2-alpha.9` and `@ng-org/alien-deepsignals@0.1.2-alpha.13` - the published packages are AHEAD of the source this repo cites, so where the two disagree both are named below. Every claim points at a symbol rather than a line, so `git grep` settles any doubt after the code moves. Companion to [[knowledge_what-a-read-scope-is-upstream]], which answers the reading half. +Read at the source in `nextgraph-rs` (`213338f697df15afc086c042f4bab1bffd01aa04`), which declares `@ng-org/orm@0.1.2-alpha.18`, `@ng-org/web@0.1.2-alpha.13`, `@ng-org/shex-orm@0.1.2-alpha.8` and `@ng-org/alien-deepsignals@0.1.2-alpha.11`. `packages/polyfill` installs `@ng-org/orm@0.1.2-alpha.21`, `@ng-org/web@0.1.2-alpha.14`, `@ng-org/shex-orm@0.1.2-alpha.9` and `@ng-org/alien-deepsignals@0.1.2-alpha.13` - the published packages are AHEAD of the source this repo cites, so where the two disagree both are named below. That gap is checked rather than remembered: the `ANCHOR` in `packages/polyfill/test/provenance.test.ts` holds it once and goes red from either end. Every claim points at a symbol rather than a line, so `git grep` settles any doubt after the code moves. Companion to [[knowledge_what-a-read-scope-is-upstream]], which answers the reading half. ## Removing an object is a set mutation, and LEVEL 3 answers @@ -45,7 +45,7 @@ Both return types are **inferred**, not annotated, and both functions are thin w ## The three remaining symbols -**`OrmSubscription`**, `RdfOrmSubscription` in alpha.21 — a class, and the machinery every other read and write goes through. Private constructor; `static getOrCreate(shapeType, scope)` pooled on `"||"` with refcounting and a 500 ms close delay. Instance surface: `signalObject: DeepSignalSet`, `readyPromise`, `close()`, `beginTransaction()`, `commitTransaction()`, `inTransaction`, `shapeType`, `scope`. In alpha.21 the second argument is no longer a bare `Scope` but an `RdfOrmConfig` (`Scope & { where?, orderBy?, pageSize?, maxActivePages? }`), `readyPromise` resolves to the subscription data rather than to nothing, and the instance also carries `mode`, `isReady`, `addChangeListener`, `removeChangeListener`, `nextPage` and `previousPage`. Whether any of that reaches the engine is NOT settled by the cited source, where `Verifier::start_orm` still builds its config from `json!({})` behind a `// TODO` (`engine/verifier/src/orm/graph/initialize.rs`): as of `213338f6` the richness is expressible at level 3 and discarded at level 1. Measuring it is not done here. It hands a caller nothing the target will not hand them — a shape, a scope and a set — and `useShape`, `getObjects` and `insertObject` are all built on it. +**`OrmSubscription`**, `RdfOrmSubscription` in alpha.21 — a class, and the machinery every other read and write goes through. Private constructor; `static getOrCreate(shapeType, scope)` pooled on `"||"` with refcounting and a 500 ms close delay. Instance surface: `signalObject: DeepSignalSet`, `readyPromise`, `close()`, `beginTransaction()`, `commitTransaction()`, `inTransaction`, `shapeType`, `scope`. In alpha.21 the second argument is no longer a bare `Scope` but an `RdfOrmConfig` (`Scope & { where?, orderBy?, pageSize?, maxActivePages? }`), `readyPromise` resolves to the subscription data rather than to nothing, and the instance also carries `mode`, `isReady`, `addChangeListener`, `removeChangeListener`, `nextPage` and `previousPage`. How far that config travels is answered in [[knowledge_what-a-read-scope-is-upstream]]: the shipped binding takes it at index 4 and the shipped ORM sends it there, while what the engine behind that binding does with it is settled by nothing reachable. The `json!({})` in `213338f6`'s `Verifier::start_orm` does NOT settle it, and reading it as *"level 1 discards the richness"* - the claim this leaf used to carry - is inference from an absent implementation. It hands a caller nothing the target will not hand them — a shape, a scope and a set — and `useShape`, `getObjects` and `insertObject` are all built on it. **`DiscreteOrmSubscription`** — the same class shape for JSON-CRDT documents. `static getOrCreate(documentId: string)`; `signalObject` is `DeepSignal | undefined` (a getter, undefined before the initial payload); it reaches the engine through `orm_start_discrete` and `discrete_orm_update`. Its unit of subscription is **one document id**, never a `Scope`.