@lapxo/bound 0.2.4 → 0.2.6
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 +1 -1
- package/README.md +20 -3
- package/TARGET.bound +85 -47
- package/dist/cli/accept.js +61 -590
- 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 +22 -321
- package/dist/cli/place.js +6 -282
- package/dist/cli/release-result.js +3 -80
- package/dist/cli/retained-judgment.js +1 -25
- package/dist/cli/standing-result.js +4 -19
- package/dist/cli/takes.js +10 -112
- package/dist/cli/verb.d.ts +1 -2
- package/dist/cli/verb.js +85 -684
- 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 -117
- 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 -132
- package/dist/fold/closed.js +24 -235
- 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 +28 -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 -35
- package/dist/host/archive.js +1 -152
- package/dist/host/call-context.js +1 -14
- package/dist/host/capsule-process.js +2 -62
- package/dist/host/capsule.js +9 -171
- package/dist/host/cell-receipts.js +12 -128
- package/dist/host/command-server.js +4 -0
- package/dist/host/commit-result.js +1 -5
- package/dist/host/content-needed.js +1 -8
- package/dist/host/content-store.js +1 -31
- package/dist/host/contextual-place.js +2 -72
- package/dist/host/digest.js +2 -15
- package/dist/host/hash.js +1 -9
- package/dist/host/host-controls.js +1 -19
- package/dist/host/in-process-act.js +3 -84
- package/dist/host/in-process-context.js +3 -91
- package/dist/host/in-process-root.js +6 -84
- package/dist/host/in-process.js +4 -55
- package/dist/host/index.d.ts +1 -15
- package/dist/host/index.js +1 -7
- 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/authority-card-view.js +5 -0
- package/dist/host/native/authority-card.js +1 -0
- 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/installed-package.d.ts +1 -0
- package/dist/host/native/installed-package.js +5 -0
- 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-inventory.js +2 -0
- 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/probes.js +1 -0
- package/dist/host/native/reading-witness-admission.js +5 -0
- 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-place-state.js +1 -0
- package/dist/host/native-reader-context.js +1 -8
- package/dist/host/native-receiver.js +1 -25
- package/dist/host/objects.js +1 -38
- package/dist/host/order.js +1 -2
- package/dist/host/persistent-host.js +1 -0
- package/dist/host/physical-lines.d.ts +1 -0
- package/dist/host/physical-lines.js +1 -0
- package/dist/host/place-act-transaction.js +4 -78
- 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 -183
- package/dist/host/ports/place-act.js +1 -134
- 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/profile-composition.d.ts +1 -0
- package/dist/host/profile-composition.js +2 -0
- 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 -307
- package/dist/host/selected-capsules.js +1 -50
- package/dist/host/selected-topos.js +1 -80
- package/dist/host/signature-era.js +1 -12
- package/dist/host/signing.js +2 -48
- package/dist/host/source-content.js +2 -111
- package/dist/host/standing-carrier.js +1 -18
- package/dist/host/standing-projection.js +1 -50
- package/dist/host/timing.js +1 -7
- package/dist/host/walk.js +20 -193
- package/dist/host/work-trace.js +1 -0
- 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 -336
- 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 +6 -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 +1 -41
- package/dist/observe/runner.js +4 -101
- package/dist/public-types.d.ts +2019 -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/receipt-projection.js +1 -0
- 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/bundle.json +1 -0
- package/dist/vendor/library14.js +1 -0
- package/dist/vendor/object-provider.js +42 -0
- package/dist/vendor/runtime.js +61 -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/authenticated-reference.publication.json +1 -1
- package/docs/contracts/authority-preflight.md +17 -0
- package/docs/contracts/authority-preflight.publication.json +25 -0
- 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/installed-package.md +21 -0
- package/docs/contracts/installed-package.publication.json +25 -0
- package/docs/contracts/materialized-leaf-sequence.md +15 -0
- package/docs/contracts/materialized-leaf-sequence.publication.json +25 -0
- package/docs/contracts/module-inventory.md +15 -0
- package/docs/contracts/module-inventory.publication.json +25 -0
- package/docs/contracts/native-host.md +29 -1
- package/docs/contracts/native-host.publication.json +4 -4
- package/docs/contracts/native-probes.md +13 -0
- package/docs/contracts/native-probes.publication.json +25 -0
- package/docs/contracts/native-publication.inventory.json +10 -1
- package/docs/contracts/native-view-batch.md +17 -0
- package/docs/contracts/native-view-batch.publication.json +25 -0
- package/docs/contracts/optional-wasm-adapter.publication.json +1 -1
- package/docs/contracts/physical-lines.md +19 -0
- package/docs/contracts/physical-lines.publication.json +25 -0
- package/docs/contracts/profile-composition.md +17 -0
- package/docs/contracts/profile-composition.publication.json +25 -0
- package/docs/contracts/profile-preparation-native-meaning.md +9 -0
- package/docs/contracts/publication.md +12 -0
- package/docs/contracts/reading-identity.md +61 -0
- package/docs/contracts/reading-identity.publication.json +25 -0
- package/docs/contracts/reading-witness-admission.md +49 -0
- package/docs/contracts/readme.publication.json +1 -1
- package/docs/contracts/reference-port.md +11 -0
- package/docs/contracts/reference-port.publication.json +1 -1
- package/docs/contracts/refusals.bound +346 -94
- package/docs/contracts/refusals.md +119 -39
- package/docs/contracts/refusals.publication.json +2 -2
- package/docs/contracts/views.md +8 -0
- package/docs/reference.md +9 -0
- package/licenses/wasm/{fast-text-encoding.txt → NOTICE.txt} +111 -0
- package/package.json +84 -34
- package/receipts.bound +12952 -10449
- package/samples/authority-preflight/no.json +6 -0
- package/samples/authority-preflight/yes.json +30 -0
- package/samples/engine-alphabet/reader.js +3 -1457
- package/samples/engine-alphabet/receipts.bound +7 -7
- package/samples/engine-interval/reader.js +3 -1457
- package/samples/engine-interval/receipts.bound +7 -7
- package/samples/installed-package/consumer.mjs +29 -0
- package/samples/installed-package/fixture.json +48 -0
- package/samples/installed-package/no.json +10 -0
- package/samples/installed-package/yes.json +52 -0
- package/samples/materialized-leaf-sequence/no.json +11 -0
- package/samples/materialized-leaf-sequence/yes.json +10 -0
- package/samples/module-inventory/yes.json +28 -0
- package/samples/native/physical-line-reader.mjs +1 -0
- package/samples/native/physical-line-reader.source.mjs +13 -0
- package/samples/native-host/no.json +6 -1
- package/samples/native-host/yes.json +18 -1
- package/samples/native-probes/inputs/inspection.json +28 -0
- package/samples/native-probes/no.json +7 -0
- package/samples/native-probes/yes.json +28 -0
- package/samples/native-view-batch/no.json +14 -0
- package/samples/native-view-batch/yes.json +10 -0
- package/samples/no/engine-order/reader.js +3 -1457
- package/samples/no/module-inventory/no.json +10 -0
- package/samples/physical-lines/no.json +5 -0
- package/samples/physical-lines/yes.json +9 -0
- package/samples/profile-composition/no.json +6 -0
- package/samples/profile-composition/yes.json +14 -0
- package/samples/reading-identity/no.json +26 -0
- package/samples/reading-identity/yes.json +69 -0
- package/vectors/native/authority-preflight.vector.json +55 -0
- package/vectors/native/installed-package.vector.json +31 -0
- package/vectors/native/materialized-leaf-sequence.vector.json +31 -0
- package/vectors/native/module-inventory.vector.json +56 -0
- package/vectors/native/native-host.vector.json +214 -0
- package/vectors/native/native-probes.vector.json +31 -0
- package/vectors/native/native-view-batch.vector.json +31 -0
- package/vectors/native/physical-lines.vector.json +105 -0
- package/vectors/native/profile-composition.vector.json +53 -0
- package/vectors/native/reading-identity.vector.json +139 -0
- package/vectors/native/refusals.vector.json +138 -0
- package/vendor/syntax/LICENSE.md +7 -0
- package/vendor/syntax/parser.js +1 -0
- package/.github/workflows/release.yml +0 -67
- package/.github/workflows/test.yml +0 -35
- package/dist/engine/object.d.ts +0 -17
- package/dist/engine/ports.d.ts +0 -37
- package/dist/fold/claims.d.ts +0 -29
- package/dist/host/call-context.d.ts +0 -20
- package/dist/host/commit-result.d.ts +0 -6
- package/dist/host/in-process-act.d.ts +0 -82
- package/dist/host/in-process-context.d.ts +0 -46
- package/dist/host/in-process-root.d.ts +0 -117
- package/dist/host/in-process.d.ts +0 -41
- package/dist/host/native/module-closure.d.ts +0 -35
- package/dist/host/native-receiver.d.ts +0 -19
- package/dist/host/place-act-transaction.d.ts +0 -24
- package/dist/host/place-clock-selection.d.ts +0 -55
- package/dist/host/ports/local-act.d.ts +0 -44
- package/dist/host/ports/place-act.d.ts +0 -49
- package/dist/host/ports/publication.d.ts +0 -10
- 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/host/root-clock-source.d.ts +0 -86
- package/licenses/wasm/jitl-quickjs-ffi-types.txt +0 -21
- package/licenses/wasm/jitl-quickjs-wasmfile-release-sync.txt +0 -47
- package/licenses/wasm/quickjs-emscripten-core.txt +0 -21
- package/licenses/wasm/topos.txt +0 -21
- /package/{licenses/wasm/bound.txt → dist/vendor/28cba430228db1c04f446c93f81b09a2705d6bf3e222d35adbe5a4cee4061884.LICENSE} +0 -0
- /package/{licenses/wasm/obligations.txt → dist/vendor/7aca161279d14bc0e054dcc281cd110aeb95be2e026b42fdf527a260e58b2aae.LICENSE} +0 -0
package/dist/land/act.js
CHANGED
|
@@ -1,336 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
export const withActHost = (host, run) => hostContext.run(host, run);
|
|
10
|
-
const actName = () => hostContext.getStore()?.name ?? selfName();
|
|
11
|
-
const report = (text) => { const host = hostContext.getStore(); if (host)
|
|
12
|
-
host.report(text);
|
|
13
|
-
else
|
|
14
|
-
process.stderr.write(text); };
|
|
15
|
-
const checkCancellation = () => { if (hostContext.getStore()?.signal?.aborted)
|
|
16
|
-
throw new BoundRefusal('host/cancelled', 'REFUSE·host/cancelled'); };
|
|
17
|
-
/** Resolve aliases before acquiring the same native lock protocol as the CLI. */
|
|
18
|
-
export function canonicalActStore(store) {
|
|
19
|
-
let at = resolve(store);
|
|
20
|
-
const tail = [];
|
|
21
|
-
while (!existsSync(at)) {
|
|
22
|
-
const parent = dirname(at);
|
|
23
|
-
if (parent === at)
|
|
24
|
-
break;
|
|
25
|
-
tail.unshift(basename(at));
|
|
26
|
-
at = parent;
|
|
27
|
-
}
|
|
28
|
-
return join(realpathSync(at), ...tail);
|
|
29
|
-
}
|
|
30
|
-
const context = new AsyncLocalStorage();
|
|
31
|
-
const held = new Map();
|
|
32
|
-
const pauseFor = (ms) => new Promise((resolve) => { setTimeout(resolve, ms); });
|
|
33
|
-
const ROOT = '_root';
|
|
34
|
-
const MINUTE = 60000;
|
|
35
|
-
const holderOf = (at) => {
|
|
36
|
-
const text = observeText(at);
|
|
37
|
-
if (text === undefined)
|
|
38
|
-
return undefined;
|
|
39
|
-
const [pid, what, since, token] = text.trim().split(' ');
|
|
40
|
-
return { pid: Number(pid), what: what ?? '', since: since ?? '', token: token ?? '' };
|
|
41
|
-
};
|
|
42
|
-
function overAMinute(at, began, holder) {
|
|
43
|
-
if (Date.now() - began < MINUTE)
|
|
44
|
-
return;
|
|
45
|
-
const who = holder === undefined ? 'a process' : `${holder.pid} · ${holder.what} since ${holder.since}`;
|
|
46
|
-
report(`RED wait · ${named(at)} is held by ${who} · a wait over a minute is a red, not a pause\n`);
|
|
47
|
-
throw new Error(`${actName()}: REFUSE·stale nothing landed · a wait over a minute is a red, not a pause`);
|
|
48
|
-
}
|
|
49
|
-
const alive = (pid) => {
|
|
50
|
-
if (!Number.isSafeInteger(pid) || pid <= 0)
|
|
51
|
-
return true;
|
|
52
|
-
try {
|
|
53
|
-
process.kill(pid, 0);
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
catch (error) {
|
|
57
|
-
return error.code !== 'ESRCH';
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
const regionAt = (store, region) => {
|
|
61
|
-
const coordinate = region.replace(/\/+$/, '');
|
|
62
|
-
if ((coordinate && coordinate.split('/').some((step) => step === '..' || step === '.' || step === '')) || coordinate.startsWith('/'))
|
|
63
|
-
throw new Error(`${actName()}: REFUSE·lock invalid region coordinate`);
|
|
64
|
-
return join(store, 'locks', coordinate ? encodeURIComponent(coordinate).replace(/^\./, '%2E').replace(/^_root$/, '%5Froot') : ROOT);
|
|
65
|
-
};
|
|
66
|
-
const coordinateOf = (file) => {
|
|
67
|
-
if (file === ROOT)
|
|
68
|
-
return '';
|
|
69
|
-
try {
|
|
70
|
-
return decodeURIComponent(file);
|
|
71
|
-
}
|
|
72
|
-
catch {
|
|
73
|
-
return file;
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
const lockFiles = (locks) => coordinatesUnder(locks, locks).filter((file) => {
|
|
77
|
-
if (file !== '.act')
|
|
78
|
-
return true;
|
|
79
|
-
// The legacy marker lists paths, while an actual region named .act has a numeric lock owner.
|
|
80
|
-
const holder = holderOf(join(locks, file));
|
|
81
|
-
return holder !== undefined && Number.isSafeInteger(holder.pid) && holder.pid > 0;
|
|
82
|
-
});
|
|
83
|
-
const overlaps = (a, b) => !a || !b || a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);
|
|
84
|
-
const treeAt = (store) => join(store, 'lock');
|
|
85
|
-
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)}`);
|
|
86
|
-
const owns = (at) => {
|
|
87
|
-
for (let frame = context.getStore(); frame !== undefined; frame = frame.parent) {
|
|
88
|
-
const token = frame.locks.get(at);
|
|
89
|
-
if (token !== undefined && held.get(at) === token)
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
return false;
|
|
93
|
-
};
|
|
94
|
-
const ownsRegion = (store) => [...held.keys()].some((at) => at.startsWith(`${join(store, 'locks')}/`) && owns(at));
|
|
95
|
-
const ownsAuthority = (store) => [...held.keys()].some((at) => dirname(at) === join(store, 'locks') && basename(at).startsWith('@authority-') && owns(at));
|
|
96
|
-
const projectionAt = (store) => join(store, 'locks', '@projection');
|
|
97
|
-
/** Reentry belongs to an awaited act's context. Another process or async act has no inherited authority. */
|
|
98
|
-
async function hold(at, what) {
|
|
99
|
-
if (owns(at))
|
|
100
|
-
return;
|
|
101
|
-
const frame = context.getStore();
|
|
102
|
-
if (frame === undefined)
|
|
103
|
-
throw new Error(`${actName()}: REFUSE·lock no act owns this request`);
|
|
104
|
-
const began = Date.now();
|
|
105
|
-
const token = randomUUID();
|
|
106
|
-
let told = false;
|
|
107
|
-
mkdirSync(dirname(at), { recursive: true });
|
|
108
|
-
for (;;) {
|
|
109
|
-
checkCancellation();
|
|
110
|
-
try {
|
|
111
|
-
writeFileSync(at, `${process.pid} ${what.replace(/\s+/g, '_')} ${new Date().toISOString()} ${token}\n`, { flag: 'wx' });
|
|
112
|
-
break;
|
|
113
|
-
}
|
|
114
|
-
catch (error) {
|
|
115
|
-
const code = error.code;
|
|
116
|
-
if (code === 'ENOENT')
|
|
117
|
-
mkdirSync(dirname(at), { recursive: true });
|
|
118
|
-
else if (code !== 'EEXIST')
|
|
119
|
-
throw error;
|
|
120
|
-
}
|
|
121
|
-
const holder = holderOf(at);
|
|
122
|
-
// Removing a dead owner's lock here would race with another process's recovery. Recovery is a separate host act.
|
|
123
|
-
if (holder !== undefined && !alive(holder.pid)) {
|
|
124
|
-
throw new Error(`${actName()}: REFUSE·stale ${named(at)} belongs to exited process ${holder.pid}; host recovery required`);
|
|
125
|
-
}
|
|
126
|
-
overAMinute(at, began, holder);
|
|
127
|
-
if (!told && holder !== undefined) {
|
|
128
|
-
report(`WAIT ${named(at)} is held by ${holder.pid} · ${holder.what} since ${holder.since}\n`);
|
|
129
|
-
told = true;
|
|
130
|
-
}
|
|
131
|
-
await pauseFor(250);
|
|
132
|
-
}
|
|
133
|
-
if (told)
|
|
134
|
-
report(`HELD ${named(at)} after ${Date.now() - began} ms waiting\n`);
|
|
135
|
-
held.set(at, token);
|
|
136
|
-
frame.locks.set(at, token);
|
|
137
|
-
if (!process.listeners('exit').includes(releaseAll))
|
|
138
|
-
process.once('exit', releaseAll);
|
|
139
|
-
}
|
|
140
|
-
function release(at, token) {
|
|
141
|
-
if (held.get(at) !== token)
|
|
142
|
-
return;
|
|
143
|
-
held.delete(at);
|
|
144
|
-
const holder = holderOf(at);
|
|
145
|
-
if (holder?.pid === process.pid && holder.token === token && existsSync(at))
|
|
146
|
-
rmSync(at, { force: true });
|
|
147
|
-
}
|
|
148
|
-
function releaseAll() {
|
|
149
|
-
for (const [at, token] of [...held])
|
|
150
|
-
release(at, token);
|
|
151
|
-
}
|
|
152
|
-
/** Only the CLI installs process termination behavior. Importing a host does not. */
|
|
153
|
-
export function installActSignalHandler() {
|
|
154
|
-
process.once('SIGTERM', () => { report(`${actName()}: REFUSE·crash signal\n`); releaseAll(); process.exit(1); });
|
|
155
|
-
}
|
|
156
|
-
async function framed(takes, act) {
|
|
157
|
-
const frame = { parent: context.getStore(), locks: new Map() };
|
|
158
|
-
return context.run(frame, async () => {
|
|
159
|
-
try {
|
|
160
|
-
checkCancellation();
|
|
161
|
-
await takes();
|
|
162
|
-
checkCancellation();
|
|
163
|
-
return await act();
|
|
164
|
-
}
|
|
165
|
-
finally {
|
|
166
|
-
for (const [at, token] of [...frame.locks].reverse())
|
|
167
|
-
release(at, token);
|
|
168
|
-
frame.locks.clear();
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
function guardedRegions(store, regions, what, act, rootAuthority) {
|
|
173
|
-
return framed(async () => {
|
|
174
|
-
const tree = treeAt(store);
|
|
175
|
-
const asked = [...new Set((regions.length ? regions : ['']).map((one) => one.replace(/\/+$/, '')))];
|
|
176
|
-
if (rootAuthority && (asked.includes('') || (ownsRegion(store) && !owns(tree) && !ownsAuthority(store))))
|
|
177
|
-
throw new Error(`${actName()}: REFUSE·lock authority dependencies and child regions must be declared together`);
|
|
178
|
-
if (owns(tree) || asked.every((region) => owns(regionAt(store, region)))) {
|
|
179
|
-
for (const region of asked)
|
|
180
|
-
await hold(regionAt(store, region), what);
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
if (ownsRegion(store))
|
|
184
|
-
throw new Error(`${actName()}: REFUSE·lock declare every region before entering an act`);
|
|
185
|
-
const already = owns(tree);
|
|
186
|
-
// The tree lock is the acquisition gate. A whole-tree act cannot enter between checking it and taking regions.
|
|
187
|
-
await hold(tree, what);
|
|
188
|
-
try {
|
|
189
|
-
const locks = join(store, 'locks');
|
|
190
|
-
for (;;) {
|
|
191
|
-
const conflict = lockFiles(locks).find((file) => !owns(join(locks, file))
|
|
192
|
-
&& (file.startsWith('@authority-') || file === '@projection' ? asked.includes('')
|
|
193
|
-
: asked.some((region) => overlaps(region, file) || overlaps(region, coordinateOf(file)))));
|
|
194
|
-
if (conflict === undefined)
|
|
195
|
-
break;
|
|
196
|
-
const at = join(locks, conflict);
|
|
197
|
-
const began = Date.now();
|
|
198
|
-
let told = false;
|
|
199
|
-
for (let holder = holderOf(at); holder !== undefined; holder = holderOf(at)) {
|
|
200
|
-
checkCancellation();
|
|
201
|
-
if (!alive(holder.pid))
|
|
202
|
-
throw new Error(`${actName()}: REFUSE·stale ${named(at)} belongs to exited process ${holder.pid}; host recovery required`);
|
|
203
|
-
overAMinute(at, began, holder);
|
|
204
|
-
if (!told) {
|
|
205
|
-
report(`WAIT ${named(at)} is held by ${holder.pid} · ${holder.what} since ${holder.since}\n`);
|
|
206
|
-
told = true;
|
|
207
|
-
}
|
|
208
|
-
await pauseFor(250);
|
|
209
|
-
}
|
|
210
|
-
if (told)
|
|
211
|
-
report(`HELD ${named(at)} after ${Date.now() - began} ms waiting\n`);
|
|
212
|
-
}
|
|
213
|
-
// Registered under the same acquisition gate as every legacy writer.
|
|
214
|
-
// Root writes overlap all locks; siblings keep distinct region locks.
|
|
215
|
-
// '@' is encoded for real region coordinates, so this is host bookkeeping.
|
|
216
|
-
if (rootAuthority)
|
|
217
|
-
await hold(join(store, 'locks', `@authority-${randomUUID()}`), what);
|
|
218
|
-
for (const region of asked.filter(Boolean).sort())
|
|
219
|
-
await hold(regionAt(store, region), what);
|
|
220
|
-
if (asked.includes(''))
|
|
221
|
-
await hold(regionAt(store, ''), what);
|
|
222
|
-
}
|
|
223
|
-
finally {
|
|
224
|
-
if (!already) {
|
|
225
|
-
const frame = context.getStore();
|
|
226
|
-
const token = frame.locks.get(tree);
|
|
227
|
-
if (token !== undefined) {
|
|
228
|
-
release(tree, token);
|
|
229
|
-
frame.locks.delete(tree);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}, act);
|
|
234
|
-
}
|
|
235
|
-
export function underTheRegions(store, regions, what, act) {
|
|
236
|
-
store = canonicalActStore(store);
|
|
237
|
-
return guardedRegions(store, regions, what, act, false);
|
|
238
|
-
}
|
|
239
|
-
/** Protect the root authority/policy read through child publication. This is
|
|
240
|
-
* exclusion only: callers must authenticate contexts and compare prepared heads
|
|
241
|
-
* while held. It creates no grant, clock advance, lease or automatic recovery. */
|
|
242
|
-
export function underAuthorityRegions(store, regions, what, act) {
|
|
243
|
-
store = canonicalActStore(store);
|
|
244
|
-
return guardedRegions(store, regions, what, act, true);
|
|
245
|
-
}
|
|
246
|
-
/** Protect an authority snapshot without taking a child region. The acquisition
|
|
247
|
-
* gate and temporary root marker exclude a root mutation while registering the
|
|
248
|
-
* shared read; existing child acts continue independently. This is exclusion,
|
|
249
|
-
* never authorization or a clock advance. */
|
|
250
|
-
export function underRootAuthority(store, what, act) {
|
|
251
|
-
store = canonicalActStore(store);
|
|
252
|
-
return framed(async () => {
|
|
253
|
-
const tree = treeAt(store), root = regionAt(store, '');
|
|
254
|
-
if (owns(tree) || owns(root) || ownsAuthority(store))
|
|
255
|
-
return;
|
|
256
|
-
if (ownsRegion(store))
|
|
257
|
-
throw new Error(`${actName()}: REFUSE·lock authority dependencies must be declared before entering a region act`);
|
|
258
|
-
await hold(tree, what);
|
|
259
|
-
try {
|
|
260
|
-
await hold(root, what);
|
|
261
|
-
await hold(join(store, 'locks', `@authority-${randomUUID()}`), what);
|
|
262
|
-
}
|
|
263
|
-
finally {
|
|
264
|
-
const frame = context.getStore();
|
|
265
|
-
for (const at of [root, tree]) {
|
|
266
|
-
const token = frame.locks.get(at);
|
|
267
|
-
if (token !== undefined) {
|
|
268
|
-
release(at, token);
|
|
269
|
-
frame.locks.delete(at);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}, act);
|
|
274
|
-
}
|
|
275
|
-
/** The fixed host may hand its child evidence of an actual held exclusion.
|
|
276
|
-
* It is an operational envelope, not a grant, signer or receipt identity. */
|
|
277
|
-
export function rootAuthorityProtection(store) {
|
|
278
|
-
store = canonicalActStore(store);
|
|
279
|
-
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-'));
|
|
280
|
-
const lock = locks.find(owns);
|
|
281
|
-
if (lock === undefined)
|
|
282
|
-
throw Error(`${actName()}: REFUSE·lock root authority is not protected`);
|
|
283
|
-
const holder = holderOf(lock);
|
|
284
|
-
if (holder?.pid !== process.pid || holder.token !== held.get(lock))
|
|
285
|
-
throw Error(`${actName()}: REFUSE·lock authority protection changed`);
|
|
286
|
-
return Object.freeze({ store, lock, pid: holder.pid, token: holder.token });
|
|
287
|
-
}
|
|
288
|
-
/** expectedStore and expectedParent come from the fixed host's inheritance
|
|
289
|
-
* channel, never from world data. Matching a live lock proves exclusion only;
|
|
290
|
-
* signature, coverage and current context still require verification. */
|
|
291
|
-
export function assertRootAuthorityProtection(proof, expectedStore, expectedParent) {
|
|
292
|
-
expectedStore = canonicalActStore(expectedStore);
|
|
293
|
-
if (!proof || proof.store !== expectedStore || !Number.isSafeInteger(expectedParent) || expectedParent <= 0 || proof.pid !== expectedParent
|
|
294
|
-
|| typeof proof.lock !== 'string' || typeof proof.token !== 'string' || !proof.token
|
|
295
|
-
|| !(proof.lock === treeAt(expectedStore) || proof.lock === regionAt(expectedStore, '')
|
|
296
|
-
|| dirname(proof.lock) === join(expectedStore, 'locks') && basename(proof.lock).startsWith('@authority-'))) {
|
|
297
|
-
throw Error(`${actName()}: REFUSE·lock invalid inherited authority protection`);
|
|
298
|
-
}
|
|
299
|
-
const holder = holderOf(proof.lock);
|
|
300
|
-
if (!alive(expectedParent) || holder?.pid !== proof.pid || holder.token !== proof.token)
|
|
301
|
-
throw Error(`${actName()}: REFUSE·lock inherited authority protection ended`);
|
|
302
|
-
}
|
|
303
|
-
/** A child can publish independently, but the joined root projection and its
|
|
304
|
-
* derived ledger appends have one writer. Authority protection already excludes
|
|
305
|
-
* root mutations, so this lock needs no acquisition-gate upgrade. */
|
|
306
|
-
export function underRootProjection(store, what, act) {
|
|
307
|
-
store = canonicalActStore(store);
|
|
308
|
-
return framed(async () => {
|
|
309
|
-
if (owns(treeAt(store)) || owns(regionAt(store, '')))
|
|
310
|
-
return;
|
|
311
|
-
if (!ownsAuthority(store))
|
|
312
|
-
throw new Error(`${actName()}: REFUSE·lock root projection requires authority protection`);
|
|
313
|
-
await hold(projectionAt(store), what);
|
|
314
|
-
}, act);
|
|
315
|
-
}
|
|
316
|
-
export const holdRoot = async (store, what) => {
|
|
317
|
-
store = canonicalActStore(store);
|
|
318
|
-
if (!owns(treeAt(store)))
|
|
319
|
-
await hold(regionAt(store, ''), what);
|
|
320
|
-
};
|
|
321
|
-
export function underTheLock(store, what, act) {
|
|
322
|
-
store = canonicalActStore(store);
|
|
323
|
-
return framed(async () => {
|
|
324
|
-
if (!owns(treeAt(store)) && ownsRegion(store))
|
|
325
|
-
throw new Error(`${actName()}: REFUSE·lock a region act cannot upgrade to the tree; declare the tree before entering`);
|
|
326
|
-
await hold(treeAt(store), what);
|
|
327
|
-
const locks = join(store, 'locks');
|
|
328
|
-
const active = lockFiles(locks);
|
|
329
|
-
for (const file of [...active].sort())
|
|
330
|
-
await hold(join(locks, file), what);
|
|
331
|
-
for (const region of [...placesIn(dirname(store))].sort())
|
|
332
|
-
await hold(regionAt(store, region), what);
|
|
333
|
-
await hold(regionAt(store, ''), what);
|
|
334
|
-
}, act);
|
|
335
|
-
}
|
|
336
|
-
export const holds = (store, region) => { store = canonicalActStore(store); return [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 w,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,pe=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"),we=r(()=>v.getStore()?.signal,"currentActSignal"),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(w(t)),t=o}return a(V(t),...n)}r(E,"canonicalActStore");const F=new q,g=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"),p=r(e=>a(e,"lock"),"treeAt"),R=r(e=>w(e)==="lock"?"the store":w(e).startsWith("@authority-")?"root authority":w(e)==="@projection"?"root projection":`region ${w(e)===j?".":w(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&&g.get(e)===n)return!0}return!1},"owns"),x=r(e=>[...g.keys()].some(t=>t.startsWith(`${a(e,"locks")}/`)&&l(t)),"ownsRegion"),O=r(e=>[...g.keys()].some(t=>$(t)===a(e,"locks")&&w(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(y){const u=y.code;if(u==="ENOENT")_($(e),{recursive:!0});else if(u!=="EEXIST")throw y}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
|
+
`),g.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(g.get(e)!==t)return;g.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[...g])I(e,t)}r(C,"releaseAll");function Ee(){process.once("SIGTERM",()=>{b(`${d()}: REFUSE\xB7crash signal
|
|
6
|
+
`),C(),process.exit(1)})}r(Ee,"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=p(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 y=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(!y){const u=F.getStore(),m=u.locks.get(c);m!==void 0&&(I(c,m),u.locks.delete(c))}}},o)}r(X,"guardedRegions");function ge(e,t,n,o){return e=E(e),X(e,t,n,o,!1)}r(ge,"underTheRegions");function ye(e,t,n,o){return e=E(e),X(e,t,n,o,!0)}r(ye,"underAuthorityRegions");function me(e,t,n){return e=E(e),T(async()=>{const o=p(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 y=c.locks.get(s);y!==void 0&&(I(s,y),c.locks.delete(s))}}}},n)}r(me,"underRootAuthority");function $e(e){e=E(e);const n=[p(e),k(e,""),...g.keys()].filter(i=>i===p(e)||i===k(e,"")||$(i)===a(e,"locks")&&w(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!==g.get(n))throw Error(`${d()}: REFUSE\xB7lock authority protection changed`);return Object.freeze({store:e,lock:n,pid:o.pid,token:o.token})}r($e,"rootAuthorityProtection");function Se(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===p(t)||e.lock===k(t,"")||$(e.lock)===a(t,"locks")&&w(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(Se,"assertRootAuthorityProtection");function Re(e,t,n){return e=E(e),T(async()=>{if(!(l(p(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(Re,"underRootProjection");const Ue=r(async(e,t)=>{e=E(e),l(p(e))||await h(k(e,""),t)},"holdRoot");function be(e,t,n){return e=E(e),T(async()=>{if(!l(p(e))&&x(e))throw new Error(`${d()}: REFUSE\xB7lock a region act cannot upgrade to the tree; declare the tree before entering`);await h(p(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(be,"underTheLock");const Fe=r((e,t)=>(e=E(e),[p(e),k(e,t)].some(l)),"holds");export{Se as assertRootAuthorityProtection,E as canonicalActStore,we as currentActSignal,Ue as holdRoot,Fe as holds,Ee as installActSignalHandler,$e as rootAuthorityProtection,ye as underAuthorityRegions,me as underRootAuthority,Re as underRootProjection,be as underTheLock,ge as underTheRegions,pe 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{library14_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{library7_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};
|
package/dist/land/leaving.js
CHANGED
|
@@ -1,55 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { meets } from "../fold/closed.js";
|
|
3
|
-
import { fieldOf } from "../fold/claims.js";
|
|
4
|
-
import { sourced } from "./vouched.js";
|
|
5
|
-
import { observedClaims } from "../fold/observed.js";
|
|
6
|
-
/**
|
|
7
|
-
* A file goes from the tree through a line, never through a hand: its path withdrawn in the family the lock sources files
|
|
8
|
-
* by is the only way a file goes, and the fold refuses it while a block still reads the file — what a run depends on is judged by the run's
|
|
9
|
-
* own memo, which names every file each block read, and not by a search for the file's name in a test. A search misses
|
|
10
|
-
* a name built in a loop; the memo does not. A test file goes with its own blocks, and is refused while one of them
|
|
11
|
-
* is the only run of a vector or a sample, which it names.
|
|
12
|
-
*/
|
|
13
|
-
export function coordinatesWithdrawn(root, store, signed, standing) {
|
|
14
|
-
const family = sourced(standing);
|
|
15
|
-
const asked = signed.filter((line) => fieldOf(line, 'scope').startsWith(`${family}/`) && fieldOf(line, 'value') === 'withdraw')
|
|
16
|
-
.map((line) => fieldOf(line, 'scope').slice(family.length + 1));
|
|
17
|
-
if (!asked.length)
|
|
18
|
-
return { taken: [], refused: [] };
|
|
19
|
-
if (readOnly() && !meets(root, store, ''))
|
|
20
|
-
throw Error('REFUSE·withdraw current native receipts are required to judge file removal; fold the declared inputs first');
|
|
21
|
-
/** A run rewrites every block of a test file under one observation, so a block whose title moved still holds a row
|
|
22
|
-
* from an older one: what reads a file now is what the latest run of each test file wrote, and nothing older. */
|
|
23
|
-
const memo = observedClaims(root, store, { wait: false }).filter((line) => fieldOf(line, 'measure') === 'memo');
|
|
24
|
-
const fileOf = (scope) => scope.split('/').slice(0, 2).join('/');
|
|
25
|
-
const last = new Map();
|
|
26
|
-
for (const line of memo)
|
|
27
|
-
last.set(fileOf(fieldOf(line, 'scope')), fieldOf(line, 'at'));
|
|
28
|
-
const latest = new Map();
|
|
29
|
-
for (const line of memo) {
|
|
30
|
-
const scope = fieldOf(line, 'scope');
|
|
31
|
-
if (fieldOf(line, 'at') === last.get(fileOf(scope)))
|
|
32
|
-
latest.set(scope, fieldOf(line, 'value'));
|
|
33
|
-
}
|
|
34
|
-
const refused = [];
|
|
35
|
-
const taken = [];
|
|
36
|
-
const ownOf = (inside) => (/^test\/[^/]+\.test\.ts$/.test(inside) ? `vector-memo/${inside.slice('test/'.length)}/` : undefined);
|
|
37
|
-
const leaving = asked.map((path) => ownOf(path.slice(path.indexOf('/') + 1))).filter((own) => own !== undefined);
|
|
38
|
-
const runs = (value) => value.split('|').filter((token) => token.startsWith('read:') && !token.includes('#')).map((token) => token.slice('read:'.length));
|
|
39
|
-
for (const path of asked) {
|
|
40
|
-
const inside = path.slice(path.indexOf('/') + 1);
|
|
41
|
-
const own = ownOf(inside);
|
|
42
|
-
const reads = (value) => value.split('|').some((token) => token.startsWith(`in:${inside}:`) && /^[0-9a-f]{12}$/.test(token.slice(`in:${inside}:`.length)));
|
|
43
|
-
const by = [...latest].find(([scope, value]) => (own === undefined || !scope.startsWith(own)) && reads(value))?.[0];
|
|
44
|
-
const elsewhere = new Set([...latest].filter(([scope]) => !leaving.some((one) => scope.startsWith(one))).flatMap(([, value]) => runs(value)));
|
|
45
|
-
const only = own === undefined ? undefined : [...latest].filter(([scope]) => scope.startsWith(own))
|
|
46
|
-
.flatMap(([scope, value]) => runs(value).filter((name) => !elsewhere.has(name)).map((name) => `${scope}, the only run of ${name}`))[0];
|
|
47
|
-
if (by !== undefined)
|
|
48
|
-
refused.push({ path, by });
|
|
49
|
-
else if (only !== undefined)
|
|
50
|
-
refused.push({ path, by: only });
|
|
51
|
-
else
|
|
52
|
-
taken.push(path);
|
|
53
|
-
}
|
|
54
|
-
return { taken, refused };
|
|
55
|
-
}
|
|
1
|
+
var j=Object.defineProperty;var o=(r,f)=>j(r,"name",{value:f,configurable:!0});import{readOnly as S}from"../host/read-only.js";import{meets as k}from"../fold/closed.js";import{fieldOf as n}from"../fold/claims.js";import{sourced as q}from"./vouched.js";import{observedClaims as C}from"../fold/observed.js";function D(r,f,O,M){const p=q(M),c=O.filter(e=>n(e,"scope").startsWith(`${p}/`)&&n(e,"value")==="withdraw").map(e=>n(e,"scope").slice(p.length+1));if(!c.length)return{taken:[],refused:[]};if(S()&&!k(r,f,""))throw Error("REFUSE\xB7withdraw current native receipts are required to judge file removal; fold the declared inputs first");const u=C(r,f,{wait:!1}).filter(e=>n(e,"measure")==="memo"),h=o(e=>e.split("/").slice(0,2).join("/"),"fileOf"),w=new Map;for(const e of u)w.set(h(n(e,"scope")),n(e,"at"));const l=new Map;for(const e of u){const t=n(e,"scope");n(e,"at")===w.get(h(t))&&l.set(t,n(e,"value"))}const d=[],g=[],$=o(e=>/^test\/[^/]+\.test\.ts$/.test(e)?`vector-memo/${e.slice(5)}/`:void 0,"ownOf"),b=c.map(e=>$(e.slice(e.indexOf("/")+1))).filter(e=>e!==void 0),v=o(e=>e.split("|").filter(t=>t.startsWith("read:")&&!t.includes("#")).map(t=>t.slice(5)),"runs");for(const e of c){const t=e.slice(e.indexOf("/")+1),a=$(t),x=o(s=>s.split("|").some(i=>i.startsWith(`in:${t}:`)&&/^[0-9a-f]{12}$/.test(i.slice(`in:${t}:`.length))),"reads"),W=[...l].find(([s,i])=>(a===void 0||!s.startsWith(a))&&x(i))?.[0],E=new Set([...l].filter(([s])=>!b.some(i=>s.startsWith(i))).flatMap(([,s])=>v(s))),y=a===void 0?void 0:[...l].filter(([s])=>s.startsWith(a)).flatMap(([s,i])=>v(i).filter(m=>!E.has(m)).map(m=>`${s}, the only run of ${m}`))[0];W!==void 0?d.push({path:e,by:W}):y!==void 0?d.push({path:e,by:y}):g.push(e)}return{taken:g,refused:d}}o(D,"coordinatesWithdrawn");export{D as coordinatesWithdrawn};
|