chore: readUnion a un consommateur declare, et son fake masque la rupture
This commit is contained in:
@@ -1,36 +0,0 @@
|
||||
---
|
||||
id: T01.d
|
||||
title: useShapeQuery reads through the SDK's shape query
|
||||
parent: T01
|
||||
depends_on: [T01.c]
|
||||
created: 2026-09-16
|
||||
claimed_by: null
|
||||
claimed_at: null
|
||||
blocked: false
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
`useShapeQuery` stops resolving a logical scope, enumerating documents, awaiting a sync barrier and calling `readUnion`, and reads through the **SDK's shape query** instead. The `ShapeQuery` snapshot and the capability filter survive; the home-grown pipeline goes.
|
||||
|
||||
**What "the pipeline" is, concretely.** `packages/polyfill/src/surface/watch-shape.ts` owns four steps today: resolve the logical scope to a document set (`listMyEntityDocs` in `shared-wallet/account-registry.ts`), open them through `ensureReposOpen` / `getSyncState` (`emulated-verifier/open-repo.ts`) which is the sync barrier `isPending` waits on, call `readUnion(docs)`, then filter the union by the shape's `@type` IRI. All four are the mechanism a translated parameter forced into existence, and all four are what this child removes.
|
||||
|
||||
**A blocker to resolve BEFORE implementing, not after.** `.project/concepts/app-contract/bug_useshape-live-read-needs-a-newer-broker.md` is an **open MAJOR bug**: the SDK's ORM subscription **never starts** against the broker deployed today — `orm_start_graph` is missing from two hand-maintained, independently-copied dispatch tables in any build made before commit `d5ecd0fd` — and the failure is an eternal pending set with one `console.error` as its only trace, indistinguishable from "this scope holds nothing". That leaf states explicitly that `watchShape` is **not affected**, because it is built on `doc_subscribe` (continuously present in both tables under a stable name), and the contract's `## Non-guarantees` tells applications to use `watchShape` for a reactive read for exactly that reason.
|
||||
|
||||
So this change takes the one reactive read that works and puts it on the path that does not, and the workaround the contract publishes stops existing. Establish what happens to that guarantee — a broker redeployment, a documented narrowing of the contract, a fallback — **before** writing the change. If it cannot be settled from the leaves, **stop and ask**. Do not implement and discover the consequence afterwards.
|
||||
|
||||
**`isError` has no counterpart at any level**, and that is recorded rather than assumed: `OrmSubscription`'s readiness promise is built with `resolve` alone, nothing rejects it, and `resolveReady()` runs on one path only — the arrival of initial data — so upstream's *"I could not find out"* **is** its *"still pending"* (annotation on `ShapeQuery` in `watch-shape.ts`; `docs/api-contract.md` § 6). Whatever replaces the pipeline must still be able to publish `isError`, or dropping it is a contract narrowing of its own that has to be declared.
|
||||
|
||||
**Facts — cite them, do not re-derive them.** `.project/concepts/app-contract/knowledge_what-a-read-scope-is-upstream.md`: the two axes and nothing else; the graph filter is literal; `did:ng:i` drops the graph filter entirely and runs over the whole local dataset with **nothing** added to narrow it by what the reader may open; the only bound is what the verifier has materialised locally; `subjects` filters the **root** shape only; `OrmSubscription.readyPromise` distinguishes not-ready from ready-and-empty at level 3 while the React `useShape` adapter drops that distinction. Also relevant: `makeReadFilteredView` (`packages/polyfill/src/emulated-verifier/read-filter.ts`) is the emulation of what the broker will bound **at delivery**, applied per document on what comes back — that is where the rights filter belongs, and `packages/polyfill/src/surface/use-shape.ts` already shows the shape of it.
|
||||
|
||||
**Leave `readUnion` alone here.** After this child `watch-shape.ts` no longer calls it, but `packages/polyfill/src/emulated-verifier/index-deposit.ts:253` and `:304` still do. Removing the symbol is T01.f's work.
|
||||
|
||||
**This child owns the contract edit and the version bump for its own change.** Edit `.project/concepts/app-contract/polyfill-surface/contract_polyfill-surface.md` — `## Guarantees` and `## Non-guarantees` first, because that is where a narrowing shows up, then `## Surface`, then `## Change policy`. Apply the contract's own rules to decide the level rather than assuming one. No other child edits the contract for this change.
|
||||
|
||||
**Hard gate:** `bun test` → 0 fail; `bunx tsc --noEmit -p packages/polyfill/tsconfig.json` → exit 0; `bunx tsc --noEmit -p packages/polyfill/e2e/tsconfig.json` → exit 0; `python3 ~/.claude/skills/concept/lint.py` → 0 ERROR. Anti-cheat: no `any`, no `@ts-ignore`, no deleting or skipping a test, no widening an assertion.
|
||||
|
||||
**Resolved since planning (2026-09-16).** `useShapeQuery` does NOT delegate to the SDK's `useShape` — that return type cannot carry the request state, which is the whole point. It KEEPS `watchShape`'s implementation: the observable and the state tracking are ours. What changes is the PARAMETER (the SDK's `Scope`) and what is queried underneath (the SDK's shape query instead of `readUnion`). **`isError` stays.** The reasoning "it survives only if the SDK exposes an error channel" is wrong: the polyfill's mission is to ENRICH the SDK in its announced direction, not to be bounded by what it exposes today. Wire real errors if you can; otherwise the field stays and is filled later.
|
||||
|
||||
## Progress
|
||||
|
||||
## Result
|
||||
@@ -32,6 +32,12 @@ Remove `readUnion` — and `UnionSubject` with it, if no published signature sti
|
||||
|
||||
**Resolved since planning (2026-09-16).** Do NOT read `ng-helpers` — not its code, not its tests. The isolation discipline says a counterpart is reached through its engagement and its usage declaration only. The planner's finding (that no contract leaf cites `readUnion`) was correct but obtained by a forbidden method. If this task needs to know who depends on `readUnion`, the answer belongs in a `usage_` declaration; `ng-helpers` has never authored one, and producing that is the fix, not a workaround by reading.
|
||||
|
||||
**Resolved since planning (2026-09-21) - `readUnion` HAS a declared consumer.** `ng-helpers` published its usage declaration (`polyfill-surface--ng-helpers`) and it says YES: `e2e/indexing-app.ts` calls `readUnion([doc])` twice, and `src/index.ts` REPUBLISHES it to ng-helpers' own consumers as the documented way to read an index. No ORM is wired there (`useShape: () => undefined`), so `useShapeQuery` is unreachable for them; their only fallback is an anchored `docs.sparqlQuery`. They declared this as a Need at full strength.
|
||||
|
||||
So the removal is not free. Before removing, decide with the owner what a consumer with no ORM reads with. Their declaration is the channel: read it at `ng-helpers`' repo through its published `usage_` leaf, never by reading their code.
|
||||
|
||||
**Also relevant, and worse than it looks.** That declaration reports `ng-helpers` still calling `createEntityDoc("public")` and `listMyEntityDocs("public")`, both invalid since `1.0.0-dev.5`, while its own test suite stays green because it runs against a fake that still models the superseded surface. A consumer can therefore be broken against us with nothing red on either side. Do not treat their green suite as evidence.
|
||||
|
||||
## Progress
|
||||
|
||||
## Result
|
||||
|
||||
Reference in New Issue
Block a user