diff --git a/.tasks/done/T01.p-four-minor-surface-faults.md b/.tasks/done/T01.p-four-minor-surface-faults.md new file mode 100644 index 0000000..aad52c3 --- /dev/null +++ b/.tasks/done/T01.p-four-minor-surface-faults.md @@ -0,0 +1,275 @@ +--- +id: T01.p +title: Four minor faults on the published surface +parent: T01 +depends_on: [T01.o] +created: 2026-09-24 +claimed_by: T01p-agent +claimed_at: 2026-09-24T18:50:06Z +blocked: false +--- + +## Description + +The four minor findings of T01.g, all CONFIRMED there. None is a rights or correctness defect; each is a published-surface or annotation inaccuracy. Verify each still stands before changing it - T01.o may have moved some. + +1. `Schema` and `DeepSignalSet` are published with no published signature using them, against the rule stated at `packages/polyfill/src/index.ts:78` (the same `ReadCap`/`InboxScope` rule, so this is a recurrence). Either a published signature uses them or they are unpublished. +2. Seven symbols annotated `kind=invention level=none ref=none` sit ABOVE the polyfill-era divider, under the heading that promises a target counterpart for every symbol (`index.ts:45`, `:111-123`). Either the annotation is wrong or they are on the wrong side of the divider. +3. `docChangeType` is published but absent from the concept contract's `## Surface`, and nothing pins that block against the actual exports. Add it, and consider whether the block should be pinned by a test the way the deletion list already is. +4. `account-registry.ts:971` annotates `storeRegistry.resolveScopeGraph`, unpublished since `1.0.0-dev.5`. A provenance annotation on an unpublished symbol claims a surface that does not exist. + +**Hard gate:** `bun test` -> 0 fail; both typechecks exit 0; `python3 ~/.claude/skills/concept/lint.py` -> 0 ERROR. Anti-cheat as usual. Any symbol you unpublish is a MAJOR by the contract's own change policy - follow it rather than deciding the level yourself. + +## Progress + +Items 1, 3 and 4 verified, fixed and committed. Item 2 investigated in full; the +coordinator confirmed the split and asked for the two determinable sub-findings (the +five `EventuallyConfig` field types, and `ShapeQuery`'s kind) to be applied, with the +third (`ShapeObservable`) left for the owner - see the "Item 2 - resolution" addendum +below. All four items are now closed for this task; the one open item is `ShapeObservable`, +explicitly the owner's. + +Commits made (chronological): `fix!:` unpublish Schema/DeepSignalSet + version bump to +`1.0.0-dev.12` (item 1); `docs:` add docChangeType to the concept contract's Surface and +pin the block with a new test (item 3); `fix:` drop the stray provenance annotation on +`resolveScopeGraph` (item 4); `fix:` move the five `EventuallyConfig` field types below +the divider + version bump to `1.0.0-dev.13` (item 2, part A); `fix:` re-kind `ShapeQuery` +to `announced-not-written` (item 2, part B). + +## Result + +**Status: done.** `ShapeObservable`'s divider placement is named below as the owner's +open item - not a blocker on this task, per the coordinator's instruction. + +### Item 1 - Schema / DeepSignalSet (DONE) + +VERIFIED by grep across `src`, `test`, `e2e`, `examples`: neither is used as an actual +TypeScript type anywhere in this repo outside the re-export itself (`DeepSignalSet` only +appears inside prose/JSDoc). Unpublished both from `packages/polyfill/src/index.ts` +(removed the `export type` lines and their `@provenance` annotations), following the +exact precedent already set for `ReadCap`/`InboxScope` - except neither has an internal +use to stay DEFINED for, so they are simply gone rather than moved to `model/types.ts`. + +Checked the sibling task's note about `ShapeResult`: VERIFIED that `useShape` now +declares a literal `ShapeResult` return type (changed today, replacing `any`), but +`ShapeResult` staying unpublished is an EXISTING, DOCUMENTED, deliberate pattern (its own +comment in `model/types.ts:81-99` says "Same discipline as {@link OrmSubscriptionHandle}" +- a published call returning an unpublished, package-invented result type, matching the +contract's own `## Surface` entry `useShape(...): ShapeResult`). This does not violate +the rule at `index.ts:78` (which is one-directional: a published TYPE needs a published +signature using it - not the reverse). Concluded this does NOT belong in item 1; no +change made. + +This is a MAJOR (published symbol removed). Version bumped `1.0.0-dev.11` -> +`1.0.0-dev.12` in `packages/polyfill/package.json`, a new dated entry added to the +concept contract's `## Change policy`, and `docs/api-contract.md` updated (the "Today" +code block in §4, the §14 ruling with a new paragraph matching the ReadCap/InboxScope +one, and the appendix's `direct:` inventory line) - in the SAME commit as the code +change. + +### Item 2 - seven `invention/none/none` symbols above the divider (BLOCKED, not changed) + +VERIFIED the exact seven, by grepping every `kind=invention level=none ref=none` +annotation in `src` and checking which are published above the `POLYFILL-ERA` divider in +`index.ts`: `NgLike`, `UseShapeLike`, `OrmSubscriptionLike`, `GetObjectsLike`, +`InsertObjectLike` (all in `model/types.ts`, all typing fields of `EventuallyConfig`) and +`ShapeQuery`, `ShapeObservable` (both in `surface/use-shape-query.ts`, the return shape of +`useShapeQuery`). + +They do NOT all resolve the same way: + +- **The five `EventuallyConfig` field types.** Each one's own comment says it "exists + only to describe what `configure` receives" - and `configure`/`EventuallyConfig` are + themselves already, unambiguously, on the deletion list (`knowledge_what-an-app-deletes- + at-migration.md`: "Deleted... today that is `configure` and its config type"). Their + `invention/none/none` annotation is honest (no kind in the closed set fits better). + INFERRED, with strong textual support: these five belong BELOW the divider, beside + `EventuallyConfig` - but moving them is the exact action the task names as requiring a + decision, so left untouched. +- **`ShapeQuery`.** VERIFIED: its declared shape - `{ data, isPending, isSuccess, + isError, error }` - is the LITERAL shape `.project/rules/nextgraph/surface-mirrors-the- + sdk.md` records as NextGraph developers' announced direction for `useShapeQuery` + (the same document `useShapeQuery` itself cites with `kind=announced-not-written`). The + word "ShapeQuery" appears in that record. Its `invention/none/none` annotation looks + like the wrong kind - `announced-not-written`, citing the same record, would be + consistent and would keep it above the divider with no relocation. Not applied: still a + change to a load-bearing annotation on a currently-blocked item, held for the same + decision. +- **`ShapeObservable`.** VERIFIED: the word "ShapeObservable" does NOT appear anywhere in + the announcement record, and VERIFIED in `examples/notebook/app.ts:192-217` that this + package's `useShapeQuery` is called as a plain factory (not a React hook) returning an + object the caller manually `.subscribe()`s and `.getSnapshot()`s - i.e. the + getSnapshot/subscribe/refetch wrapper is this package's OWN framework-agnostic + composition, not something NextGraph announced. Its `invention/none/none` annotation is + therefore honest. Whether this wrapper is deleted at migration (if the real, + eventually-shipped `useShapeQuery` is itself a plain hook returning the snapshot + directly, the way `useShape` does) or survives (if the real one needs the same kind of + wrapper) cannot be determined from anything in this repo - this is the irreducible + design question. + +No code or annotation changed for item 2 at this point in the session (see "Item 2 - +resolution" below for what the coordinator then asked to be applied). + +### Item 2 - resolution (PART A and B DONE; PART C left to the owner) + +The coordinator reviewed the analysis above, agreed the split was right, and asked for +Parts A and B to be applied since they are determinable from this repo, with Part C +(`ShapeObservable`) left untouched for the owner. + +**Part A - the five `EventuallyConfig` field types (DONE).** Verified the precondition +before moving anything, as instructed: grepped `index.ts` for `export { configure }` and +`export type { EventuallyConfig }` - both sit BELOW the `POLYFILL-ERA` divider (lines 174- +175 at the time of checking), i.e. already, unambiguously, on the deletion list. Since the +precondition held, moved `NgLike`, `UseShapeLike`, `OrmSubscriptionLike`, `GetObjectsLike` +and `InsertObjectLike` out of the SDK-SHAPED `export type { Nuri, NuriLike, PrincipalId, +... }` grouping and into a new `export type { ... } from "./model/types";` placed right +after `EventuallyConfig`'s own export, with prose explaining the move on both sides of the +divider. No signature changed - same five names, same five shapes, still exported from +`index.ts` - only which section of the entry documents them. + +This is a **PATCH** by the concept contract's own `## Change policy`: nothing under +`## Surface` or `## Guarantees` changed (neither contract document ever separately listed +these five as standalone entries - both already only show them as `EventuallyConfig`'s +field types, correctly tied to bootstrap), so none of the three `major` triggers (removed, +renamed, narrowed/reshaped) applies, and "a symbol added" doesn't fit either - this is +"changes neither the published surface nor anything above `## Guarantees`" verbatim. +Version bumped `1.0.0-dev.12` -> `1.0.0-dev.13` in `packages/polyfill/package.json`, a +dated `patch` entry added to the concept contract's `## Change policy`, and +`docs/api-contract.md` §14 updated (code block split in two, plus a paragraph) - all in +the same commit as the code move. + +**Part B - `ShapeQuery`'s kind (DONE - the record exists).** Checked the precondition the +coordinator named: `.project/rules/nextgraph/surface-mirrors-the-sdk.md` already carries +the record `useShapeQuery` itself cites (`kind=announced-not-written ... announced-by= +nextgraph-developers@2026-09-16`), and that same document's prose states the announced +shape verbatim as `{ data, isPending, isSuccess, isError, error }` - identical, field for +field, to `ShapeQuery`'s own declared interface - and literally contains the word +`ShapeQuery` (checked with the same word-boundary rule `test/provenance.test.ts`'s +`deadCitations` uses). The record exists, so the kind was re-annotated: `ShapeQuery` now +carries `kind=announced-not-written level=3 ref=.project/rules/nextgraph/surface-mirrors- +the-sdk.md:ShapeQuery announced-by=nextgraph-developers@2026-09-16`, citing the identical +statement `useShapeQuery` cites. `ref` points at the `.md` in this working copy, never a +source file, per the rule. No version bump: this changes a provenance comment only - +invisible to a consumer, no change under `## Surface` or `## Guarantees`, and `ShapeQuery`'s +divider position (above it) was already correct and stays put. + +**Part C - `ShapeObservable` (LEFT UNTOUCHED, as instructed).** Not moved, not re-kinded, +not weakened. It remains `kind=invention level=none ref=none`, above the divider, exactly +as found - the coordinator is putting its migration fate to the owner. + +Verified after both parts: `test/provenance.test.ts`'s well-formedness and citation checks +pass on the new `ShapeQuery` annotation, and the `announced-not-written` malformation +tests (which exercise the exact form `useShapeQuery` uses) still pass unchanged since they +test against a literal fixture, not the source tree. + +### Item 3 - docChangeType absent from the concept contract's Surface (DONE, and pinned) + +VERIFIED: `docChangeType` (lowercase, the function) is exported from `index.ts` but was +absent from `.project/concepts/app-contract/polyfill-surface/contract_polyfill- +surface.md`'s `## Surface` block. Also VERIFIED that `docs/api-contract.md` (a separate, +still-actively-maintained document at the repo root, distinct from the concept contract - +see Surprises) already had it correctly, and is pinned by three existing tests in +`test/vocabulary.test.ts`; the concept contract had NO such test. + +Added the `docChangeType` signature to the concept contract's Surface block, and added a +new test, `"every 'export' shown in the concept contract's Surface block is actually +exported"`, reusing the same `publishedNames()`/`isNamespaceMember()` helpers the +existing `docs/api-contract.md` check uses. VERIFIED the new test actually catches drift: +temporarily removed `docChangeType` from `index.ts`'s export list, re-ran the suite, saw +it fail naming exactly `docChangeType`, then restored the file and confirmed green again +(diff checked against the original afterward - clean revert). + +### Item 4 - stray provenance annotation on resolveScopeGraph (DONE) + +VERIFIED: `resolveScopeGraph` is not re-exported by `surface/placement.ts` (which backs +the published `storeRegistry` namespace), so `storeRegistry.resolveScopeGraph` names +nothing a consumer can reach - confirmed unpublished since `1.0.0-dev.5` per +`surface/placement.ts`'s own comment. VERIFIED its two siblings, `resolveWriteGraph` and +`listMyEntityDocs` (same file, same unpublished status), carry NO `@provenance` +annotation at all - the established convention for internal/unpublished helpers. Removed +the stray `@provenance storeRegistry.resolveScopeGraph ...` line to match; left the JSDoc +comment above it untouched (still an accurate internal note). No test previously caught +this because `test/provenance.test.ts` only checks that every PUBLISHED symbol has an +annotation, never the reverse (an annotation naming something that isn't published) - +this is a real, un-pinned gap in that test file, left as a follow-up (see below). + +### Gate (all measured on the final committed state, after item 2 parts A and B) + +- `bun test` -> **exit 0**, `492 pass / 0 fail` (matches the coordinator's own measured + baseline of `492 pass / 0 fail` exactly - item 3's new pinning test is the +1 over the + original `491 pass / 0 fail`, and items 2A/2B added no test and changed none). +- `pnpm exec tsc --noEmit -p packages/polyfill/tsconfig.json` -> **exit 0**. +- `pnpm exec tsc --noEmit -p packages/polyfill/e2e/tsconfig.json` -> **exit 0**. +- Example typecheck (`pnpm run typecheck` in `examples/notebook`) -> **exit 0**. +- `python3 ~/.claude/skills/concept/lint.py` -> **exit 0**, `0 ERROR` (5 pre-existing + WARNING categories, none new). +- e2e harness: NOT run. Nothing changed anywhere in this task (items 1, 3, 4, 2A, 2B) is + exercised by it: type-only exports, an annotation moved or re-kinded, doc text, one new + `bun:test` unit test, one dead annotation line removed. + +### Unused imports in account-registry.ts (confirmed, not touched) + +Confirmed the coordinator's reading exactly: `publishInboxAddress`, `readInboxCapsFor`, +`ownsDocument`, `documentInboxAddress`, `subscribePhysicalDoc`, `hasReadCap` and +`mustNotAttempt` are each imported into `packages/polyfill/src/shared-wallet/account- +registry.ts` and appear NOWHERE else in that file as executable code - six have exactly 1 +occurrence (the import line itself) and `ownsDocument` has 2, the second being a JSDoc +mention ("a caller that genuinely prefers to carry on catches it itself, and one does: +`ownsDocument`, ..."), not a call. VERIFIED `noUnusedLocals` and `noUnusedParameters` are +absent from both `packages/polyfill/tsconfig.json` and the `tsconfig.base.json` it +extends, so both default to `false` - that is why `tsc` passes despite this. Pre-existing +(this task's item 4 commit removed exactly one line, the `@provenance` annotation on +`resolveScopeGraph`, confirmed by its own diff). Left untouched, as instructed - recorded +as a follow-up only. + +### Surprises + +- **VERIFIED, corrected before acting on it:** `docs/api-contract.md` genuinely exists at + the repo root and is actively maintained (last touched today by the sibling task, T01.o) + - I initially looked only under `packages/polyfill/docs/` (which holds a different file, + `polyfill-reference.md`) and briefly concluded the file referenced by `index.ts`'s header + comment and by `test/vocabulary.test.ts` was missing/stale. It is not. Two contract + documents exist side by side: `docs/api-contract.md` (detailed, symbol-by-symbol, pinned + by three tests) and the concept contract (terser, what a consumer's `usage_` leaf pulls + against, now pinned by one more test after item 3). +- **INFERRED, not verified, out of scope:** the two documents' dual maintenance is itself + a standing cost (item 3 is exactly this: one drifted, one didn't) - not something this + task was scoped to resolve. + +### Owner's open item + +- **`ShapeObservable`'s migration fate** (`packages/polyfill/src/surface/use-shape- + query.ts:218`). Still `kind=invention level=none ref=none`, still above the + `POLYFILL-ERA` divider, untouched by this task. VERIFIED it is this package's own + framework-agnostic getSnapshot/subscribe/refetch composition (`examples/notebook/ + app.ts:192-217` calls `useShapeQuery` as a plain factory and manually + `.subscribe()`s/`.getSnapshot()`s it, not as a React hook), and VERIFIED the word + "ShapeObservable" does not appear anywhere in `.project/rules/nextgraph/surface-mirrors- + the-sdk.md`, so the `announced-not-written` route Part B used for `ShapeQuery` is not + available for it - honestly claiming it would require a record nobody has written. Its + divider placement depends on whether NextGraph's eventually-shipped `useShapeQuery` + needs the same wrapper or returns the snapshot directly (the way `useShape` does), which + is not knowable from anything in this repo. The coordinator is putting this to the + owner directly. + +### Follow-ups (not fixed, out of scope) + +- `test/provenance.test.ts` has no test for the direction item 4 exposed: an + `@provenance` annotation naming a symbol that is not actually published. Only the + reverse (every published symbol has an annotation) is pinned. +- Several `docs/api-contract.md` / `index.ts` header comments cite line numbers (e.g. + "index.ts:48-49", "index.ts:45, :111-123") rather than symbols, which the project's own + citation discipline discourages (line numbers rot); pre-existing, not introduced here, + and not mechanically checked. +- `.project/concepts/app-contract/polyfill-surface/contract_polyfill-surface.md` is + flagged by the concept linter as an oversized leaf (75 KB / 256 lines) - pre-existing, + a WARNING not an ERROR, unrelated to this task's changes beyond the lines added across + this session. +- Seven imports in `packages/polyfill/src/shared-wallet/account-registry.ts` are unused + in code (`publishInboxAddress`, `readInboxCapsFor`, `ownsDocument`, + `documentInboxAddress`, `subscribePhysicalDoc`, `hasReadCap`, `mustNotAttempt`) - + confirmed above, pre-existing, `tsc` passes only because `noUnusedLocals` is off. +- `docs/api-contract.md` §1's shown `EventuallyConfig` interface is itself stale (it + includes a `pointerGuard` field and omits `getObjects`/`insertObject`, neither matching + the real interface) - noticed while reading that section for Part A, pre-existing, + out of scope for this task.