Skip to content

Commit 7865154

Browse files
committed
refactor(@metamask/sheaves): apply updated terminology
1 parent 8e7336e commit 7865154

17 files changed

Lines changed: 789 additions & 744 deletions

packages/sheaves/README.md

Lines changed: 63 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,111 +2,121 @@
22

33
Runtime capability routing adapted from sheaf theory in algebraic topology.
44

5-
`sheafify({ name, sections })` produces a **sheaf** — an authority manager
6-
over a presheaf of capabilities. The sheaf produces dispatch sections via
7-
`getSection`, each of which routes invocations through the presheaf.
5+
`sheafify({ name, providers })` produces a **sheaf** — an authority manager
6+
over a collection of capability providers. The sheaf produces dispatch handlers via
7+
`getSection`, each of which routes invocations through the provider set.
88

99
See [USAGE.md](./USAGE.md) for annotated examples and [LIFT.md](./LIFT.md) for
10-
the lift coroutine protocol and semantic equivalence assumption.
10+
the policy coroutine protocol and semantic equivalence assumption.
11+
12+
## Install
13+
14+
```sh
15+
yarn add @metamask/sheaves
16+
```
17+
18+
```sh
19+
npm install @metamask/sheaves
20+
```
1121

1222
## Concepts
1323

14-
**Presheaf section** (`PresheafSection`) — The input data: a capability (exo)
15-
paired with operational metadata, assigned over the open set defined by the
16-
exo's guard. This is an element of the presheaf F = F_sem x F_op.
24+
**Provider** (`Provider`) — The input data: a capability handler paired with
25+
operational metadata, assigned over the open set defined by the handler's guard.
26+
This is an element of the presheaf F = F_sem x F_op.
1727

18-
> A `getBalance(string)` provider with `{ cost: 100 }` is one presheaf
19-
> section. A `getBalance("alice")` provider with `{ cost: 1 }` is another,
20-
> covering a narrower open set.
28+
> A `getBalance(string)` provider with `{ cost: 100 }` is one provider. A
29+
> `getBalance("alice")` provider with `{ cost: 1 }` is another, covering a
30+
> narrower open set.
2131
22-
**Germ** — An equivalence class of presheaf sections at an invocation point,
23-
identified by metadata. At dispatch time, sections in the stalk with identical
24-
metadata are collapsed into a single germ; the system picks an arbitrary
32+
**Candidate** — An equivalence class of providers at an invocation point,
33+
identified by metadata. At dispatch time, providers in the stalk with identical
34+
metadata are collapsed into a single candidate; the system picks an arbitrary
2535
representative for dispatch. If two capabilities are indistinguishable by
2636
metadata, the sheaf has no data to prefer one over the other.
2737

2838
> Two `getBalance(string)` providers both with `{ cost: 1 }` collapse into
29-
> one germ. The lift never sees both — it receives one representative.
39+
> one candidate. The policy never sees both — it receives one representative.
3040
31-
**Stalk** — The set of germs matching a specific `(method, args)` invocation,
41+
**Stalk** — The set of candidates matching a specific `(method, args)` invocation,
3242
computed at dispatch time by guard filtering and then collapsing equivalent
3343
entries.
3444

35-
> Stalk at `("getBalance", "alice")` might contain two germs (cost 1 vs 100);
45+
> Stalk at `("getBalance", "alice")` might contain two candidates (cost 1 vs 100);
3646
> stalk at `("transfer", ...)` might contain one.
3747
38-
**Lift** — An `async function*` coroutine that yields candidates from a
39-
multi-germ stalk in preference order. See [LIFT.md](./LIFT.md) for the
40-
coroutine protocol, `LiftContext`, and the semantic equivalence assumption
41-
required of all lifts.
48+
**Policy** — An `async function*` coroutine that yields candidates from a
49+
multi-candidate stalk in preference order. See [LIFT.md](./LIFT.md) for the
50+
coroutine protocol, `PolicyContext`, and the semantic equivalence assumption
51+
required of all policies.
4252

4353
At dispatch time, metadata is decomposed into **constraints** (keys with the
44-
same value across every germ — topologically determined, not a choice) and
45-
**options** (the remaining keys — the lift's actual decision space). The lift
46-
receives only options on each germ; constraints arrive separately in the
54+
same value across every candidate — topologically determined, not a choice) and
55+
**options** (the remaining keys — the policy's actual decision space). The policy
56+
receives only options on each candidate; constraints arrive separately in the
4757
context.
4858

4959
> `argmin` by cost, `argmin` by latency, or any custom selection logic. The
50-
> lift is never invoked when the stalk resolves to a single germ — either
51-
> because only one section matched, or because all matching sections had
60+
> policy is never invoked when the stalk resolves to a single candidate — either
61+
> because only one provider matched, or because all matching providers had
5262
> identical metadata and collapsed to one representative.
5363
54-
**Sheaf** — The authority manager returned by `sheafify`. Holds the presheaf
55-
data (sections frozen at construction time) and exposes factory methods that
56-
produce dispatch exos on demand.
64+
**Sheaf** — The authority manager returned by `sheafify`. Holds the provider
65+
data (frozen at construction time) and exposes factory methods that
66+
produce dispatch handlers on demand.
5767

5868
```
59-
const sheaf = sheafify({ name: 'Wallet', sections });
69+
const sheaf = sheafify({ name: 'Wallet', providers });
6070
```
6171

62-
- `sheaf.getSection({ guard, lift })` — produce a dispatch exo
63-
- `sheaf.getDiscoverableSection({ guard, lift, schema })` — same, but the exo exposes its guard
72+
- `sheaf.getSection({ guard, lift })` — produce a dispatch handler
73+
- `sheaf.getDiscoverableSection({ guard, lift, schema })` — same, but the handler exposes its guard
6474

6575
## Dispatch pipeline
6676

6777
At each invocation point `(method, args)` within a granted section:
6878

6979
```
70-
getStalk(sections, method, args) presheaf → stalk (filter by guard)
80+
getStalk(providers, method, args) presheaf → stalk (filter by guard)
7181
evaluateMetadata(stalk, args) metadata specs → concrete values
7282
collapseEquivalent(stalk) locality condition (quotient by metadata)
7383
decomposeMetadata(collapsed) restriction map (constraints / options)
74-
lift(stripped, { method, args, operational selection (extra-theoretic)
75-
constraints })
76-
dispatch to chosen.exo evaluation
84+
policy(candidates, { method, args, operational selection (extra-theoretic)
85+
constraints })
86+
dispatch to chosen.handler evaluation
7787
```
7888

79-
The pipeline short-circuits at two points: if only one section matches the
80-
guard, it is invoked directly without evaluate/collapse/lift; if all matching
81-
sections collapse to an identical germ, the single representative is invoked
82-
without calling the lift.
89+
The pipeline short-circuits at two points: if only one provider matches the
90+
guard, it is invoked directly without evaluate/collapse/policy; if all matching
91+
providers collapse to an identical candidate, the single representative is invoked
92+
without calling the policy.
8393

8494
`callable` and `source` metadata specs make the stalk shape depend on the
85-
invocation arguments. A `swap(amount)` section can produce `{ cost: 'low' }`
95+
invocation arguments. A `swap(amount)` provider can produce `{ cost: 'low' }`
8696
for small amounts and `{ cost: 'high' }` for large ones, yielding a different
87-
set of germs — and potentially a different lift outcome — for the same method
88-
called with different arguments.
97+
set of candidates — and potentially a different policy outcome — for the same
98+
method called with different arguments.
8999

90100
## Design choices
91101

92-
**Germ identity is metadata identity.** The collapse step quotients by
93-
metadata: if two sections should be distinguishable, the caller must give them
94-
distinguishable metadata. Sections with identical metadata are treated as
102+
**Candidate identity is metadata identity.** The collapse step quotients by
103+
metadata: if two providers should be distinguishable, the caller must give them
104+
distinguishable metadata. Providers with identical metadata are treated as
95105
interchangeable. Under the sheaf condition (effect-equivalence), this recovers
96106
the classical equivalence relation on germs.
97107

98108
**Pseudosheafification.** The sheafification functor would precompute the full
99109
etale space. This system defers to invocation time: compute the stalk,
100-
collapse, decompose, lift. The trade-off is that global coherence (a lift
101-
choosing consistently across points) is not guaranteed.
110+
collapse, decompose, select via policy. The trade-off is that global coherence
111+
(a policy choosing consistently across points) is not guaranteed.
102112

103113
**Restriction and gluing are implicit.** Guard restriction induces a
104114
restriction map on metadata: restricting to a point filters the presheaf to
105-
covering sections (`getStalk`), then `decomposeMetadata` strips the metadata
115+
covering providers (`getStalk`), then `decomposeMetadata` strips the metadata
106116
to distinguishing keys — the restricted metadata over that point. The join
107-
works dually: the union of two sections has the join of their metadata, and
117+
works dually: the union of two providers has the join of their metadata, and
108118
restriction at any point recovers the local distinguishing keys in O(n).
109-
Gluing follows: compatible sections (equal metadata on their overlap) produce a
119+
Gluing follows: compatible providers (equal metadata on their overlap) produce a
110120
well-defined join. The dispatch pipeline computes all of this implicitly. The
111121
remaining gap is `revokeSite` (revoking over an open set rather than a point),
112122
which requires an `intersects` operator on guards not yet available.
@@ -115,7 +125,7 @@ which requires an `intersects` operator on guards not yet available.
115125

116126
This construction is more properly a **stack** in algebraic geometry. We call
117127
it a sheaf because engineers already know "stack" as a LIFO data structure, and
118-
the algebraic geometry term is unrelated. Within a germ, any representative
128+
the algebraic geometry term is unrelated. Within a candidate, any representative
119129
will do — authority-equivalence is asserted by constructor contract, not
120-
verified at runtime. Between germs, metadata distinguishes them and the lift
121-
resolves the choice.
130+
verified at runtime. Between candidates, metadata distinguishes them and the
131+
policy resolves the choice.

packages/sheaves/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"build:docs": "typedoc",
4343
"changelog:validate": "../../scripts/validate-changelog.sh @metamask/sheaves",
4444
"changelog:update": "../../scripts/update-changelog.sh @metamask/sheaves",
45-
"clean": "rimraf --glob './*.tsbuildinfo' ./.eslintcache ./coverage ./dist ./.turbo",
45+
"clean": "rimraf --glob './*.tsbuildinfo' ./.eslintcache ./coverage ./dist ./.turbo ./logs",
4646
"lint": "yarn lint:eslint && yarn lint:misc --check && yarn constraints && yarn lint:dependencies",
4747
"lint:dependencies": "depcheck --quiet",
4848
"lint:eslint": "eslint . --cache",

0 commit comments

Comments
 (0)