Skip to content

Commit 20737b2

Browse files
grypezclaude
andcommitted
docs(kernel-utils): fix sheaf doc errors from revocation removal
- Remove stale revokePoint/revokeAll/getExported references from README.md and USAGE.md (the revocation API was removed in the preceding commit but the docs were not updated) - Fix withRanking/withFilter signatures in USAGE.md: the combinators are curried — withRanking(comparator)(inner), not withRanking(comparator, inner) - Correct the fallthrough doc comment: liftB does receive accumulated errors from liftA's attempts via yield* after its own failures (the test at compose.test.ts:337 confirms this); liftB is only unaware of them at its prime call - Document the germ identity invariant in LIFT.md: the lift must yield elements from its input germs array, not reconstructed objects, because the sheaf resolves the dispatch target by object identity Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 532fd27 commit 20737b2

4 files changed

Lines changed: 13 additions & 27 deletions

File tree

packages/kernel-utils/src/sheaf/LIFT.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ The sheaf drives it with the following protocol:
2121

2222
1. **Prime**`gen.next([])` starts the coroutine. The empty array is
2323
discarded; it exists only to satisfy the generator type.
24-
2. **Yield** — the coroutine yields a candidate germ to try next.
24+
2. **Yield** — the coroutine yields a candidate germ to try next. The yielded
25+
value must be an element of the `germs` array received on entry — the sheaf
26+
uses object identity to map it back to the original section, so constructing
27+
a new object with the same shape will produce "lift yielded an unknown germ".
2528
3. **Attempt** — the sheaf calls the candidate's exo method.
2629
4. **Success** — the result is returned; the generator is abandoned.
2730
5. **Failure** — the sheaf calls `gen.next(errors)`, passing the ordered list

packages/kernel-utils/src/sheaf/README.md

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
Runtime capability routing adapted from sheaf theory in algebraic topology.
44

55
`sheafify({ name, sections })` produces a **sheaf** — an authority manager
6-
over a presheaf of capabilities. The sheaf grants revocable dispatch sections
7-
via `getSection`, tracks all delegated authority, and supports point-wise
8-
revocation.
6+
over a presheaf of capabilities. The sheaf grants dispatch sections via
7+
`getSection` and tracks all delegated authority.
98

109
See [USAGE.md](./USAGE.md) for annotated examples and [LIFT.md](./LIFT.md) for
1110
the lift coroutine protocol and semantic equivalence assumption.
@@ -59,12 +58,8 @@ data (captured at construction time) and a registry of all granted sections.
5958
const sheaf = sheafify({ name: 'Wallet', sections });
6059
```
6160

62-
- `sheaf.getSection({ guard, lift })` — produce a revocable dispatch exo
61+
- `sheaf.getSection({ guard, lift })` — produce a dispatch exo
6362
- `sheaf.getDiscoverableSection({ guard, lift, schema })` — same, but the exo exposes its guard
64-
- `sheaf.revokePoint(method, ...args)` — revoke every granted section whose
65-
guard covers the point
66-
- `sheaf.getExported()` — union guard of all active (non-revoked) sections
67-
- `sheaf.revokeAll()` — revoke every granted section
6863

6964
## Dispatch pipeline
7065

packages/kernel-utils/src/sheaf/USAGE.md

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const sheaf = sheafify({
3131
});
3232

3333
const section = sheaf.getSection({ guard: priceGuard, lift: noop });
34-
// section is a revocable dispatch exo; call it like any capability
34+
// section is a dispatch exo; call it like any capability
3535
const price = await E(section).getPrice('ETH');
3636
```
3737

@@ -119,19 +119,6 @@ sections are assembled dynamically (e.g., rebuilt at runtime from a set of
119119
grants that changes) and the union guard isn't known until after `sheafify`
120120
runs, the global variants are the right choice.
121121

122-
## Revocation
123-
124-
```ts
125-
// revoke every granted section whose guard covers this invocation point
126-
sheaf.revokePoint('getPrice', 'ETH');
127-
128-
// revoke all granted sections at once
129-
sheaf.revokeAll();
130-
131-
// union guard of all currently active (non-revoked) sections
132-
const exported = sheaf.getExported();
133-
```
134-
135122
## Remote sections
136123

137124
`makeRemoteSection` wraps a CapTP remote reference as a `PresheafSection`,
@@ -167,9 +154,9 @@ import {
167154
} from '@metamask/kernel-utils';
168155
```
169156

170-
- **`withRanking(comparator, inner)`** — sort germs by comparator before
157+
- **`withRanking(comparator)(inner)`** — sort germs by comparator before
171158
passing to `inner`
172-
- **`withFilter(predicate, inner)`** — remove germs that fail `predicate`
159+
- **`withFilter(predicate)(inner)`** — remove germs that fail `predicate`
173160
before passing to `inner`
174161
- **`fallthrough(liftA, liftB)`** — try all candidates from `liftA` first;
175162
if all fail, try `liftB`

packages/kernel-utils/src/sheaf/compose.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,9 @@ export const withRanking =
8989
* `.next(value)` to the inner iterator, so error arrays are correctly
9090
* threaded through each inner lift.
9191
*
92-
* liftB starts fresh and only sees errors from its own failed attempts,
93-
* not from liftA's attempts.
92+
* liftB is not informed of liftA's failures at its prime call, but via
93+
* `yield*` it receives all accumulated errors (including liftA's) as the
94+
* argument to each subsequent `next(errors)` after its own failed attempts.
9495
*
9596
* @param liftA - First lift; its candidates are tried before liftB's.
9697
* @param liftB - Fallback lift; only invoked after liftA is exhausted.

0 commit comments

Comments
 (0)