@lapxo/bound 0.2.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CITATION.cff +19 -0
- package/TARGET.bound +95 -39
- package/dist/cli/accept.js +72 -558
- package/dist/cli/act-result.js +3 -103
- package/dist/cli/args.js +3 -44
- package/dist/cli/custodian.js +2 -29
- package/dist/cli/host.js +4 -32
- package/dist/cli/names.js +1 -12
- package/dist/cli/native-descendant.js +1 -19
- package/dist/cli/native.js +3 -60
- package/dist/cli/observe.js +1 -13
- package/dist/cli/owner.js +3 -139
- package/dist/cli/pass.js +21 -321
- package/dist/cli/place.js +6 -281
- package/dist/cli/release-result.js +3 -80
- package/dist/cli/retained-judgment.js +1 -25
- package/dist/cli/standing-result.js +4 -21
- package/dist/cli/takes.js +10 -111
- package/dist/cli/verb.d.ts +1 -2
- package/dist/cli/verb.js +83 -683
- package/dist/engine/computation.js +2 -0
- package/dist/engine/conformance.js +4 -0
- package/dist/engine/encoding.js +1 -2
- package/dist/engine/index.d.ts +1 -13
- package/dist/engine/index.js +2 -11
- package/dist/engine/object.js +1 -38
- package/dist/engine/ports.js +2 -103
- package/dist/fold/admission-history.js +1 -17
- package/dist/fold/bootstrap-anchor.js +1 -28
- package/dist/fold/ceilings.js +1 -142
- package/dist/fold/claims.js +2 -131
- package/dist/fold/closed.js +24 -234
- package/dist/fold/configures.js +1 -25
- package/dist/fold/digests.js +10 -226
- package/dist/fold/evidence.js +1 -22
- package/dist/fold/fold-worker.js +1 -13
- package/dist/fold/kept.js +12 -173
- package/dist/fold/keys.js +3 -91
- package/dist/fold/laid.js +3 -90
- package/dist/fold/nos.js +1 -48
- package/dist/fold/object.js +1 -2
- package/dist/fold/observed.js +27 -534
- package/dist/fold/opened.js +1 -33
- package/dist/fold/own.js +3 -217
- package/dist/fold/paid.js +1 -92
- package/dist/fold/place-inputs.js +1 -70
- package/dist/fold/places.js +3 -100
- package/dist/fold/rank.js +1 -9
- package/dist/fold/reach.js +1 -83
- package/dist/fold/readers.js +6 -142
- package/dist/fold/receipts.js +1 -47
- package/dist/fold/region-declarations.js +1 -13
- package/dist/fold/region.js +8 -286
- package/dist/fold/release-policy.js +1 -101
- package/dist/fold/resolved.js +6 -145
- package/dist/fold/roles.js +2 -59
- package/dist/fold/second.js +4 -71
- package/dist/fold/shards.js +12 -100
- package/dist/fold/signed.js +3 -81
- package/dist/fold/signers.js +1 -54
- package/dist/fold/stranger.js +6 -24
- package/dist/fold/views.js +1 -66
- package/dist/fold/wire.js +1 -46
- package/dist/fold/zoom.js +3 -81
- package/dist/host/act-cost.js +1 -25
- package/dist/host/adapters/keys/ed25519.js +1 -30
- package/dist/host/adapters/modules/javascript.js +1 -50
- package/dist/host/adapters/transport/http.js +1 -28
- package/dist/host/admitted-place.js +1 -63
- package/dist/host/archive.js +1 -152
- package/dist/host/call-context.js +1 -0
- package/dist/host/capsule-process.js +2 -61
- package/dist/host/capsule.js +9 -168
- package/dist/host/cell-receipts.js +12 -128
- package/dist/host/commit-result.js +1 -0
- package/dist/host/content-needed.js +1 -8
- package/dist/host/content-store.js +1 -31
- package/dist/host/contextual-place.js +2 -77
- package/dist/host/digest.js +2 -15
- package/dist/host/hash.js +1 -9
- package/dist/host/host-controls.js +1 -0
- package/dist/host/in-process-act.js +3 -0
- package/dist/host/in-process-context.js +3 -0
- package/dist/host/in-process-root.js +6 -0
- package/dist/host/in-process.js +4 -0
- package/dist/host/index.d.ts +1 -0
- package/dist/host/index.js +1 -0
- package/dist/host/io.js +1 -11
- package/dist/host/lifetime.js +1 -79
- package/dist/host/located.js +6 -105
- package/dist/host/native/bounded-file.js +1 -32
- package/dist/host/native/command.js +1 -91
- package/dist/host/native/control-bridge-worker.js +2 -88
- package/dist/host/native/control-bridge.js +1 -110
- package/dist/host/native/control-selection.js +1 -32
- package/dist/host/native/custody.js +1 -91
- package/dist/host/native/deadline.js +1 -28
- package/dist/host/native/descendants.js +1 -528
- package/dist/host/native/generated-custodian.js +5 -267
- package/dist/host/native/generated.js +1 -379
- package/dist/host/native/image.js +1 -45
- package/dist/host/native/jobs.js +2 -148
- package/dist/host/native/loader.js +1 -269
- package/dist/host/native/materialize.js +1 -175
- package/dist/host/native/module-closure.js +1 -130
- package/dist/host/native/module-delivery.d.ts +1 -62
- package/dist/host/native/module-delivery.js +1 -151
- package/dist/host/native/module-syntax.js +1 -69
- package/dist/host/native/native-binary.js +1 -115
- package/dist/host/native/native-program.js +1 -72
- package/dist/host/native/node-jobs.js +3 -187
- package/dist/host/native/node-launch.js +1 -159
- package/dist/host/native/preload.js +1 -45
- package/dist/host/native/reading.js +1 -249
- package/dist/host/native/receipt-environment.js +1 -41
- package/dist/host/native/references.js +1 -30
- package/dist/host/native/root.js +1 -37
- package/dist/host/native/route.js +1 -216
- package/dist/host/native/runtime.js +1 -9
- package/dist/host/native-reader-context.js +1 -8
- package/dist/host/native-receiver.js +1 -0
- package/dist/host/objects.js +1 -38
- package/dist/host/order.js +1 -2
- package/dist/host/place-act-transaction.js +4 -0
- package/dist/host/place-clock-selection.js +5 -124
- package/dist/host/ports/ingress.js +2 -57
- package/dist/host/ports/local-act.js +5 -172
- package/dist/host/ports/place-act.js +1 -169
- package/dist/host/ports/publication.js +1 -56
- package/dist/host/ports/signing.js +1 -74
- package/dist/host/ports/store.js +1 -18
- package/dist/host/ports/transport.js +1 -48
- package/dist/host/process-lifetime.js +1 -17
- package/dist/host/provide.js +1 -183
- package/dist/host/read-only.js +1 -9
- package/dist/host/reading-closures.js +7 -227
- package/dist/host/reading-context.js +1 -53
- package/dist/host/reading-identity-types.js +0 -0
- package/dist/host/reading-identity.js +3 -0
- package/dist/host/reading-preparation.js +6 -0
- package/dist/host/reference-authenticated.d.ts +1 -40
- package/dist/host/reference-authenticated.js +3 -100
- package/dist/host/reference-contracts.js +1 -6
- package/dist/host/reference-export.js +6 -81
- package/dist/host/reference-native-api.d.ts +1 -3
- package/dist/host/reference-native-api.js +1 -3
- package/dist/host/reference-native.js +1 -74
- package/dist/host/reference-profile.js +1 -63
- package/dist/host/reference-standing.js +2 -18
- package/dist/host/reference.js +1 -24
- package/dist/host/refusals.js +2 -43
- package/dist/host/release.js +4 -256
- package/dist/host/root-clock-source.js +1 -305
- package/dist/host/selected-capsules.js +1 -50
- package/dist/host/selected-topos.js +1 -80
- package/dist/host/signature-era.js +1 -0
- package/dist/host/signing.js +2 -48
- package/dist/host/source-content.js +2 -110
- package/dist/host/standing-carrier.js +1 -0
- package/dist/host/standing-projection.js +1 -0
- package/dist/host/timing.js +1 -7
- package/dist/host/walk.js +20 -193
- package/dist/judge/late.js +1 -33
- package/dist/judge/take.js +2 -75
- package/dist/judge/widening.js +1 -25
- package/dist/land/act.js +8 -302
- package/dist/land/alias.js +1 -41
- package/dist/land/held.js +1 -23
- package/dist/land/inert.js +1 -33
- package/dist/land/leaving.js +1 -55
- package/dist/land/ledger.js +7 -188
- package/dist/land/owned.js +4 -66
- package/dist/land/sign.js +1 -53
- package/dist/land/standing-pin.js +1 -49
- package/dist/land/vouched.js +1 -112
- package/dist/land/withdraw.js +1 -24
- package/dist/observe/files.js +1 -88
- package/dist/observe/identity.js +1 -61
- package/dist/observe/match.js +1 -8
- package/dist/observe/regions.js +7 -306
- package/dist/observe/run.js +2 -40
- package/dist/observe/runner.js +4 -93
- package/dist/public-types.d.ts +1114 -0
- package/dist/render/capsule.js +1 -30
- package/dist/render/field.js +1 -40
- package/dist/render/names.js +1 -4
- package/dist/render/open.js +1 -61
- package/dist/render/page.js +1 -7
- package/dist/render/receipts.js +1 -47
- package/dist/render/shape.js +1 -74
- package/dist/render/target.js +4 -52
- package/dist/render/view.js +7 -197
- package/dist/vendor/50086958553b9376d600583f7dff354196bfeb41170fc6d1482ca7bea7c493e2.LICENSE +21 -0
- package/dist/vendor/b3e938d28f88a1851af303a40c749e12ebd5a686daac4f0b343b5cdd2e040419.LICENSE +21 -0
- package/dist/vendor/bundle.json +1 -0
- package/dist/vendor/library11.js +1 -0
- package/dist/vendor/object-provider.js +42 -0
- package/dist/vendor/runtime.js +38 -0
- package/dist/vendor/sources.json +1 -0
- package/dist/wasm/adapter.d.ts +1 -51
- package/dist/wasm/adapter.js +1 -180
- package/dist/wasm/node-worker.js +1 -13
- package/dist/wasm/object.js +1 -76
- package/dist/wasm/worker.js +1 -7
- package/docs/contracts/closure-delivery.md +1 -1
- package/docs/contracts/closure-delivery.publication.json +1 -1
- package/docs/contracts/conformance.json +142 -0
- package/docs/contracts/determinism.bound +9 -0
- package/docs/contracts/engine-object-projection.publication.json +1 -1
- package/docs/contracts/engine.md +21 -1
- package/docs/contracts/native-host.md +21 -0
- package/docs/contracts/native-host.publication.json +25 -0
- package/docs/contracts/native-publication.inventory.json +3 -1
- package/docs/contracts/optional-wasm-adapter.publication.json +1 -1
- package/docs/contracts/publication.inventory.json +29 -0
- package/docs/contracts/reading-identity.md +37 -0
- package/docs/contracts/reading-identity.publication.json +25 -0
- package/docs/contracts/refusals.bound +51 -0
- package/docs/contracts/refusals.md +18 -3
- package/docs/contracts/refusals.publication.json +2 -2
- package/docs/contracts/views.md +8 -0
- package/docs/guide.md +10 -0
- package/docs/reference.md +40 -0
- package/docs/why.md +109 -0
- package/package.json +37 -18
- package/receipts.bound +11675 -9725
- package/samples/native-host/no.json +10 -0
- package/samples/native-host/yes.json +20 -0
- package/samples/reading-identity/no.json +20 -0
- package/samples/reading-identity/yes.json +46 -0
- package/vectors/native/native-host.vector.json +62 -0
- package/vectors/native/reading-identity.vector.json +101 -0
- package/vectors/native/refusals.vector.json +104 -0
- package/vendor/syntax/LICENSE.md +7 -0
- package/vendor/syntax/parser.js +1 -0
- package/dist/engine/object.d.ts +0 -17
- package/dist/engine/ports.d.ts +0 -32
- package/dist/host/native/module-closure.d.ts +0 -35
- package/dist/host/reference-export.d.ts +0 -33
- package/dist/host/reference-native.d.ts +0 -30
- package/dist/host/reference-profile.d.ts +0 -23
- package/dist/host/refusals.d.ts +0 -14
package/dist/judge/late.js
CHANGED
|
@@ -1,33 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { fieldOf } from "../fold/claims.js";
|
|
3
|
-
import { fullDigest } from "../fold/digests.js";
|
|
4
|
-
import { inside, locationsOf, vouchedCoordinates } from "../land/vouched.js";
|
|
5
|
-
import { wordOf } from "../fold/wire.js";
|
|
6
|
-
import { holdsCases } from "../fold/paid.js";
|
|
7
|
-
/**
|
|
8
|
-
* A demand that landed after its coordinates. A take judges what moved, because it assumes the demand came first and the
|
|
9
|
-
* tree after it; a demand that arrives second has nothing left to move — its cone is already in the ledger, every coordinate
|
|
10
|
-
* of it vouched at a digest. Judging that is reading, not observing, so it is answered where it lands and no file is
|
|
11
|
-
* touched to force it. A demand whose cone holds no vouched coordinate is not late, it is unlanded, and it waits for a take.
|
|
12
|
-
*/
|
|
13
|
-
export function lateFacts(store, signed, answered) {
|
|
14
|
-
const vouched = [...vouchedCoordinates(store)];
|
|
15
|
-
const views = `${wordOf(signed, 'families', 'view')}/`;
|
|
16
|
-
const out = [];
|
|
17
|
-
for (const line of signed) {
|
|
18
|
-
const scope = fieldOf(line, 'scope');
|
|
19
|
-
const value = fieldOf(line, 'value') || 'present';
|
|
20
|
-
if (fieldOf(line, 'role') !== 'demands' || value === 'withdraw' || answered.has(scope))
|
|
21
|
-
continue;
|
|
22
|
-
const asked = locationsOf(fieldOf(line, 'needs')).locations;
|
|
23
|
-
if (!asked.length || (!scope.startsWith(views) && !asked.some(holdsCases)))
|
|
24
|
-
continue;
|
|
25
|
-
const cone = asked.map((where) => vouched.filter(([coordinate]) => inside(coordinate, where)));
|
|
26
|
-
if (cone.some((held) => !held.length))
|
|
27
|
-
continue;
|
|
28
|
-
const held = cone.flat();
|
|
29
|
-
const at = `cone:${fullDigest(store, held.map(([coordinate, digest]) => `${coordinate} ${digest}`).sort()).replace(/^sha256:/, '')}`;
|
|
30
|
-
out.push(canonical({ scope, role: 'writes', form: 'alphabet', measure: fieldOf(line, 'measure') || 'status', value, by: 'judge', at }), canonical({ scope, role: 'writes', form: 'alphabet', measure: 'cone', value: held.map(([coordinate]) => coordinate).join('|'), by: 'judge', at }));
|
|
31
|
-
}
|
|
32
|
-
return out;
|
|
33
|
-
}
|
|
1
|
+
var b=Object.defineProperty;var p=(s,a)=>b(s,"name",{value:a,configurable:!0});import{library11_canonical as d}from"../vendor/runtime.js";import{fieldOf as t}from"../fold/claims.js";import{fullDigest as g}from"../fold/digests.js";import{inside as $,locationsOf as j,vouchedCoordinates as y}from"../land/vouched.js";import{wordOf as O}from"../fold/wire.js";import{holdsCases as C}from"../fold/paid.js";function z(s,a,h){const v=[...y(s)],w=`${O(a,"families","view")}/`,c=[];for(const e of a){const n=t(e,"scope"),l=t(e,"value")||"present";if(t(e,"role")!=="demands"||l==="withdraw"||h.has(n))continue;const r=j(t(e,"needs")).locations;if(!r.length||!n.startsWith(w)&&!r.some(C))continue;const m=r.map(o=>v.filter(([i])=>$(i,o)));if(m.some(o=>!o.length))continue;const f=m.flat(),u=`cone:${g(s,f.map(([o,i])=>`${o} ${i}`).sort()).replace(/^sha256:/,"")}`;c.push(d({scope:n,role:"writes",form:"alphabet",measure:t(e,"measure")||"status",value:l,by:"judge",at:u}),d({scope:n,role:"writes",form:"alphabet",measure:"cone",value:f.map(([o])=>o).join("|"),by:"judge",at:u}))}return c}p(z,"lateFacts");export{z as lateFacts};
|
package/dist/judge/take.js
CHANGED
|
@@ -1,75 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { answers, point, region } from '@lapxo/obligations/field';
|
|
4
|
-
import { parse, PROTOCOL } from '@lapxo/topos/wire';
|
|
5
|
-
import { observeText } from "../observe/files.js";
|
|
6
|
-
import { storeOf } from "../land/ledger.js";
|
|
7
|
-
import { holdsCases } from "../fold/paid.js";
|
|
8
|
-
/** A demanded location is a region: it is there when some place of the tree answers to it, file or directory alike. */
|
|
9
|
-
function located(root, location) {
|
|
10
|
-
return existsSync(join(root, location.replace(/\/+$/, '')));
|
|
11
|
-
}
|
|
12
|
-
function namedEffects(_root, _changed, _ROOTS) {
|
|
13
|
-
return [];
|
|
14
|
-
}
|
|
15
|
-
export function judgeTake(input) {
|
|
16
|
-
const { root, scope, value, locations, before, after } = input;
|
|
17
|
-
const paths = [...new Set([...before.keys(), ...after.keys()])].sort();
|
|
18
|
-
const moved = paths.filter((p) => before.get(p) !== after.get(p));
|
|
19
|
-
const notOwned = moved.filter((coordinate) => {
|
|
20
|
-
if (before.has(coordinate) || locations.includes(coordinate) || !input.witnessOf || !input.law)
|
|
21
|
-
return false;
|
|
22
|
-
const named = input.witnessOf(coordinate);
|
|
23
|
-
return named !== undefined && !input.law.includes(named);
|
|
24
|
-
});
|
|
25
|
-
const changed = moved.filter((coordinate) => !notOwned.includes(coordinate));
|
|
26
|
-
const absent = value === 'present' ? locations.filter((l) => !located(root, l)) : [];
|
|
27
|
-
const effects = changed.length && !absent.length ? namedEffects(root, changed, input.template) : [];
|
|
28
|
-
const envelope = {
|
|
29
|
-
scope,
|
|
30
|
-
cone: [...locations],
|
|
31
|
-
before: Object.fromEntries([...before].sort()),
|
|
32
|
-
after: Object.fromEntries([...after].filter(([coordinate]) => !notOwned.includes(coordinate)).sort()),
|
|
33
|
-
effects,
|
|
34
|
-
};
|
|
35
|
-
const digest = fullDigest(storeOf(root), JSON.stringify({ ...envelope, effects: effects.map((e) => ({ kind: e.kind, status: e.status, at: e.at })) }));
|
|
36
|
-
const refuse = (why) => ({ kind: 'refuse', why, envelope, digest, changed, notOwned });
|
|
37
|
-
const met = (why) => ({ kind: 'fact', why, envelope, digest, changed, notOwned });
|
|
38
|
-
if (!changed.length && !input.unpaid)
|
|
39
|
-
return refuse('nothing in the cone moved against what was vouched');
|
|
40
|
-
const cone = locations.map((l) => region(l));
|
|
41
|
-
const outside = changed.filter((coordinate) => !answers([point(coordinate)], cone));
|
|
42
|
-
if (outside.length)
|
|
43
|
-
return refuse(`outside the cone: ${outside.join(', ')}`);
|
|
44
|
-
if (absent.length)
|
|
45
|
-
return refuse(`demanded locations absent: ${absent.join(', ')}`);
|
|
46
|
-
if (input.shape === 'lock' || input.shape === 'render') {
|
|
47
|
-
const lines = locations.map((l) => ({ at: l, text: observeText(join(root, l)) }));
|
|
48
|
-
const absent = lines.filter((one) => one.text === undefined).map((one) => one.at);
|
|
49
|
-
if (absent.length)
|
|
50
|
-
return refuse(`a lock the demand names is not here: ${absent.join(', ')}`);
|
|
51
|
-
const said = lines.flatMap((one) => (one.text ?? '').split('\n').filter((line) => line.startsWith(PROTOCOL)));
|
|
52
|
-
const unread = said.filter((line) => parse(line).kind !== 'fact');
|
|
53
|
-
if (input.shape === 'lock' && (!said.length || unread.length)) {
|
|
54
|
-
return refuse(`a lock the demand names holds ${said.length ? `${unread.length} lines the wire does not read` : 'no claim'}`);
|
|
55
|
-
}
|
|
56
|
-
const rests = input.restsOn ?? '';
|
|
57
|
-
const digest = rests ? `sha256:${createHash('sha256').update(lines.map((one) => one.text ?? '').join('')).digest('hex')}` : rests;
|
|
58
|
-
if (rests && digest !== rests)
|
|
59
|
-
return refuse(`the lock moved: it rests on ${rests} and is ${digest}`);
|
|
60
|
-
return met(input.shape === 'lock' ? `${said.length} lines of the lock read, at the digest it rests on` : 'the region is here, at the digest it rests on');
|
|
61
|
-
}
|
|
62
|
-
const vectors = locations.filter((l) => holdsCases(l) && located(root, l));
|
|
63
|
-
if (!vectors.length)
|
|
64
|
-
return refuse('no vector location in the cone exists');
|
|
65
|
-
const red = effects.filter((e) => e.status === 'red' && e.admitted);
|
|
66
|
-
if (red.length)
|
|
67
|
-
return refuse(`effects red: ${red.map((e) => `${e.kind}@${e.at}`).join(', ')}`);
|
|
68
|
-
return met('demand met in its cone');
|
|
69
|
-
}
|
|
70
|
-
/** A take that met its cone carries the gates its batch passed: their runs join its envelope, and its receipt is sealed with them. */
|
|
71
|
-
export function sealed(root, verdict, gates) {
|
|
72
|
-
const envelope = { ...verdict.envelope, effects: [...verdict.envelope.effects, ...gates.map(({ kind, status, ms, at, admitted }) => ({ kind, status, ms, at, admitted }))] };
|
|
73
|
-
const digest = fullDigest(storeOf(root), JSON.stringify({ ...envelope, effects: envelope.effects.map((e) => ({ kind: e.kind, status: e.status, at: e.at })) }));
|
|
74
|
-
return { ...verdict, envelope, digest };
|
|
75
|
-
}
|
|
1
|
+
var L=Object.defineProperty;var i=(t,s)=>L(t,"name",{value:s,configurable:!0});import{createHash as N,existsSync as P,join as S}from"../host/io.js";import{fullDigest as T}from"../fold/digests.js";import{library12_answers as D,library12_point as H,library12_region as M}from"../vendor/runtime.js";import{library11_parse as W,library11_PROTOCOL as q}from"../vendor/runtime.js";import{observeText as z}from"../observe/files.js";import{storeOf as C}from"../land/ledger.js";import{holdsCases as A}from"../fold/paid.js";function E(t,s){return P(S(t,s.replace(/\/+$/,"")))}i(E,"located");function B(t,s,g){return[]}i(B,"namedEffects");function Z(t){const{root:s,scope:g,value:l,locations:o,before:r,after:d}=t,u=[...new Set([...r.keys(),...d.keys()])].sort().filter(e=>r.get(e)!==d.get(e)),f=u.filter(e=>{if(r.has(e)||o.includes(e)||!t.witnessOf||!t.law)return!1;const h=t.witnessOf(e);return h!==void 0&&!t.law.includes(h)}),c=u.filter(e=>!f.includes(e)),k=l==="present"?o.filter(e=>!E(s,e)):[],O=c.length&&!k.length?B(s,c,t.template):[],b={scope:g,cone:[...o],before:Object.fromEntries([...r].sort()),after:Object.fromEntries([...d].filter(([e])=>!f.includes(e)).sort()),effects:O},v=T(C(s),JSON.stringify({...b,effects:O.map(e=>({kind:e.kind,status:e.status,at:e.at}))})),a=i(e=>({kind:"refuse",why:e,envelope:b,digest:v,changed:c,notOwned:f}),"refuse"),w=i(e=>({kind:"fact",why:e,envelope:b,digest:v,changed:c,notOwned:f}),"met");if(!c.length&&!t.unpaid)return a("nothing in the cone moved against what was vouched");const R=o.map(e=>M(e)),x=c.filter(e=>!D([H(e)],R));if(x.length)return a(`outside the cone: ${x.join(", ")}`);if(k.length)return a(`demanded locations absent: ${k.join(", ")}`);if(t.shape==="lock"||t.shape==="render"){const e=o.map(n=>({at:n,text:z(S(s,n))})),h=e.filter(n=>n.text===void 0).map(n=>n.at);if(h.length)return a(`a lock the demand names is not here: ${h.join(", ")}`);const p=e.flatMap(n=>(n.text??"").split(`
|
|
2
|
+
`).filter(J=>J.startsWith(q))),j=p.filter(n=>W(n).kind!=="fact");if(t.shape==="lock"&&(!p.length||j.length))return a(`a lock the demand names holds ${p.length?`${j.length} lines the wire does not read`:"no claim"}`);const m=t.restsOn??"",_=m&&`sha256:${N("sha256").update(e.map(n=>n.text??"").join("")).digest("hex")}`;return m&&_!==m?a(`the lock moved: it rests on ${m} and is ${_}`):w(t.shape==="lock"?`${p.length} lines of the lock read, at the digest it rests on`:"the region is here, at the digest it rests on")}if(!o.filter(e=>A(e)&&E(s,e)).length)return a("no vector location in the cone exists");const y=O.filter(e=>e.status==="red"&&e.admitted);return y.length?a(`effects red: ${y.map(e=>`${e.kind}@${e.at}`).join(", ")}`):w("demand met in its cone")}i(Z,"judgeTake");function ee(t,s,g){const l={...s.envelope,effects:[...s.envelope.effects,...g.map(({kind:r,status:d,ms:$,at:u,admitted:f})=>({kind:r,status:d,ms:$,at:u,admitted:f}))]},o=T(C(t),JSON.stringify({...l,effects:l.effects.map(r=>({kind:r.kind,status:r.status,at:r.at}))}));return{...s,envelope:l,digest:o}}i(ee,"sealed");export{Z as judgeTake,ee as sealed};
|
package/dist/judge/widening.js
CHANGED
|
@@ -1,25 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { ALPHABETS, idsOf, INTERVALS, spanOf } from '@lapxo/topos/forms';
|
|
3
|
-
/**
|
|
4
|
-
* A ceiling that admits more than it did is not a revision of the same kind as one that admits less: narrowing costs
|
|
5
|
-
* the signer nothing anyone else can dispute, while widening gives back freedom the tree had already spent. So a line
|
|
6
|
-
* that widens what it replaces is refused unless it says what forced it — an `at` of the witness class, which names
|
|
7
|
-
* the reading or the case that made the old bound wrong. Policy may narrow; only a witness may widen. A list of what is
|
|
8
|
-
* forbidden narrows as it grows.
|
|
9
|
-
*/
|
|
10
|
-
function widens(now, before) {
|
|
11
|
-
const [was, held] = [spanOf(fieldOf(before, 'value')), spanOf(fieldOf(now, 'value'))];
|
|
12
|
-
if (was && held)
|
|
13
|
-
return INTERVALS.leq(was, held) && !INTERVALS.leq(held, was);
|
|
14
|
-
const [old, fresh] = [idsOf(fieldOf(before, 'value')), idsOf(fieldOf(now, 'value'))];
|
|
15
|
-
return old.polarity === fresh.polarity && ALPHABETS.leq(old, fresh) && !ALPHABETS.leq(fresh, old);
|
|
16
|
-
}
|
|
17
|
-
export function widenedWithoutWitness(proposed, standing, isCeiling, witness) {
|
|
18
|
-
const held = new Map(standing.filter(isCeiling).map((line) => [fieldOf(line, 'scope'), line]));
|
|
19
|
-
return proposed.filter((line) => {
|
|
20
|
-
const before = held.get(fieldOf(line, 'scope'));
|
|
21
|
-
if (!before || !isCeiling(line) || !widens(line, before))
|
|
22
|
-
return false;
|
|
23
|
-
return !fieldOf(line, 'at').startsWith(`${witness}:`);
|
|
24
|
-
});
|
|
25
|
-
}
|
|
1
|
+
var c=Object.defineProperty;var o=(e,a)=>c(e,"name",{value:a,configurable:!0});import{fieldOf as t}from"../fold/claims.js";import{library4_ALPHABETS as n,library4_idsOf as u,library4_INTERVALS as p,library4_spanOf as d}from"../vendor/runtime.js";function y(e,a){const[s,f]=[d(t(a,"value")),d(t(e,"value"))];if(s&&f)return p.leq(s,f)&&!p.leq(f,s);const[l,r]=[u(t(a,"value")),u(t(e,"value"))];return l.polarity===r.polarity&&n.leq(l,r)&&!n.leq(r,l)}o(y,"widens");function O(e,a,s,f){const l=new Map(a.filter(s).map(r=>[t(r,"scope"),r]));return e.filter(r=>{const i=l.get(t(r,"scope"));return!i||!s(r)||!y(r,i)?!1:!t(r,"at").startsWith(`${f}:`)})}o(O,"widenedWithoutWitness");export{O as widenedWithoutWitness};
|
package/dist/land/act.js
CHANGED
|
@@ -1,302 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
const pauseFor = (ms) => new Promise((resolve) => { setTimeout(resolve, ms); });
|
|
10
|
-
const ROOT = '_root';
|
|
11
|
-
const MINUTE = 60000;
|
|
12
|
-
const holderOf = (at) => {
|
|
13
|
-
const text = observeText(at);
|
|
14
|
-
if (text === undefined)
|
|
15
|
-
return undefined;
|
|
16
|
-
const [pid, what, since, token] = text.trim().split(' ');
|
|
17
|
-
return { pid: Number(pid), what: what ?? '', since: since ?? '', token: token ?? '' };
|
|
18
|
-
};
|
|
19
|
-
function overAMinute(at, began, holder) {
|
|
20
|
-
if (Date.now() - began < MINUTE)
|
|
21
|
-
return;
|
|
22
|
-
const who = holder === undefined ? 'a process' : `${holder.pid} · ${holder.what} since ${holder.since}`;
|
|
23
|
-
process.stderr.write(`RED wait · ${named(at)} is held by ${who} · a wait over a minute is a red, not a pause\n`);
|
|
24
|
-
throw new Error(`${selfName()}: REFUSE·stale nothing landed · a wait over a minute is a red, not a pause`);
|
|
25
|
-
}
|
|
26
|
-
const alive = (pid) => {
|
|
27
|
-
if (!Number.isSafeInteger(pid) || pid <= 0)
|
|
28
|
-
return true;
|
|
29
|
-
try {
|
|
30
|
-
process.kill(pid, 0);
|
|
31
|
-
return true;
|
|
32
|
-
}
|
|
33
|
-
catch (error) {
|
|
34
|
-
return error.code !== 'ESRCH';
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
const regionAt = (store, region) => {
|
|
38
|
-
const coordinate = region.replace(/\/+$/, '');
|
|
39
|
-
if ((coordinate && coordinate.split('/').some((step) => step === '..' || step === '.' || step === '')) || coordinate.startsWith('/'))
|
|
40
|
-
throw new Error(`${selfName()}: REFUSE·lock invalid region coordinate`);
|
|
41
|
-
return join(store, 'locks', coordinate ? encodeURIComponent(coordinate).replace(/^\./, '%2E').replace(/^_root$/, '%5Froot') : ROOT);
|
|
42
|
-
};
|
|
43
|
-
const coordinateOf = (file) => {
|
|
44
|
-
if (file === ROOT)
|
|
45
|
-
return '';
|
|
46
|
-
try {
|
|
47
|
-
return decodeURIComponent(file);
|
|
48
|
-
}
|
|
49
|
-
catch {
|
|
50
|
-
return file;
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
const lockFiles = (locks) => coordinatesUnder(locks, locks).filter((file) => {
|
|
54
|
-
if (file !== '.act')
|
|
55
|
-
return true;
|
|
56
|
-
// The legacy marker lists paths, while an actual region named .act has a numeric lock owner.
|
|
57
|
-
const holder = holderOf(join(locks, file));
|
|
58
|
-
return holder !== undefined && Number.isSafeInteger(holder.pid) && holder.pid > 0;
|
|
59
|
-
});
|
|
60
|
-
const overlaps = (a, b) => !a || !b || a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);
|
|
61
|
-
const treeAt = (store) => join(store, 'lock');
|
|
62
|
-
const named = (at) => (basename(at) === 'lock' ? 'the store' : basename(at).startsWith('@authority-') ? 'root authority' : basename(at) === '@projection' ? 'root projection' : `region ${basename(at) === ROOT ? '.' : basename(at)}`);
|
|
63
|
-
const owns = (at) => {
|
|
64
|
-
for (let frame = context.getStore(); frame !== undefined; frame = frame.parent) {
|
|
65
|
-
const token = frame.locks.get(at);
|
|
66
|
-
if (token !== undefined && held.get(at) === token)
|
|
67
|
-
return true;
|
|
68
|
-
}
|
|
69
|
-
return false;
|
|
70
|
-
};
|
|
71
|
-
const ownsRegion = (store) => [...held.keys()].some((at) => at.startsWith(`${join(store, 'locks')}/`) && owns(at));
|
|
72
|
-
const ownsAuthority = (store) => [...held.keys()].some((at) => dirname(at) === join(store, 'locks') && basename(at).startsWith('@authority-') && owns(at));
|
|
73
|
-
const projectionAt = (store) => join(store, 'locks', '@projection');
|
|
74
|
-
/** Reentry belongs to an awaited act's context. Another process or async act has no inherited authority. */
|
|
75
|
-
async function hold(at, what) {
|
|
76
|
-
if (owns(at))
|
|
77
|
-
return;
|
|
78
|
-
const frame = context.getStore();
|
|
79
|
-
if (frame === undefined)
|
|
80
|
-
throw new Error(`${selfName()}: REFUSE·lock no act owns this request`);
|
|
81
|
-
const began = Date.now();
|
|
82
|
-
const token = randomUUID();
|
|
83
|
-
let told = false;
|
|
84
|
-
mkdirSync(dirname(at), { recursive: true });
|
|
85
|
-
for (;;) {
|
|
86
|
-
try {
|
|
87
|
-
writeFileSync(at, `${process.pid} ${what.replace(/\s+/g, '_')} ${new Date().toISOString()} ${token}\n`, { flag: 'wx' });
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
catch (error) {
|
|
91
|
-
const code = error.code;
|
|
92
|
-
if (code === 'ENOENT')
|
|
93
|
-
mkdirSync(dirname(at), { recursive: true });
|
|
94
|
-
else if (code !== 'EEXIST')
|
|
95
|
-
throw error;
|
|
96
|
-
}
|
|
97
|
-
const holder = holderOf(at);
|
|
98
|
-
// Removing a dead owner's lock here would race with another process's recovery. Recovery is a separate host act.
|
|
99
|
-
if (holder !== undefined && !alive(holder.pid)) {
|
|
100
|
-
throw new Error(`${selfName()}: REFUSE·stale ${named(at)} belongs to exited process ${holder.pid}; host recovery required`);
|
|
101
|
-
}
|
|
102
|
-
overAMinute(at, began, holder);
|
|
103
|
-
if (!told && holder !== undefined) {
|
|
104
|
-
process.stderr.write(`WAIT ${named(at)} is held by ${holder.pid} · ${holder.what} since ${holder.since}\n`);
|
|
105
|
-
told = true;
|
|
106
|
-
}
|
|
107
|
-
await pauseFor(250);
|
|
108
|
-
}
|
|
109
|
-
if (told)
|
|
110
|
-
process.stderr.write(`HELD ${named(at)} after ${Date.now() - began} ms waiting\n`);
|
|
111
|
-
held.set(at, token);
|
|
112
|
-
frame.locks.set(at, token);
|
|
113
|
-
if (!process.listeners('exit').includes(releaseAll))
|
|
114
|
-
process.once('exit', releaseAll);
|
|
115
|
-
}
|
|
116
|
-
function release(at, token) {
|
|
117
|
-
if (held.get(at) !== token)
|
|
118
|
-
return;
|
|
119
|
-
held.delete(at);
|
|
120
|
-
const holder = holderOf(at);
|
|
121
|
-
if (holder?.pid === process.pid && holder.token === token && existsSync(at))
|
|
122
|
-
rmSync(at, { force: true });
|
|
123
|
-
}
|
|
124
|
-
function releaseAll() {
|
|
125
|
-
for (const [at, token] of [...held])
|
|
126
|
-
release(at, token);
|
|
127
|
-
}
|
|
128
|
-
process.once('SIGTERM', () => {
|
|
129
|
-
process.stderr.write(`${selfName()}: REFUSE·crash signal\n`);
|
|
130
|
-
releaseAll();
|
|
131
|
-
process.exit(1);
|
|
132
|
-
});
|
|
133
|
-
async function framed(takes, act) {
|
|
134
|
-
const frame = { parent: context.getStore(), locks: new Map() };
|
|
135
|
-
return context.run(frame, async () => {
|
|
136
|
-
try {
|
|
137
|
-
await takes();
|
|
138
|
-
return await act();
|
|
139
|
-
}
|
|
140
|
-
finally {
|
|
141
|
-
for (const [at, token] of [...frame.locks].reverse())
|
|
142
|
-
release(at, token);
|
|
143
|
-
frame.locks.clear();
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
function guardedRegions(store, regions, what, act, rootAuthority) {
|
|
148
|
-
return framed(async () => {
|
|
149
|
-
const tree = treeAt(store);
|
|
150
|
-
const asked = [...new Set((regions.length ? regions : ['']).map((one) => one.replace(/\/+$/, '')))];
|
|
151
|
-
if (rootAuthority && (asked.includes('') || (ownsRegion(store) && !owns(tree) && !ownsAuthority(store))))
|
|
152
|
-
throw new Error(`${selfName()}: REFUSE·lock authority dependencies and child regions must be declared together`);
|
|
153
|
-
if (owns(tree) || asked.every((region) => owns(regionAt(store, region)))) {
|
|
154
|
-
for (const region of asked)
|
|
155
|
-
await hold(regionAt(store, region), what);
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
if (ownsRegion(store))
|
|
159
|
-
throw new Error(`${selfName()}: REFUSE·lock declare every region before entering an act`);
|
|
160
|
-
const already = owns(tree);
|
|
161
|
-
// The tree lock is the acquisition gate. A whole-tree act cannot enter between checking it and taking regions.
|
|
162
|
-
await hold(tree, what);
|
|
163
|
-
try {
|
|
164
|
-
const locks = join(store, 'locks');
|
|
165
|
-
for (;;) {
|
|
166
|
-
const conflict = lockFiles(locks).find((file) => !owns(join(locks, file))
|
|
167
|
-
&& (file.startsWith('@authority-') || file === '@projection' ? asked.includes('')
|
|
168
|
-
: asked.some((region) => overlaps(region, file) || overlaps(region, coordinateOf(file)))));
|
|
169
|
-
if (conflict === undefined)
|
|
170
|
-
break;
|
|
171
|
-
const at = join(locks, conflict);
|
|
172
|
-
const began = Date.now();
|
|
173
|
-
let told = false;
|
|
174
|
-
for (let holder = holderOf(at); holder !== undefined; holder = holderOf(at)) {
|
|
175
|
-
if (!alive(holder.pid))
|
|
176
|
-
throw new Error(`${selfName()}: REFUSE·stale ${named(at)} belongs to exited process ${holder.pid}; host recovery required`);
|
|
177
|
-
overAMinute(at, began, holder);
|
|
178
|
-
if (!told) {
|
|
179
|
-
process.stderr.write(`WAIT ${named(at)} is held by ${holder.pid} · ${holder.what} since ${holder.since}\n`);
|
|
180
|
-
told = true;
|
|
181
|
-
}
|
|
182
|
-
await pauseFor(250);
|
|
183
|
-
}
|
|
184
|
-
if (told)
|
|
185
|
-
process.stderr.write(`HELD ${named(at)} after ${Date.now() - began} ms waiting\n`);
|
|
186
|
-
}
|
|
187
|
-
// Registered under the same acquisition gate as every legacy writer.
|
|
188
|
-
// Root writes overlap all locks; siblings keep distinct region locks.
|
|
189
|
-
// '@' is encoded for real region coordinates, so this is host bookkeeping.
|
|
190
|
-
if (rootAuthority)
|
|
191
|
-
await hold(join(store, 'locks', `@authority-${randomUUID()}`), what);
|
|
192
|
-
for (const region of asked.filter(Boolean).sort())
|
|
193
|
-
await hold(regionAt(store, region), what);
|
|
194
|
-
if (asked.includes(''))
|
|
195
|
-
await hold(regionAt(store, ''), what);
|
|
196
|
-
}
|
|
197
|
-
finally {
|
|
198
|
-
if (!already) {
|
|
199
|
-
const frame = context.getStore();
|
|
200
|
-
const token = frame.locks.get(tree);
|
|
201
|
-
if (token !== undefined) {
|
|
202
|
-
release(tree, token);
|
|
203
|
-
frame.locks.delete(tree);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}, act);
|
|
208
|
-
}
|
|
209
|
-
export function underTheRegions(store, regions, what, act) {
|
|
210
|
-
return guardedRegions(store, regions, what, act, false);
|
|
211
|
-
}
|
|
212
|
-
/** Protect the root authority/policy read through child publication. This is
|
|
213
|
-
* exclusion only: callers must authenticate contexts and compare prepared heads
|
|
214
|
-
* while held. It creates no grant, clock advance, lease or automatic recovery. */
|
|
215
|
-
export function underAuthorityRegions(store, regions, what, act) {
|
|
216
|
-
return guardedRegions(store, regions, what, act, true);
|
|
217
|
-
}
|
|
218
|
-
/** Protect an authority snapshot without taking a child region. The acquisition
|
|
219
|
-
* gate and temporary root marker exclude a root mutation while registering the
|
|
220
|
-
* shared read; existing child acts continue independently. This is exclusion,
|
|
221
|
-
* never authorization or a clock advance. */
|
|
222
|
-
export function underRootAuthority(store, what, act) {
|
|
223
|
-
return framed(async () => {
|
|
224
|
-
const tree = treeAt(store), root = regionAt(store, '');
|
|
225
|
-
if (owns(tree) || owns(root) || ownsAuthority(store))
|
|
226
|
-
return;
|
|
227
|
-
if (ownsRegion(store))
|
|
228
|
-
throw new Error(`${selfName()}: REFUSE·lock authority dependencies must be declared before entering a region act`);
|
|
229
|
-
await hold(tree, what);
|
|
230
|
-
try {
|
|
231
|
-
await hold(root, what);
|
|
232
|
-
await hold(join(store, 'locks', `@authority-${randomUUID()}`), what);
|
|
233
|
-
}
|
|
234
|
-
finally {
|
|
235
|
-
const frame = context.getStore();
|
|
236
|
-
for (const at of [root, tree]) {
|
|
237
|
-
const token = frame.locks.get(at);
|
|
238
|
-
if (token !== undefined) {
|
|
239
|
-
release(at, token);
|
|
240
|
-
frame.locks.delete(at);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}, act);
|
|
245
|
-
}
|
|
246
|
-
/** The fixed host may hand its child evidence of an actual held exclusion.
|
|
247
|
-
* It is an operational envelope, not a grant, signer or receipt identity. */
|
|
248
|
-
export function rootAuthorityProtection(store) {
|
|
249
|
-
const locks = [treeAt(store), regionAt(store, ''), ...held.keys()].filter(at => at === treeAt(store) || at === regionAt(store, '') || dirname(at) === join(store, 'locks') && basename(at).startsWith('@authority-'));
|
|
250
|
-
const lock = locks.find(owns);
|
|
251
|
-
if (lock === undefined)
|
|
252
|
-
throw Error(`${selfName()}: REFUSE·lock root authority is not protected`);
|
|
253
|
-
const holder = holderOf(lock);
|
|
254
|
-
if (holder?.pid !== process.pid || holder.token !== held.get(lock))
|
|
255
|
-
throw Error(`${selfName()}: REFUSE·lock authority protection changed`);
|
|
256
|
-
return Object.freeze({ store, lock, pid: holder.pid, token: holder.token });
|
|
257
|
-
}
|
|
258
|
-
/** expectedStore and expectedParent come from the fixed host's inheritance
|
|
259
|
-
* channel, never from world data. Matching a live lock proves exclusion only;
|
|
260
|
-
* signature, coverage and current context still require verification. */
|
|
261
|
-
export function assertRootAuthorityProtection(proof, expectedStore, expectedParent) {
|
|
262
|
-
if (!proof || proof.store !== expectedStore || !Number.isSafeInteger(expectedParent) || expectedParent <= 0 || proof.pid !== expectedParent
|
|
263
|
-
|| typeof proof.lock !== 'string' || typeof proof.token !== 'string' || !proof.token
|
|
264
|
-
|| !(proof.lock === treeAt(expectedStore) || proof.lock === regionAt(expectedStore, '')
|
|
265
|
-
|| dirname(proof.lock) === join(expectedStore, 'locks') && basename(proof.lock).startsWith('@authority-'))) {
|
|
266
|
-
throw Error(`${selfName()}: REFUSE·lock invalid inherited authority protection`);
|
|
267
|
-
}
|
|
268
|
-
const holder = holderOf(proof.lock);
|
|
269
|
-
if (!alive(expectedParent) || holder?.pid !== proof.pid || holder.token !== proof.token)
|
|
270
|
-
throw Error(`${selfName()}: REFUSE·lock inherited authority protection ended`);
|
|
271
|
-
}
|
|
272
|
-
/** A child can publish independently, but the joined root projection and its
|
|
273
|
-
* derived ledger appends have one writer. Authority protection already excludes
|
|
274
|
-
* root mutations, so this lock needs no acquisition-gate upgrade. */
|
|
275
|
-
export function underRootProjection(store, what, act) {
|
|
276
|
-
return framed(async () => {
|
|
277
|
-
if (owns(treeAt(store)) || owns(regionAt(store, '')))
|
|
278
|
-
return;
|
|
279
|
-
if (!ownsAuthority(store))
|
|
280
|
-
throw new Error(`${selfName()}: REFUSE·lock root projection requires authority protection`);
|
|
281
|
-
await hold(projectionAt(store), what);
|
|
282
|
-
}, act);
|
|
283
|
-
}
|
|
284
|
-
export const holdRoot = async (store, what) => {
|
|
285
|
-
if (!owns(treeAt(store)))
|
|
286
|
-
await hold(regionAt(store, ''), what);
|
|
287
|
-
};
|
|
288
|
-
export function underTheLock(store, what, act) {
|
|
289
|
-
return framed(async () => {
|
|
290
|
-
if (!owns(treeAt(store)) && ownsRegion(store))
|
|
291
|
-
throw new Error(`${selfName()}: REFUSE·lock a region act cannot upgrade to the tree; declare the tree before entering`);
|
|
292
|
-
await hold(treeAt(store), what);
|
|
293
|
-
const locks = join(store, 'locks');
|
|
294
|
-
const active = lockFiles(locks);
|
|
295
|
-
for (const file of [...active].sort())
|
|
296
|
-
await hold(join(locks, file), what);
|
|
297
|
-
for (const region of [...placesIn(dirname(store))].sort())
|
|
298
|
-
await hold(regionAt(store, region), what);
|
|
299
|
-
await hold(regionAt(store, ''), what);
|
|
300
|
-
}, act);
|
|
301
|
-
}
|
|
302
|
-
export const holds = (store, region) => [treeAt(store), regionAt(store, region)].some(owns);
|
|
1
|
+
var J=Object.defineProperty;var r=(e,t)=>J(e,"name",{value:t,configurable:!0});import{AsyncLocalStorage as q}from"node:async_hooks";import{randomUUID as D}from"node:crypto";import{basename as p,dirname as $,existsSync as L,join as a,mkdirSync as _,rmSync as K,writeFileSync as Q,realpathSync as V,resolve as Y}from"../host/io.js";import{BoundRefusal as Z}from"../host/refusals.js";import{selfName as ee}from"../fold/claims.js";import{placesIn as te}from"../fold/places.js";import{coordinatesUnder as ne,observeText as oe}from"../observe/files.js";const v=new q,we=r((e,t)=>v.run(e,t),"withActHost"),d=r(()=>v.getStore()?.name??ee(),"actName"),b=r(e=>{const t=v.getStore();t?t.report(e):process.stderr.write(e)},"report"),A=r(()=>{if(v.getStore()?.signal?.aborted)throw new Z("host/cancelled","REFUSE\xB7host/cancelled")},"checkCancellation");function E(e){let t=Y(e);const n=[];for(;!L(t);){const o=$(t);if(o===t)break;n.unshift(p(t)),t=o}return a(V(t),...n)}r(E,"canonicalActStore");const F=new q,y=new Map,B=r(e=>new Promise(t=>{setTimeout(t,e)}),"pauseFor"),j="_root",re=6e4,S=r(e=>{const t=oe(e);if(t===void 0)return;const[n,o,i,c]=t.trim().split(" ");return{pid:Number(n),what:o??"",since:i??"",token:c??""}},"holderOf");function z(e,t,n){if(Date.now()-t<re)return;const o=n===void 0?"a process":`${n.pid} \xB7 ${n.what} since ${n.since}`;throw b(`RED wait \xB7 ${R(e)} is held by ${o} \xB7 a wait over a minute is a red, not a pause
|
|
2
|
+
`),new Error(`${d()}: REFUSE\xB7stale nothing landed \xB7 a wait over a minute is a red, not a pause`)}r(z,"overAMinute");const N=r(e=>{if(!Number.isSafeInteger(e)||e<=0)return!0;try{return process.kill(e,0),!0}catch(t){return t.code!=="ESRCH"}},"alive"),k=r((e,t)=>{const n=t.replace(/\/+$/,"");if(n&&n.split("/").some(o=>o===".."||o==="."||o==="")||n.startsWith("/"))throw new Error(`${d()}: REFUSE\xB7lock invalid region coordinate`);return a(e,"locks",n?encodeURIComponent(n).replace(/^\./,"%2E").replace(/^_root$/,"%5Froot"):j)},"regionAt"),ie=r(e=>{if(e===j)return"";try{return decodeURIComponent(e)}catch{return e}},"coordinateOf"),G=r(e=>ne(e,e).filter(t=>{if(t!==".act")return!0;const n=S(a(e,t));return n!==void 0&&Number.isSafeInteger(n.pid)&&n.pid>0}),"lockFiles"),P=r((e,t)=>!e||!t||e===t||e.startsWith(`${t}/`)||t.startsWith(`${e}/`),"overlaps"),w=r(e=>a(e,"lock"),"treeAt"),R=r(e=>p(e)==="lock"?"the store":p(e).startsWith("@authority-")?"root authority":p(e)==="@projection"?"root projection":`region ${p(e)===j?".":p(e)}`,"named"),l=r(e=>{for(let t=F.getStore();t!==void 0;t=t.parent){const n=t.locks.get(e);if(n!==void 0&&y.get(e)===n)return!0}return!1},"owns"),x=r(e=>[...y.keys()].some(t=>t.startsWith(`${a(e,"locks")}/`)&&l(t)),"ownsRegion"),O=r(e=>[...y.keys()].some(t=>$(t)===a(e,"locks")&&p(t).startsWith("@authority-")&&l(t)),"ownsAuthority"),ce=r(e=>a(e,"locks","@projection"),"projectionAt");async function h(e,t){if(l(e))return;const n=F.getStore();if(n===void 0)throw new Error(`${d()}: REFUSE\xB7lock no act owns this request`);const o=Date.now(),i=D();let c=!1;for(_($(e),{recursive:!0});;){A();try{Q(e,`${process.pid} ${t.replace(/\s+/g,"_")} ${new Date().toISOString()} ${i}
|
|
3
|
+
`,{flag:"wx"});break}catch(g){const u=g.code;if(u==="ENOENT")_($(e),{recursive:!0});else if(u!=="EEXIST")throw g}const s=S(e);if(s!==void 0&&!N(s.pid))throw new Error(`${d()}: REFUSE\xB7stale ${R(e)} belongs to exited process ${s.pid}; host recovery required`);z(e,o,s),!c&&s!==void 0&&(b(`WAIT ${R(e)} is held by ${s.pid} \xB7 ${s.what} since ${s.since}
|
|
4
|
+
`),c=!0),await B(250)}c&&b(`HELD ${R(e)} after ${Date.now()-o} ms waiting
|
|
5
|
+
`),y.set(e,i),n.locks.set(e,i),process.listeners("exit").includes(C)||process.once("exit",C)}r(h,"hold");function I(e,t){if(y.get(e)!==t)return;y.delete(e);const n=S(e);n?.pid===process.pid&&n.token===t&&L(e)&&K(e,{force:!0})}r(I,"release");function C(){for(const[e,t]of[...y])I(e,t)}r(C,"releaseAll");function pe(){process.once("SIGTERM",()=>{b(`${d()}: REFUSE\xB7crash signal
|
|
6
|
+
`),C(),process.exit(1)})}r(pe,"installActSignalHandler");async function T(e,t){const n={parent:F.getStore(),locks:new Map};return F.run(n,async()=>{try{return A(),await e(),A(),await t()}finally{for(const[o,i]of[...n.locks].reverse())I(o,i);n.locks.clear()}})}r(T,"framed");function X(e,t,n,o,i){return T(async()=>{const c=w(e),s=[...new Set((t.length?t:[""]).map(u=>u.replace(/\/+$/,"")))];if(i&&(s.includes("")||x(e)&&!l(c)&&!O(e)))throw new Error(`${d()}: REFUSE\xB7lock authority dependencies and child regions must be declared together`);if(l(c)||s.every(u=>l(k(e,u)))){for(const u of s)await h(k(e,u),n);return}if(x(e))throw new Error(`${d()}: REFUSE\xB7lock declare every region before entering an act`);const g=l(c);await h(c,n);try{const u=a(e,"locks");for(;;){const m=G(u).find(f=>!l(a(u,f))&&(f.startsWith("@authority-")||f==="@projection"?s.includes(""):s.some(M=>P(M,f)||P(M,ie(f)))));if(m===void 0)break;const U=a(u,m),H=Date.now();let W=!1;for(let f=S(U);f!==void 0;f=S(U)){if(A(),!N(f.pid))throw new Error(`${d()}: REFUSE\xB7stale ${R(U)} belongs to exited process ${f.pid}; host recovery required`);z(U,H,f),W||(b(`WAIT ${R(U)} is held by ${f.pid} \xB7 ${f.what} since ${f.since}
|
|
7
|
+
`),W=!0),await B(250)}W&&b(`HELD ${R(U)} after ${Date.now()-H} ms waiting
|
|
8
|
+
`)}i&&await h(a(e,"locks",`@authority-${D()}`),n);for(const m of s.filter(Boolean).sort())await h(k(e,m),n);s.includes("")&&await h(k(e,""),n)}finally{if(!g){const u=F.getStore(),m=u.locks.get(c);m!==void 0&&(I(c,m),u.locks.delete(c))}}},o)}r(X,"guardedRegions");function Ee(e,t,n,o){return e=E(e),X(e,t,n,o,!1)}r(Ee,"underTheRegions");function ye(e,t,n,o){return e=E(e),X(e,t,n,o,!0)}r(ye,"underAuthorityRegions");function ge(e,t,n){return e=E(e),T(async()=>{const o=w(e),i=k(e,"");if(!(l(o)||l(i)||O(e))){if(x(e))throw new Error(`${d()}: REFUSE\xB7lock authority dependencies must be declared before entering a region act`);await h(o,t);try{await h(i,t),await h(a(e,"locks",`@authority-${D()}`),t)}finally{const c=F.getStore();for(const s of[i,o]){const g=c.locks.get(s);g!==void 0&&(I(s,g),c.locks.delete(s))}}}},n)}r(ge,"underRootAuthority");function me(e){e=E(e);const n=[w(e),k(e,""),...y.keys()].filter(i=>i===w(e)||i===k(e,"")||$(i)===a(e,"locks")&&p(i).startsWith("@authority-")).find(l);if(n===void 0)throw Error(`${d()}: REFUSE\xB7lock root authority is not protected`);const o=S(n);if(o?.pid!==process.pid||o.token!==y.get(n))throw Error(`${d()}: REFUSE\xB7lock authority protection changed`);return Object.freeze({store:e,lock:n,pid:o.pid,token:o.token})}r(me,"rootAuthorityProtection");function $e(e,t,n){if(t=E(t),!e||e.store!==t||!Number.isSafeInteger(n)||n<=0||e.pid!==n||typeof e.lock!="string"||typeof e.token!="string"||!e.token||!(e.lock===w(t)||e.lock===k(t,"")||$(e.lock)===a(t,"locks")&&p(e.lock).startsWith("@authority-")))throw Error(`${d()}: REFUSE\xB7lock invalid inherited authority protection`);const o=S(e.lock);if(!N(n)||o?.pid!==e.pid||o.token!==e.token)throw Error(`${d()}: REFUSE\xB7lock inherited authority protection ended`)}r($e,"assertRootAuthorityProtection");function Se(e,t,n){return e=E(e),T(async()=>{if(!(l(w(e))||l(k(e,"")))){if(!O(e))throw new Error(`${d()}: REFUSE\xB7lock root projection requires authority protection`);await h(ce(e),t)}},n)}r(Se,"underRootProjection");const Re=r(async(e,t)=>{e=E(e),l(w(e))||await h(k(e,""),t)},"holdRoot");function Ue(e,t,n){return e=E(e),T(async()=>{if(!l(w(e))&&x(e))throw new Error(`${d()}: REFUSE\xB7lock a region act cannot upgrade to the tree; declare the tree before entering`);await h(w(e),t);const o=a(e,"locks"),i=G(o);for(const c of[...i].sort())await h(a(o,c),t);for(const c of[...te($(e))].sort())await h(k(e,c),t);await h(k(e,""),t)},n)}r(Ue,"underTheLock");const be=r((e,t)=>(e=E(e),[w(e),k(e,t)].some(l)),"holds");export{$e as assertRootAuthorityProtection,E as canonicalActStore,Re as holdRoot,be as holds,pe as installActSignalHandler,me as rootAuthorityProtection,ye as underAuthorityRegions,ge as underRootAuthority,Se as underRootProjection,Ue as underTheLock,Ee as underTheRegions,we as withActHost};
|
package/dist/land/alias.js
CHANGED
|
@@ -1,41 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { fieldOf, fieldsOf } from "../fold/claims.js";
|
|
3
|
-
import { lockStanding } from "../fold/keys.js";
|
|
4
|
-
import { worldsIn } from "../fold/places.js";
|
|
5
|
-
import { ownLockOf } from "../fold/signed.js";
|
|
6
|
-
import { storeOf } from "./ledger.js";
|
|
7
|
-
const retracts = (withdraw, line) => Object.keys(withdraw).filter((key) => !ENVELOPE.has(key) && key !== 'value').every((key) => line[key] === withdraw[key]);
|
|
8
|
-
const pinScope = (scope) => scope === 'uses' || scope.startsWith('uses/') || scope.split('/').slice(1, -1).includes('uses');
|
|
9
|
-
const aliasWithdraw = (line) => fieldOf(line, 'value') === 'withdraw' && fieldOf(line, 'scope').startsWith('dep/') && fieldOf(line, 'role') !== 'reads';
|
|
10
|
-
/**
|
|
11
|
-
* An alias is gone only when no pin will still name its digest. The pins are the root's uses lines and each world's own,
|
|
12
|
-
* minus the pins this batch itself withdraws, plus the pins it adds. Checked before the trial, so a batch that would
|
|
13
|
-
* orphan a pin lands nothing.
|
|
14
|
-
*/
|
|
15
|
-
export function aliasPinned(root, signed) {
|
|
16
|
-
const aliases = lockStanding(storeOf(root)).filter((line) => fieldOf(line, 'scope').startsWith('dep/') && fieldOf(line, 'role') !== 'reads' && fieldOf(line, 'value') !== 'withdraw');
|
|
17
|
-
const digests = new Map();
|
|
18
|
-
for (const withdraw of signed.filter(aliasWithdraw)) {
|
|
19
|
-
const fields = fieldsOf(withdraw);
|
|
20
|
-
for (const line of aliases) {
|
|
21
|
-
if (!retracts(fields, fieldsOf(line)))
|
|
22
|
-
continue;
|
|
23
|
-
const digest = fieldOf(line, 'value');
|
|
24
|
-
const kept = signed.some((one) => fieldOf(one, 'scope') === fieldOf(line, 'scope') && fieldOf(one, 'value') === digest);
|
|
25
|
-
if (!kept)
|
|
26
|
-
digests.set(`${fieldOf(line, 'scope')}\0${digest}`, { scope: fieldOf(line, 'scope'), digest });
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
if (!digests.size)
|
|
30
|
-
return [];
|
|
31
|
-
const named = [
|
|
32
|
-
...lockStanding(storeOf(root)).filter((line) => pinScope(fieldOf(line, 'scope')) && fieldOf(line, 'value') !== 'withdraw').map((line) => ({ scope: fieldOf(line, 'scope'), value: fieldOf(line, 'value'), fields: fieldsOf(line) })),
|
|
33
|
-
...worldsIn(root).flatMap((place) => ownLockOf(root, place).filter((line) => pinScope(fieldOf(line, 'scope')) && fieldOf(line, 'value') !== 'withdraw').map((line) => ({ scope: `${place}/${fieldOf(line, 'scope')}`, value: fieldOf(line, 'value'), fields: fieldsOf(line) }))),
|
|
34
|
-
];
|
|
35
|
-
const still = named.filter((pin) => !signed.some((line) => fieldOf(line, 'value') === 'withdraw' && retracts(fieldsOf(line), pin.fields)));
|
|
36
|
-
const added = signed.filter((line) => pinScope(fieldOf(line, 'scope')) && fieldOf(line, 'value') !== 'withdraw').map((line) => ({ scope: fieldOf(line, 'scope'), value: fieldOf(line, 'value') }));
|
|
37
|
-
return [...digests.values()].flatMap((alias) => {
|
|
38
|
-
const by = [...still.filter((pin) => pin.value === alias.digest).map((pin) => pin.scope), ...added.filter((pin) => pin.value === alias.digest).map((pin) => pin.scope)];
|
|
39
|
-
return by.length ? [{ scope: alias.scope, digest: alias.digest, by }] : [];
|
|
40
|
-
});
|
|
41
|
-
}
|
|
1
|
+
var O=Object.defineProperty;var p=(t,a)=>O(t,"name",{value:a,configurable:!0});import{library11_ENVELOPE as E}from"../vendor/runtime.js";import{fieldOf as s,fieldsOf as i}from"../fold/claims.js";import{lockStanding as m}from"../fold/keys.js";import{worldsIn as g}from"../fold/places.js";import{ownLockOf as W}from"../fold/signed.js";import{storeOf as v}from"./ledger.js";const n=p((t,a)=>Object.keys(t).filter(c=>!E.has(c)&&c!=="value").every(c=>a[c]===t[c]),"retracts"),d=p(t=>t==="uses"||t.startsWith("uses/")||t.split("/").slice(1,-1).includes("uses"),"pinScope"),$=p(t=>s(t,"value")==="withdraw"&&s(t,"scope").startsWith("dep/")&&s(t,"role")!=="reads","aliasWithdraw");function j(t,a){const c=m(v(t)).filter(e=>s(e,"scope").startsWith("dep/")&&s(e,"role")!=="reads"&&s(e,"value")!=="withdraw"),f=new Map;for(const e of a.filter($)){const o=i(e);for(const r of c){if(!n(o,i(r)))continue;const l=s(r,"value");a.some(u=>s(u,"scope")===s(r,"scope")&&s(u,"value")===l)||f.set(`${s(r,"scope")}\0${l}`,{scope:s(r,"scope"),digest:l})}}if(!f.size)return[];const w=[...m(v(t)).filter(e=>d(s(e,"scope"))&&s(e,"value")!=="withdraw").map(e=>({scope:s(e,"scope"),value:s(e,"value"),fields:i(e)})),...g(t).flatMap(e=>W(t,e).filter(o=>d(s(o,"scope"))&&s(o,"value")!=="withdraw").map(o=>({scope:`${e}/${s(o,"scope")}`,value:s(o,"value"),fields:i(o)})))].filter(e=>!a.some(o=>s(o,"value")==="withdraw"&&n(i(o),e.fields))),h=a.filter(e=>d(s(e,"scope"))&&s(e,"value")!=="withdraw").map(e=>({scope:s(e,"scope"),value:s(e,"value")}));return[...f.values()].flatMap(e=>{const o=[...w.filter(r=>r.value===e.digest).map(r=>r.scope),...h.filter(r=>r.value===e.digest).map(r=>r.scope)];return o.length?[{scope:e.scope,digest:e.digest,by:o}]:[]})}p(j,"aliasPinned");export{j as aliasPinned};
|
package/dist/land/held.js
CHANGED
|
@@ -1,23 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { spanOf } from '@lapxo/topos/forms';
|
|
3
|
-
import { blobAt, ledgerLines, storeAt } from "./ledger.js";
|
|
4
|
-
const STORE = 'store';
|
|
5
|
-
const pathOf = (store, scope) => {
|
|
6
|
-
const name = scope.split('/').pop() ?? '';
|
|
7
|
-
if (scope.startsWith('cas/blobs/'))
|
|
8
|
-
return blobAt(store, name);
|
|
9
|
-
if (scope.startsWith('cas/laid/'))
|
|
10
|
-
return storeAt(store, 'cas', 'laid', name);
|
|
11
|
-
if (scope.startsWith('cas/answers/'))
|
|
12
|
-
return storeAt(store, 'cas', 'answers', name);
|
|
13
|
-
return storeAt(store, ...scope.split('/'));
|
|
14
|
-
};
|
|
15
|
-
const sizeOf = (line) => spanOf(fieldOf(line, 'value'))?.hi ?? 0;
|
|
16
|
-
function inventory(store) {
|
|
17
|
-
return ledgerLines(store, STORE).filter((line) => fieldOf(line, 'value') !== 'withdraw').map((line) => {
|
|
18
|
-
const scope = fieldOf(line, 'scope');
|
|
19
|
-
return { scope, bytes: sizeOf(line), at: pathOf(store, scope) };
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
/** Bytes the store receipts name: a byte lives only while a standing line names it, and the receipts list what is there. */
|
|
23
|
-
export const heldBytes = (_root, store, _standing) => inventory(store).reduce((sum, one) => sum + one.bytes, 0);
|
|
1
|
+
var f=Object.defineProperty;var a=(r,t)=>f(r,"name",{value:t,configurable:!0});import{fieldOf as n}from"../fold/claims.js";import{library4_spanOf as l}from"../vendor/runtime.js";import{blobAt as c,ledgerLines as p,storeAt as i}from"./ledger.js";const u="store",d=a((r,t)=>{const s=t.split("/").pop()??"";return t.startsWith("cas/blobs/")?c(r,s):t.startsWith("cas/laid/")?i(r,"cas","laid",s):t.startsWith("cas/answers/")?i(r,"cas","answers",s):i(r,...t.split("/"))},"pathOf"),m=a(r=>l(n(r,"value"))?.hi??0,"sizeOf");function b(r){return p(r,u).filter(t=>n(t,"value")!=="withdraw").map(t=>{const s=n(t,"scope");return{scope:s,bytes:m(t),at:d(r,s)}})}a(b,"inventory");const v=a((r,t,s)=>b(t).reduce((e,o)=>e+o.bytes,0),"heldBytes");export{v as heldBytes};
|
package/dist/land/inert.js
CHANGED
|
@@ -1,33 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { fieldOf } from "../fold/claims.js";
|
|
3
|
-
import { isCeiling } from "../fold/configures.js";
|
|
4
|
-
import { placedReadings } from "../fold/observed.js";
|
|
5
|
-
import { boundOf, rankOf, regionsOf } from "../fold/region.js";
|
|
6
|
-
/**
|
|
7
|
-
* The ceilings of a batch that would stand unread: no reading meets them and no reading of the instrument's own
|
|
8
|
-
* carries their measure. A batch that also signs a reader goes through whole, since what a reader reads is known only
|
|
9
|
-
* once it runs, and so does a ceiling a gate of the same act reads, whose reading lands with it or refuses it.
|
|
10
|
-
*/
|
|
11
|
-
export function inertIn(batch, input) {
|
|
12
|
-
if (input.signsReader)
|
|
13
|
-
return [];
|
|
14
|
-
const folded = foldCeilings({ standing: input.standing, ceilings: batch.filter(input.ceiling), observed: input.observed, own: input.own, epoch: input.epoch });
|
|
15
|
-
return [...folded.unread, ...folded.vacuous];
|
|
16
|
-
}
|
|
17
|
-
/** What each ceiling of a batch would bite, read off the summaries of the cone before anything lands. */
|
|
18
|
-
export function rankedIn(batch, fold) {
|
|
19
|
-
const regions = regionsOf(fold.standing, [...fold.standing.filter(isCeiling), ...batch], placedReadings(fold.observed));
|
|
20
|
-
return batch.map((line) => {
|
|
21
|
-
const bound = boundOf(regions.named, line);
|
|
22
|
-
const got = rankOf(regions, bound, fold.own);
|
|
23
|
-
const bite = got.cells ? `bites ${got.cells} cells in ${got.bars} bars, ${got.fresh} no ceiling above bites` : got.sums ? `bites ${got.sums} sums` : `bites nothing of ${got.met} met`;
|
|
24
|
-
return `RANK ${fieldOf(line, 'scope')} · ${bite} · region ${bound.region || '.'}`;
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
/** Every ceiling asked, at resolution one: what the fold reads for it, beside its bound, or unmeasured where no reading answers it. */
|
|
28
|
-
export function readingsIn(ceilings, fold) {
|
|
29
|
-
const got = foldCeilings({ standing: fold.standing, ceilings, observed: fold.observed, own: fold.own, epoch: fold.epoch });
|
|
30
|
-
const outside = new Map(got.over.map((one) => [one.ceiling, `${one.side} ${one.got}`]));
|
|
31
|
-
return ceilings.map((line) => ((scope, read) => `RANK@1 ${scope} · ${fieldOf(line, 'measure')} ${fieldOf(line, 'value')} · ${read === undefined ? 'unmeasured'
|
|
32
|
-
: `read ${read.length > 3 ? `${read.slice(0, 3).join(' · ')} +${read.length - 3}` : read.join(' · ')}`}${outside.has(scope) ? ` · ${outside.get(scope)}` : read === undefined ? '' : ' · met'}`)(fieldOf(line, 'scope'), got.readings.get(fieldOf(line, 'scope'))));
|
|
33
|
-
}
|
|
1
|
+
var d=Object.defineProperty;var c=(o,e)=>d(o,"name",{value:e,configurable:!0});import{foldCeilings as a}from"../fold/ceilings.js";import{fieldOf as g}from"../fold/claims.js";import{isCeiling as m}from"../fold/configures.js";import{placedReadings as $}from"../fold/observed.js";import{boundOf as u,rankOf as f,regionsOf as b}from"../fold/region.js";function R(o,e){if(e.signsReader)return[];const i=a({standing:e.standing,ceilings:o.filter(e.ceiling),observed:e.observed,own:e.own,epoch:e.epoch});return[...i.unread,...i.vacuous]}c(R,"inertIn");function x(o,e){const i=b(e.standing,[...e.standing.filter(m),...o],$(e.observed));return o.map(t=>{const n=u(i.named,t),s=f(i,n,e.own),r=s.cells?`bites ${s.cells} cells in ${s.bars} bars, ${s.fresh} no ceiling above bites`:s.sums?`bites ${s.sums} sums`:`bites nothing of ${s.met} met`;return`RANK ${g(t,"scope")} \xB7 ${r} \xB7 region ${n.region||"."}`})}c(x,"rankedIn");function I(o,e){const i=a({standing:e.standing,ceilings:o,observed:e.observed,own:e.own,epoch:e.epoch}),t=new Map(i.over.map(n=>[n.ceiling,`${n.side} ${n.got}`]));return o.map(n=>((s,r)=>`RANK@1 ${s} \xB7 ${g(n,"measure")} ${g(n,"value")} \xB7 ${r===void 0?"unmeasured":`read ${r.length>3?`${r.slice(0,3).join(" \xB7 ")} +${r.length-3}`:r.join(" \xB7 ")}`}${t.has(s)?` \xB7 ${t.get(s)}`:r===void 0?"":" \xB7 met"}`)(g(n,"scope"),i.readings.get(g(n,"scope"))))}c(I,"readingsIn");export{R as inertIn,x as rankedIn,I as readingsIn};
|