chore: T01.g est close, sa trouvaille bloquante est devenue T01.o
This commit is contained in:
@@ -67,3 +67,4 @@ The polyfill's published surface has drifted from the SDK's: invented names, inv
|
||||
- T01.l - `ng-e2e-helpers`' peer range tightened to `>=0.1.2-alpha.13 <0.1.2`, MEASURED BY RESOLUTION: before, 4 versions admitted with `maxSatisfying` = the bare `0.1.2` of 2025-10-19; after, 3, and pnpm resolves `0.1.2-alpha.15`. The premise it was handed was half wrong and it said so: pnpm never actually RESOLVED to `0.1.2` because it prefers the `latest` dist-tag, which upstream happens to point at alpha.15 - so the trap was one dist-tag move from firing, and only resolution testing shows that either way. `playwright` 1.61.1 -> 1.63.0 (raises `engines.node` to `>=20`, drops `fsevents`), e2e `46 passed / 46` on the first run. Both `typecheck` scripts moved from `bunx tsc` to `pnpm exec tsc`, VERIFIED with `~/.bun/bin` off PATH and `command -v bun` empty. MEASURED about the optional peer: a consumer of the packed polyfill receives NO `@ng-org` package under pnpm, so the old `bun install` semantics survived the tool change - but THIS checkout does get the ORM, through `packages/polyfill/package.json:33`'s devDependency, so the runner's "install it in packages/polyfill" was a false lead and both texts now say the optional peer governs what a CONSUMER receives. `pnpm link` PERFORMED and it works: the polyfill resolves to the checkout and stays at ONE copy, so the single-instance hazard is untripped - but `@ng-org/web` and `@ng-org/orm` end up at TWO copies when the app also imports the SDK, pnpm warning by name, and `file:` gives one copy at the cost of repacking, which forfeits live editing. Left alone, reported: the polyfill's own four `"*"` peers admit ONLY the bare `0.1.2` of 16 published versions and EXCLUDE every alpha, because `*` matches no pre-release - inert while the polyfill is unpublished, certain to bite at first publish (now T01.n); `examples/notebook` has no `typecheck` script; `bun build` at `orm-live-read.ts:128` and `bun run` in `mint-wallet` are still bun-bound.
|
||||
- T01.m - THE COUNT WAS ELEVEN, not the three the split had named. Deleted from `open-repo.ts`: `held`, `syncState`, `inFlight`, `settleInFlight`, `registryEpoch` - the last two IMPLIED openness through a short-circuit and nobody had ever counted them, including six adversarial rounds of T01.j. Surviving as the one answer, in `surface/subscribe.ts` (NOT `emulated-verifier/`, which is what the task file wrongly said): `fanOuts`, `establishing`, `realUnsub`, `lastState`, `attempt` - and `lastState` turned out to have been a second barrier record all along, the correct one. THE INVARIANT, written at `open-repo.ts:100-128` and on `DocChannel`: "is this document open in this session" is answered in ONE place, `docChannel(nuri)`, and `open-repo` records only the bootstrap open it ASKED FOR. Teardown is now safe BY CONSTRUCTION with no cross-module notification added, because nothing outside records openness any more; `resetOpenedRepos` disowns rather than forgets, since forgetting yields the lax `"unknown"`. CONTRACT: both non-guarantees DELETED and the arrival guarantee unqualified, `1.0.0-dev.10`, guarantee and test in the same commit - and an INDEPENDENT review attacked that first and hardest and could not break it. `462 pass / 0 fail` six times, e2e `46 passed / 46`. My own spec was wrong twice and the agent said so instead of contorting to satisfy it: the module path, and failure B's acceptance test ("2 subscribes in-window"), which is UNACHIEVABLE because the fan-out correctly dedupes. Four adversarial passes found SIX real defects in the agent's own work, including two regressions and a test of its own that asserted the defect. THE LESSON WORTH KEEPING, from the last one: it had the right fix, could not make a test discriminate, and REVERTED it - correctly - but recorded "could not construct an ordering" as an OPEN QUESTION rather than a clean bill. That wording is what let a later pass finish it. The window is exactly ONE microtask hop, swept 0-6: at 0 the clear has not happened so delivery is legitimate, at 1 a forgotten barrier is delivered, at 2+ `lastState` is already null so nothing is queued. Its earlier fake put the rejection three hops behind the replay, so the replay always won - what it had wrong was the TEST, not the remedy. Also verified by the independent review, and worth knowing because the guarantee is right for a reason nobody had written down: `"unknown"` is unreachable where a barrier was expected NOT for the stated reason, but because `fetchReadCap` -> `downloadReadCap` -> `ensurePhysicalRepoOpen` populates the open record BEFORE `mustNotAttempt` is evaluated, so even the refused path leaves a trace. Follow-ups left open: a never-settling `doc_subscribe` is unrecoverable; `public-store.attempted` skips an open after `configure`; `forgetEverything` clears four maps never.
|
||||
- T01.n - the four `@ng-org` peer ranges fixed, VERIFIED BY RESOLUTION against the registry with the real node-semver engine rather than by reading. WORSE THAN THE TASK STATED: `@ng-org/orm`'s `"*"` admitted ZERO of its 22 published versions - that library publishes no bare `0.1.2` at all, so the range was UNSATISFIABLE, not merely wrong. The other three admitted exactly 1, the stale bare `0.1.2` of 2025, and excluded every alpha. After: web `>=0.1.2-alpha.14 <0.1.2` (2 admitted, maxSatisfying alpha.15), orm `>=0.1.2-alpha.21 <0.1.2` (2), shex-orm `>=0.1.2-alpha.9 <0.1.2` (2), alien-deepsignals `>=0.1.2-alpha.13 <0.1.2` (2). The floor was taken PER PACKAGE from its own devDependencies pin rather than copying the sibling package's `alpha.13` that the task offered as an example - that floor predates its own devDep bump and is a stale artifact, not a rule. `peerDependenciesMeta: optional` confirmed correct for all four and VERIFIED rather than assumed: every `@ng-org/*` reference in `packages/polyfill/src` is `import type` only, zero runtime imports, the application injecting the real functions through `bootstrap.ts`. `examples/notebook` gained the `typecheck` script it lacked. Fresh install ends with ONE `.pnpm` store entry per package and every consuming project's realpath matching. `462 pass / 0 fail`. It also caught an error of MINE: the task file I wrote carried a baseline of 449 while the measurement says 462 - written before T01.m added its tests and never refreshed. That is the second of my own specs to carry a wrong number, after T01.m's unachievable acceptance test. Left alone, reported: `ng-e2e-helpers`' own floor looks stale for the same reason (INFERRED, out of scope).
|
||||
- T01.g - the closing review REFUTED the parent's success criterion, which is what it was for. 8 findings over 53 published symbols (not the 25 the orchestrator's naive grep counted - it measured export STATEMENTS), 41 clean. THE BLOCKING ONE IS A RIGHTS LEAK, and it is this batch's whole failure mode applied to access control: `read-filter.ts` returned non-function members RAW on the written ground that "a plain property carries no items" - true of the CITED tree (orm alpha.18, a bare `DeepSignalSet`), FALSE of the INSTALLED alpha.21, whose `useShape` returns a `UseShapeResult` carrying every identity's items on the plain properties `data`, `promise` and `subscription`. A stranger read the owner's data through all three and nothing threw. It became T01.o. Three majors: the contract instructed an injection that does not resolve (`@ng-org/orm`'s `.` maps to `core.d.ts`, which has no `useShape`); four present-tense claims that the SDK returns a bare `DeepSignalSet` are false of alpha.21, TWO of them load-bearing provenance grounds - the `readUnion` failure mode again, invisible to `provenance.test.ts` by construction; and the only live gate for the published `useShape` injects a HAND-WRITTEN substitute, so no fake in the repository returned the shipped shape, which is exactly why every gate was green. Four minors became T01.p. THE LESSON FOR THE ORCHESTRATOR, not the code: ten adversarial passes and every re-run gate of this batch were blind to this, because the only artifact exercising that path was a fake that had never been checked against what ships. A green suite is worth what its fakes are faithful to, and nobody had asked.
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
---
|
||||
id: T01.g
|
||||
title: Adversarial review of the whole published surface
|
||||
parent: T01
|
||||
depends_on: [T01.a, T01.b, T01.c, T01.d, T01.e, T01.f, T01.h, T01.i, T01.j, T01.k, T01.l, T01.m, T01.n]
|
||||
created: 2026-09-16
|
||||
claimed_by: adversarial-reviewer
|
||||
claimed_at: 2026-09-24
|
||||
blocked: false
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
An adversarial pass over the **whole** published surface — every symbol exported from `packages/polyfill/src/index.ts`, not only the ones this batch touched — trying to **refute** the parent task's success criterion: *every published symbol either mirrors an SDK symbol in name, parameters and return, or carries a justified annotation*.
|
||||
|
||||
**Method, in this order.** For each published symbol ask the two questions of `.project/rules/nextgraph/no-divergence-from-nextgraph.md` in their stated order: *does the target do this?* **first**, verified in `nextgraph-rs` or stated by its author; *would an application have to unlearn it?* second, and only to rank severity — never to authorise a divergence. Then, for the name and the shape (`.project/rules/nextgraph/surface-mirrors-the-sdk.md`): is this the target's own name, does the verb belong to something else upstream, is the parameter passed through or translated, is the return the SDK's.
|
||||
|
||||
**Check every `@provenance` line 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"* — that is precisely how `readUnion` survived. Use the mechanism as T01.a left it, including whatever the new kind for an announced-but-unwritten target requires as evidence.
|
||||
|
||||
**Known, and not findings.** The three open `bug_` leaves in `.project/concepts/app-contract/`: `bug_useshape-live-read-needs-a-newer-broker` (MAJOR), `bug_a-lost-inbox-watch-is-never-retried` (MAJOR), `bug_an-empty-inbox-list-can-mean-a-failure`. Do not re-report them as new. **Do** report it if a change in this batch altered their status, or invalidated a workaround they or the contract publish — the `useShape` bug leaf and the contract's `## Non-guarantees` both name `watchShape` and `readUnion` as the unaffected paths, and both were changed here.
|
||||
|
||||
**Check the contract as delivered**, since three children edited it in sequence: `## Surface` matches the actual exports symbol for symbol; `## Change policy` records a version whose bump level follows the contract's own rules for what actually changed; no section was half-edited or edited twice for the same change; nothing published is left described by a sentence that is no longer true.
|
||||
|
||||
**Findings are leads, not mandates, and this child fixes nothing.** A finding without a reproducible failure scenario or a checkable citation does not count. Report symptom, precise location (`file:line`, the failing assertion, the offending extract) and, where it is already known, the cause — but do not instrument, bisect or repair. Each fix is a new task.
|
||||
|
||||
**Deliverable.** In `## Result`: findings by severity (blocking / major / minor), atomic, numbered `1.1`, `1.2`, … so they can be answered precisely. Neutral tone, no first or second person. One line of verdict on the test suites, not a list of what passes.
|
||||
|
||||
**Pass condition for this child** (it writes no code): run `bun test`, `bunx tsc --noEmit -p packages/polyfill/tsconfig.json`, `bunx tsc --noEmit -p packages/polyfill/e2e/tsconfig.json` and `python3 ~/.claude/skills/concept/lint.py` to **establish** the delivered state and report it verbatim; the review covers every symbol exported from `packages/polyfill/src/index.ts`, with the ones found clean stated as a count rather than an inventory.
|
||||
|
||||
## Progress
|
||||
|
||||
## Result
|
||||
|
||||
Read-only pass. Nothing in the delivered code was changed; one throwaway probe was run and deleted, and `git status` shows only this task file's own move.
|
||||
|
||||
### Delivered state, measured
|
||||
|
||||
- `bun test` -> `465 pass / 0 fail`, 1316 `expect()` calls, 40 files. MATCHES the figure on record.
|
||||
- `pnpm exec tsc --noEmit -p packages/polyfill/tsconfig.json` -> exit 0. MATCHES.
|
||||
- `pnpm exec tsc --noEmit -p packages/polyfill/e2e/tsconfig.json` -> exit 0. MATCHES.
|
||||
- `python3 ~/.claude/skills/concept/lint.py` -> **0 ERROR** (11 items across 4 WARNING classes). MATCHES.
|
||||
- `packages/polyfill/src/index.ts` carries **21** `export` statements. MATCHES. It **DIFFERS** on the symbol count: those 21 statements name **37** top-level names, of which 3 are namespace groupings (`docs`, `inbox`, `storeRegistry`), so the published surface as `test/provenance.test.ts:publishedSymbols` itself computes it is **53** (34 direct + 3 `docs` + 11 `inbox` + 5 `storeRegistry`), which is also exactly what `docs/api-contract.md`'s appendix lists. Not 25.
|
||||
- 123 `@provenance` annotations in `src`, covering the 53 published symbols plus 70 internal ones.
|
||||
|
||||
### Blocking
|
||||
|
||||
**1.1 The read filter on the published `useShape` is bypassed by the SDK version this repo builds against, and every identity's objects reach the caller out of the one shared wallet. PROVED.**
|
||||
|
||||
`src/surface/use-shape.ts:14-17` hands whatever the injected hook returned to `makeReadFilteredView`. `read-filter.ts:179-180` passes any non-function member through untouched, on the header's stated ground that "a plain property carries no items".
|
||||
|
||||
That ground held for `@ng-org/orm@0.1.2-alpha.18`, the version in the cited `nextgraph-rs` checkout: `sdk/js/orm/src/frontendAdapters/react/useShape.ts:123` ends `return state as DeepSignalSet<T>` - a bare set, whose item-yielding members are all functions the whitelist covers. It is FALSE of `@ng-org/orm@0.1.2-alpha.21`, which the `ANCHOR` calls the build and which is installed under `packages/polyfill/node_modules`: `dist/frontendAdapters/react/useShape.d.ts` declares the return `UseShapeResult`, an object carrying `data`, `promise`, `subscription`, `isLoading`, `nextPage`, `previousPage`. `data`, `promise` and `subscription` are plain PROPERTIES holding the items.
|
||||
|
||||
Repro run against the delivered `read-filter.ts` and `caps.ts`, with a `CapRegistry` in which alice and bob each minted one document, `isEnforcing() === true`, and bob the current holder, over an object of exactly the shape `useShape.d.ts` declares:
|
||||
|
||||
```
|
||||
alpha.18 shape -> iterated: [ "bob-own" ]
|
||||
alpha.21 shape -> .data items : [ "bob-own", "alice-private" ]
|
||||
alpha.21 shape -> .subscription.signalObject items: [ "bob-own", "alice-private" ]
|
||||
alpha.21 shape -> await .promise items: [ "bob-own", "alice-private" ]
|
||||
did anything throw? no.
|
||||
```
|
||||
|
||||
The contract instructs exactly the injection that opens this: `docs/api-contract.md:50` reads `useShape: UseShapeLike; // the REAL @ng-org/orm useShape`, and `contract_polyfill-surface.md:36` says the same. `EventuallyConfig.useShape` is not optional, so every application passes something, and `UseShapeLike = (...args: any[]) => any` (`src/model/types.ts:83`) accepts either return shape without a type error - which is why both typechecks stay at exit 0.
|
||||
|
||||
Two published statements are falsified by the run. `contract_polyfill-surface.md:256`: "**No unfiltered read through `useShape`.** Members that yield items are filtered and mutations pass through; anything else throws" - nothing throws, and the unfiltered items come back on three separate properties. And `docs/api-contract.md:345`'s rationale for wrapping the ORM, "an unwrapped ORM read returns EVERY identity's data out of the shared wallet with nothing signalling it", describes the WRAPPED `useShape`'s current behaviour on this version.
|
||||
|
||||
### Major
|
||||
|
||||
**2.1 `@ng-org/orm` does not export `useShape` at the specifier the contract names. CONFIRMED.** The installed manifest maps `"."` to `dist/core.d.ts`, and `core.d.ts` exports `initNg`, `ngSession`, `RdfOrmSubscription`, `DiscreteOrmSubscription`, `insertObject`, `removeObject`, `getObjects`, the `types.ts` re-export and three `alien-deepsignals` members. No `useShape`. The hook is at `@ng-org/orm/react` (also `/svelte`, `/svelte4`, `/vue`), or as `reactUseShape` from `@ng-org/orm/all`. An application following `contract_polyfill-surface.md:36` or `docs/api-contract.md:50` literally fails to resolve the import. Note the neighbouring claim that IS correct and was checked: `index.ts:162`'s reason for taking `RdfOrmConfig` from `/all` holds, since `core.d.ts` really does not carry it.
|
||||
|
||||
**2.2 Four present-tense claims that the SDK's `useShape` returns a bare `DeepSignalSet` are false of the version built against, and two of them are the stated ground of a provenance ruling. CONFIRMED.** The claim is at `src/model/types.ts:124`, `src/surface/use-shape-query.ts:11` and `:33`, and `contract_polyfill-surface.md:234` ("`useShape` returns a set you cannot tell from an empty one"). In `alpha.21` the return carries `isLoading` and `promise`. The two that are load-bearing:
|
||||
|
||||
- `src/surface/use-shape-query.ts:284`, the `announced-not-written` annotation, whose note reads "the SDK ships `useShape` returning a bare `DeepSignalSet`; the announced direction is a `useShapeQuery` returning a TanStack-shaped snapshot". The premise is false of what the SDK ships; the shipped hook already returns a load-state-carrying object.
|
||||
- `src/surface/use-shape-query.ts:193`, `ShapeQuery kind=invention level=none ref=none`, whose note opens "no upstream type carries load state". `UseShapeResult.isLoading` is an upstream load state at level 3. `ref=none` and `level=none` assert that nothing answers at any level.
|
||||
|
||||
This is the failure mode the mechanism exists to catch, in its documented form: the citations resolve, and the claims attached to them do not hold at the version a consumer compiles against. `test/provenance.test.ts` cannot see it by construction (it pins that a claim was made, not that it is true), and the `ANCHOR`'s own comment predicted this class of error.
|
||||
|
||||
**2.3 The one gate that exercises the published `useShape` against a live broker injects a hand-written substitute rather than the SDK's hook, which is why 1.1 is green. CONFIRMED.** `packages/polyfill/e2e/orm-live-entry.ts:101-105` defines `realOrmUseShape` as `RdfOrmSubscription.getOrCreate(...)` returning `sub.signalObject`, and `:109` injects that. The file's header states the substitution and its reason ("without a React tree to mount"). The state it fabricates - a hook returning a bare set - is the one `alpha.21` no longer produces, so the suite measures the `alpha.18` shape exclusively. Every unit fake does the same (`test/orm-fake.ts`, `e2e/polyfill-entry.ts:191`).
|
||||
|
||||
### Minor
|
||||
|
||||
**3.1 Two published types have no published signature using them, against the entry's own rule. CONFIRMED.** `src/index.ts:78` states "A type is published only when a PUBLISHED SIGNATURE uses it", and `:87-96` enumerates the warrants. `Schema` (`index.ts:149`) appears in no signature anywhere: `grep -rn "\bSchema\b"` over the working copy outside `node_modules` returns only its own export line, its annotation, and three document copies of that line. `DeepSignalSet` (`index.ts:151`) appears in `src` only inside prose and one annotation, never in a type position; no published signature returns one, since `useShape` returns `unknown`. This is the defect for which `ReadCap` and `InboxScope` were unpublished on 2026-08-10, with the rationale still at `index.ts:79-86`.
|
||||
|
||||
**3.2 Seven published symbols carrying `kind=invention level=none ref=none` sit under the block headed "a target counterpart for every symbol". CONFIRMED.** `src/index.ts:45-46` heads the first block "SDK-SHAPED - a target counterpart for every symbol / At migration the build alias is removed and these resolve to the real SDK", and `:166-169` heads the second "POLYFILL-ERA - THE DELETION LIST / nothing below has a target counterpart". Exported above the divider and annotated `invention`, which the taxonomy defines as "nothing at any level answers": `NgLike`, `UseShapeLike`, `OrmSubscriptionLike`, `GetObjectsLike`, `InsertObjectLike` (`:111-120`) and `ShapeQuery`, `ShapeObservable` (`:123`). The five `...Like` types are used by exactly one published signature each, all of them fields of `EventuallyConfig`, which is itself on the deletion list. `docs/api-contract.md:822` states the matching count as "exactly ONE is polyfill-era with no target counterpart".
|
||||
|
||||
**3.3 A published function is absent from the contract's `## Surface`. CONFIRMED.** `docChangeType` is exported at `src/index.ts:132` and listed in the appendix, and `contract_polyfill-surface.md`'s `## Surface` block shows only the type `DocChangeType`, inside the two `subscribeDoc` signatures (`:97-98`). Nothing pins that block: `test/vocabulary.test.ts` checks `docs/api-contract.md`, never the concept leaf.
|
||||
|
||||
**3.4 A stale annotation claims a published namespace name for an internal symbol. CONFIRMED.** `src/shared-wallet/account-registry.ts:971` annotates `storeRegistry.resolveScopeGraph`, and the format's own rule (`test/provenance.test.ts:22-24`) reserves the qualified form for a published namespace member. `resolveScopeGraph` was unpublished in `1.0.0-dev.5` (`src/surface/placement.ts:135,144`; `contract_polyfill-surface.md:325`), `surface/placement.ts` does not re-export it, and it is absent from the 53-symbol set `publishedSymbols()` computes.
|
||||
|
||||
### Found clean
|
||||
|
||||
**41 of the 53 published symbols** were walked against `nextgraph-rs` or the installed `.d.ts` and faulted on nothing. The 12 named above are `useShape`, `useShapeQuery`, `ShapeQuery`, `ShapeObservable`, `Schema`, `DeepSignalSet`, `docChangeType`, `NgLike`, `UseShapeLike`, `OrmSubscriptionLike`, `GetObjectsLike`, `InsertObjectLike`.
|
||||
|
||||
Checked and HOLDING, listed only because each was a plausible refutation that failed: `getObjects` and `insertObject` mirror `alpha.21`'s declared signatures exactly, including `Omit<RdfOrmConfig<T>, "pageSize" | "maxActivePages">`, and their `passthrough` notes disclose the filter and the guard; `RdfOrmConfig`'s `/all` subpath justification is true of the installed manifest; `Scope` is genuinely on `core.d.ts` via `export * from "./types.ts"`; `ng`, `NG`, `init`, `initNg`, `subscribeDoc`, `subscribeDocs`, the three `docs` members, the eleven `inbox` members and the five `storeRegistry` members carry annotations whose claims match their code. `## Change policy` records `1.0.0-dev.10`, which `packages/polyfill/package.json:3` pins, and its "Nothing is added, renamed or removed from the entry" is true: `git diff de9b8a0..HEAD -- packages/polyfill/src/index.ts` moves no `export` line.
|
||||
|
||||
### Verdict on the suites
|
||||
|
||||
Green as delivered and reproduced verbatim above, and 1.1 shows the green is not evidence: no fake in `test/` or `e2e/` returns the shape the installed SDK returns, so the suites exercise a hook shape that `@ng-org/orm@0.1.2-alpha.21` does not produce.
|
||||
Reference in New Issue
Block a user