Skip to content

Commit 5c536ca

Browse files
committed
docs(sheaves): update USAGE.md and POLICY.md terminology
1 parent 7038128 commit 5c536ca

2 files changed

Lines changed: 58 additions & 61 deletions

File tree

packages/sheaves/documents/POLICY.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Policy
22

33
The policy is the caller-supplied selection coroutine in the sheaf dispatch
4-
pipeline. It runs when the stalk at an invocation point contains more than one
5-
candidate and the sheaf has no data to resolve the ambiguity on its own. The
4+
pipeline. It runs when more than one candidate matches an invocation and the sheaf
5+
has no data to resolve the ambiguity on its own. The
66
caller is responsible for writing a policy that is correct for the providers it
77
will receive.
88

@@ -70,9 +70,9 @@ type PolicyContext<M> = {
7070
};
7171
```
7272

73-
**`constraints`** are metadata keys whose values are the same on every
74-
candidate in the stalk. Because all candidates agree on these keys, they carry
75-
no information useful for choosing between them — the sheaf strips them from
73+
**`constraints`** are metadata keys whose values are the same across every
74+
candidate. Because all candidates agree on these keys, they carry no
75+
information useful for choosing between them — the sheaf strips them from
7676
each candidate and delivers them separately. A policy that needs to know, say,
7777
the agreed `protocol` version reads it from `context.constraints.protocol`
7878
rather than from any individual candidate.

packages/sheaves/documents/USAGE.md

Lines changed: 53 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2,60 +2,60 @@
22

33
## Single provider
44

5-
When there is only one section per invocation point, no lift is needed — the
6-
dispatch short-circuits before the lift is ever called. Provide a no-op lift
7-
as a placeholder:
5+
When there is only one provider per invocation point, no policy is needed —
6+
the dispatch short-circuits before the policy is ever called. Provide a no-op
7+
policy as a placeholder:
88

99
```ts
1010
import { M } from '@endo/patterns';
11-
import { sheafify, makeSection, noopLift } from '@metamask/kernel-utils';
11+
import { sheafify, makeHandler, noopPolicy } from '@metamask/sheaves';
1212

1313
const priceGuard = M.interface('PriceService', {
1414
getPrice: M.callWhen(M.await(M.string())).returns(M.await(M.number())),
1515
});
1616

17-
const priceExo = makeSection('PriceService', priceGuard, {
17+
const priceHandler = makeHandler('PriceService', priceGuard, {
1818
async getPrice(token) {
1919
return fetchPrice(token);
2020
},
2121
});
2222

2323
const sheaf = sheafify({
2424
name: 'PriceService',
25-
sections: [{ exo: priceExo }],
25+
providers: [{ handler: priceHandler }],
2626
});
2727

28-
const section = sheaf.getSection({ guard: priceGuard, lift: noopLift });
29-
// section is a dispatch exo; call it like any capability
28+
const section = sheaf.getSection({ guard: priceGuard, lift: noopPolicy });
29+
// section is a dispatch handler; call it like any capability
3030
const price = await E(section).getPrice('ETH');
3131
```
3232

33-
## Multiple providers with a lift
33+
## Multiple providers with a policy
3434

35-
When the stalk at a given invocation point contains more than one germ, the
36-
sheaf calls the lift to choose. The lift is an `async function*` coroutine that
37-
yields candidates in preference order; it receives accumulated errors as the
38-
argument to each subsequent `.next()` so it can adapt its ranking.
35+
When more than one candidate matches an invocation, the sheaf calls the policy
36+
to choose. The policy is an `async function*` coroutine that yields candidates
37+
in preference order; it receives accumulated errors as the argument to each
38+
subsequent `.next()` so it can adapt its ranking.
3939

4040
The idiomatic pattern is a generator that `yield*`s candidates filtered by
4141
metadata, expressing priority tiers in source order:
4242

4343
```ts
44-
import { sheafify, constant } from '@metamask/kernel-utils';
45-
import type { Lift } from '@metamask/kernel-utils';
44+
import { sheafify, constant } from '@metamask/sheaves';
45+
import type { Policy } from '@metamask/sheaves';
4646

4747
type WalletMeta = { mode: 'fast' | 'reliable' };
4848

49-
const preferFast: Lift<WalletMeta> = async function* (germs) {
50-
yield* germs.filter((g) => g.metadata?.mode === 'fast');
51-
yield* germs.filter((g) => g.metadata?.mode === 'reliable');
49+
const preferFast: Policy<WalletMeta> = async function* (candidates) {
50+
yield* candidates.filter((c) => c.metadata?.mode === 'fast');
51+
yield* candidates.filter((c) => c.metadata?.mode === 'reliable');
5252
};
5353

5454
const sheaf = sheafify<WalletMeta>({
5555
name: 'Wallet',
56-
sections: [
57-
{ exo: fastExo, metadata: constant({ mode: 'fast' }) },
58-
{ exo: reliableExo, metadata: constant({ mode: 'reliable' }) },
56+
providers: [
57+
{ handler: fastHandler, metadata: constant({ mode: 'fast' }) },
58+
{ handler: reliableHandler, metadata: constant({ mode: 'reliable' }) },
5959
],
6060
});
6161

@@ -65,12 +65,12 @@ const section = sheaf.getSection({ guard: clientGuard, lift: preferFast });
6565

6666
The sheaf drives the generator: it primes it with `gen.next([])`, calls the
6767
chosen candidate, then passes any thrown errors back as `gen.next(errors)` so
68-
the lift can adapt before yielding the next candidate.
68+
the policy can adapt before yielding the next candidate.
6969

7070
Use the `constant`, `source`, or `callable` helpers to build metadata specs:
7171

7272
```ts
73-
import { constant, source, callable } from '@metamask/kernel-utils';
73+
import { constant, source, callable } from '@metamask/sheaves';
7474

7575
// static value known at construction time
7676
constant({ mode: 'fast' });
@@ -86,10 +86,11 @@ callable((args) => ({ cost: Number(args[0]) > 9000 ? 'high' : 'low' }));
8686

8787
## Discoverable sections
8888

89-
`getDiscoverableSection` works like `getSection` but the returned exo exposes
90-
its guard — it can be introspected by the caller to discover what methods and
91-
argument shapes it accepts. Use this when the recipient needs to advertise
92-
capability to a third party. It requires a `schema` map describing each method:
89+
`getDiscoverableSection` works like `getSection` but the returned handler
90+
exposes its guard — it can be introspected by the caller to discover what
91+
methods and argument shapes it accepts. Use this when the recipient needs to
92+
advertise capability to a third party. It requires a `schema` map describing
93+
each method:
9394

9495
```ts
9596
import type { MethodSchema } from '@metamask/kernel-utils';
@@ -108,60 +109,56 @@ const section = sheaf.getDiscoverableSection({
108109
`getSection` is the non-discoverable variant (no `schema` required).
109110

110111
`getGlobalSection` and `getDiscoverableGlobalSection` derive the guard
111-
automatically from the union of all presheaf sections. They are `@deprecated`
112-
as a nudge toward explicit guards once the caller knows the section set —
113-
explicit guards make the capability's scope visible at the call site. When
114-
sections are assembled dynamically (e.g., rebuilt at runtime from a set of
115-
grants that changes) and the union guard isn't known until after `sheafify`
116-
runs, the global variants are the right choice.
112+
automatically from the union of all providers. They are `@deprecated` as a
113+
nudge toward explicit guards once the caller knows the provider set — explicit
114+
guards make the capability's scope visible at the call site. When providers are
115+
assembled dynamically (e.g., rebuilt at runtime from a set of grants that
116+
changes) and the union guard isn't known until after `sheafify` runs, the
117+
global variants are the right choice.
117118

118-
## Remote sections
119+
## Remote providers
119120

120-
`makeRemoteSection` wraps a CapTP remote reference as a `PresheafSection`,
121-
fetching the remote's guard once at construction and forwarding all calls via
122-
`E()`. This lets you mix local exos and remote capabilities in the same sheaf:
121+
`makeRemoteSection` wraps a CapTP remote reference as a `Provider`, fetching
122+
the remote's guard once at construction and forwarding all calls via `E()`.
123+
This lets you mix local handlers and remote capabilities in the same sheaf:
123124

124125
```ts
125-
import {
126-
makeSection,
127-
makeRemoteSection,
128-
constant,
129-
} from '@metamask/kernel-utils';
126+
import { makeHandler, makeRemoteSection, constant } from '@metamask/sheaves';
130127

131-
const remoteSection = await makeRemoteSection(
132-
'RemoteWallet', // name for the wrapper exo
128+
const remoteProvider = await makeRemoteSection(
129+
'RemoteWallet', // name for the wrapper handler
133130
remoteCapRef, // CapTP reference
134131
constant({ mode: 'remote' }), // optional metadata
135132
);
136133

137134
const sheaf = sheafify({
138135
name: 'Mixed',
139-
sections: [localSection, remoteSection],
136+
providers: [localProvider, remoteProvider],
140137
});
141138
```
142139

143-
## Lift composition
140+
## Policy composition
144141

145-
`@metamask/kernel-utils` exports helpers for building lifts from composable
146-
parts, useful when lift logic would otherwise be duplicated across callers:
142+
`@metamask/sheaves` exports helpers for building policies from composable
143+
parts, useful when policy logic would otherwise be duplicated across callers:
147144

148145
```ts
149146
import {
150-
proxyLift,
147+
proxyPolicy,
151148
withFilter,
152149
withRanking,
153150
fallthrough,
154-
} from '@metamask/kernel-utils';
151+
} from '@metamask/sheaves';
155152
```
156153

157-
- **`withRanking(comparator)(inner)`** — sort germs by comparator before
154+
- **`withRanking(comparator)(inner)`** — sort candidates by comparator before
158155
passing to `inner`
159-
- **`withFilter(predicate)(inner)`** — remove germs that fail `predicate`
156+
- **`withFilter(predicate)(inner)`** — remove candidates that fail `predicate`
160157
before passing to `inner`
161-
- **`fallthrough(liftA, liftB)`** — try all candidates from `liftA` first;
162-
if all fail, try `liftB`
163-
- **`proxyLift(gen)`** — forward yielded candidates up and error arrays down
158+
- **`fallthrough(policyA, policyB)`** — try all candidates from `policyA`
159+
first; if all fail, try `policyB`
160+
- **`proxyPolicy(gen)`** — forward yielded candidates up and error arrays down
164161
to an already-started generator; useful when you need to add logic between
165162
yields (logging, counting, conditional abort). For simple sequential
166-
composition (`fallthrough`, `withFilter`) you do not need `proxyLift`
163+
composition (`fallthrough`, `withFilter`) you do not need `proxyPolicy`
167164
`yield*` forwards `.next(value)` to the delegated iterator automatically.

0 commit comments

Comments
 (0)