@lapxo/bound 0.2.4 → 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.
Files changed (250) hide show
  1. package/CITATION.cff +1 -1
  2. package/TARGET.bound +44 -39
  3. package/dist/cli/accept.js +72 -590
  4. package/dist/cli/act-result.js +3 -103
  5. package/dist/cli/args.js +3 -44
  6. package/dist/cli/custodian.js +2 -29
  7. package/dist/cli/host.js +4 -32
  8. package/dist/cli/names.js +1 -12
  9. package/dist/cli/native-descendant.js +1 -19
  10. package/dist/cli/native.js +3 -60
  11. package/dist/cli/observe.js +1 -13
  12. package/dist/cli/owner.js +3 -139
  13. package/dist/cli/pass.js +21 -321
  14. package/dist/cli/place.js +6 -282
  15. package/dist/cli/release-result.js +3 -80
  16. package/dist/cli/retained-judgment.js +1 -25
  17. package/dist/cli/standing-result.js +4 -19
  18. package/dist/cli/takes.js +10 -112
  19. package/dist/cli/verb.d.ts +1 -2
  20. package/dist/cli/verb.js +83 -684
  21. package/dist/engine/computation.js +2 -0
  22. package/dist/engine/conformance.js +4 -0
  23. package/dist/engine/encoding.js +1 -2
  24. package/dist/engine/index.d.ts +1 -13
  25. package/dist/engine/index.js +2 -11
  26. package/dist/engine/object.js +1 -38
  27. package/dist/engine/ports.js +2 -117
  28. package/dist/fold/admission-history.js +1 -17
  29. package/dist/fold/bootstrap-anchor.js +1 -28
  30. package/dist/fold/ceilings.js +1 -142
  31. package/dist/fold/claims.js +2 -132
  32. package/dist/fold/closed.js +24 -235
  33. package/dist/fold/configures.js +1 -25
  34. package/dist/fold/digests.js +10 -226
  35. package/dist/fold/evidence.js +1 -22
  36. package/dist/fold/fold-worker.js +1 -13
  37. package/dist/fold/kept.js +12 -173
  38. package/dist/fold/keys.js +3 -91
  39. package/dist/fold/laid.js +3 -90
  40. package/dist/fold/nos.js +1 -48
  41. package/dist/fold/object.js +1 -2
  42. package/dist/fold/observed.js +27 -534
  43. package/dist/fold/opened.js +1 -33
  44. package/dist/fold/own.js +3 -217
  45. package/dist/fold/paid.js +1 -92
  46. package/dist/fold/place-inputs.js +1 -70
  47. package/dist/fold/places.js +3 -100
  48. package/dist/fold/rank.js +1 -9
  49. package/dist/fold/reach.js +1 -83
  50. package/dist/fold/readers.js +6 -142
  51. package/dist/fold/receipts.js +1 -47
  52. package/dist/fold/region-declarations.js +1 -13
  53. package/dist/fold/region.js +8 -286
  54. package/dist/fold/release-policy.js +1 -101
  55. package/dist/fold/resolved.js +6 -145
  56. package/dist/fold/roles.js +2 -59
  57. package/dist/fold/second.js +4 -71
  58. package/dist/fold/shards.js +12 -100
  59. package/dist/fold/signed.js +3 -81
  60. package/dist/fold/signers.js +1 -54
  61. package/dist/fold/stranger.js +6 -24
  62. package/dist/fold/views.js +1 -66
  63. package/dist/fold/wire.js +1 -46
  64. package/dist/fold/zoom.js +3 -81
  65. package/dist/host/act-cost.js +1 -25
  66. package/dist/host/adapters/keys/ed25519.js +1 -30
  67. package/dist/host/adapters/modules/javascript.js +1 -50
  68. package/dist/host/adapters/transport/http.js +1 -28
  69. package/dist/host/admitted-place.js +1 -35
  70. package/dist/host/archive.js +1 -152
  71. package/dist/host/call-context.js +1 -14
  72. package/dist/host/capsule-process.js +2 -62
  73. package/dist/host/capsule.js +9 -171
  74. package/dist/host/cell-receipts.js +12 -128
  75. package/dist/host/commit-result.js +1 -5
  76. package/dist/host/content-needed.js +1 -8
  77. package/dist/host/content-store.js +1 -31
  78. package/dist/host/contextual-place.js +2 -72
  79. package/dist/host/digest.js +2 -15
  80. package/dist/host/hash.js +1 -9
  81. package/dist/host/host-controls.js +1 -19
  82. package/dist/host/in-process-act.js +3 -84
  83. package/dist/host/in-process-context.js +3 -91
  84. package/dist/host/in-process-root.js +6 -84
  85. package/dist/host/in-process.js +4 -55
  86. package/dist/host/index.d.ts +1 -15
  87. package/dist/host/index.js +1 -7
  88. package/dist/host/io.js +1 -11
  89. package/dist/host/lifetime.js +1 -79
  90. package/dist/host/located.js +6 -105
  91. package/dist/host/native/bounded-file.js +1 -32
  92. package/dist/host/native/command.js +1 -91
  93. package/dist/host/native/control-bridge-worker.js +2 -88
  94. package/dist/host/native/control-bridge.js +1 -110
  95. package/dist/host/native/control-selection.js +1 -32
  96. package/dist/host/native/custody.js +1 -91
  97. package/dist/host/native/deadline.js +1 -28
  98. package/dist/host/native/descendants.js +1 -528
  99. package/dist/host/native/generated-custodian.js +5 -267
  100. package/dist/host/native/generated.js +1 -379
  101. package/dist/host/native/image.js +1 -45
  102. package/dist/host/native/jobs.js +2 -148
  103. package/dist/host/native/loader.js +1 -269
  104. package/dist/host/native/materialize.js +1 -175
  105. package/dist/host/native/module-closure.js +1 -130
  106. package/dist/host/native/module-delivery.d.ts +1 -62
  107. package/dist/host/native/module-delivery.js +1 -151
  108. package/dist/host/native/module-syntax.js +1 -69
  109. package/dist/host/native/native-binary.js +1 -115
  110. package/dist/host/native/native-program.js +1 -72
  111. package/dist/host/native/node-jobs.js +3 -187
  112. package/dist/host/native/node-launch.js +1 -159
  113. package/dist/host/native/preload.js +1 -45
  114. package/dist/host/native/reading.js +1 -249
  115. package/dist/host/native/receipt-environment.js +1 -41
  116. package/dist/host/native/references.js +1 -30
  117. package/dist/host/native/root.js +1 -37
  118. package/dist/host/native/route.js +1 -216
  119. package/dist/host/native/runtime.js +1 -9
  120. package/dist/host/native-reader-context.js +1 -8
  121. package/dist/host/native-receiver.js +1 -25
  122. package/dist/host/objects.js +1 -38
  123. package/dist/host/order.js +1 -2
  124. package/dist/host/place-act-transaction.js +4 -78
  125. package/dist/host/place-clock-selection.js +5 -124
  126. package/dist/host/ports/ingress.js +2 -57
  127. package/dist/host/ports/local-act.js +5 -183
  128. package/dist/host/ports/place-act.js +1 -134
  129. package/dist/host/ports/publication.js +1 -56
  130. package/dist/host/ports/signing.js +1 -74
  131. package/dist/host/ports/store.js +1 -18
  132. package/dist/host/ports/transport.js +1 -48
  133. package/dist/host/process-lifetime.js +1 -17
  134. package/dist/host/provide.js +1 -183
  135. package/dist/host/read-only.js +1 -9
  136. package/dist/host/reading-closures.js +7 -227
  137. package/dist/host/reading-context.js +1 -53
  138. package/dist/host/reading-identity-types.js +0 -0
  139. package/dist/host/reading-identity.js +3 -0
  140. package/dist/host/reading-preparation.js +6 -0
  141. package/dist/host/reference-authenticated.d.ts +1 -40
  142. package/dist/host/reference-authenticated.js +3 -100
  143. package/dist/host/reference-contracts.js +1 -6
  144. package/dist/host/reference-export.js +6 -81
  145. package/dist/host/reference-native-api.d.ts +1 -3
  146. package/dist/host/reference-native-api.js +1 -3
  147. package/dist/host/reference-native.js +1 -74
  148. package/dist/host/reference-profile.js +1 -63
  149. package/dist/host/reference-standing.js +2 -18
  150. package/dist/host/reference.js +1 -24
  151. package/dist/host/refusals.js +2 -43
  152. package/dist/host/release.js +4 -256
  153. package/dist/host/root-clock-source.js +1 -307
  154. package/dist/host/selected-capsules.js +1 -50
  155. package/dist/host/selected-topos.js +1 -80
  156. package/dist/host/signature-era.js +1 -12
  157. package/dist/host/signing.js +2 -48
  158. package/dist/host/source-content.js +2 -111
  159. package/dist/host/standing-carrier.js +1 -18
  160. package/dist/host/standing-projection.js +1 -50
  161. package/dist/host/timing.js +1 -7
  162. package/dist/host/walk.js +20 -193
  163. package/dist/judge/late.js +1 -33
  164. package/dist/judge/take.js +2 -75
  165. package/dist/judge/widening.js +1 -25
  166. package/dist/land/act.js +8 -336
  167. package/dist/land/alias.js +1 -41
  168. package/dist/land/held.js +1 -23
  169. package/dist/land/inert.js +1 -33
  170. package/dist/land/leaving.js +1 -55
  171. package/dist/land/ledger.js +7 -188
  172. package/dist/land/owned.js +4 -66
  173. package/dist/land/sign.js +1 -53
  174. package/dist/land/standing-pin.js +1 -49
  175. package/dist/land/vouched.js +1 -112
  176. package/dist/land/withdraw.js +1 -24
  177. package/dist/observe/files.js +1 -88
  178. package/dist/observe/identity.js +1 -61
  179. package/dist/observe/match.js +1 -8
  180. package/dist/observe/regions.js +7 -306
  181. package/dist/observe/run.js +2 -41
  182. package/dist/observe/runner.js +4 -101
  183. package/dist/public-types.d.ts +1114 -0
  184. package/dist/render/capsule.js +1 -30
  185. package/dist/render/field.js +1 -40
  186. package/dist/render/names.js +1 -4
  187. package/dist/render/open.js +1 -61
  188. package/dist/render/page.js +1 -7
  189. package/dist/render/receipts.js +1 -47
  190. package/dist/render/shape.js +1 -74
  191. package/dist/render/target.js +4 -52
  192. package/dist/render/view.js +7 -197
  193. package/dist/vendor/50086958553b9376d600583f7dff354196bfeb41170fc6d1482ca7bea7c493e2.LICENSE +21 -0
  194. package/dist/vendor/b3e938d28f88a1851af303a40c749e12ebd5a686daac4f0b343b5cdd2e040419.LICENSE +21 -0
  195. package/dist/vendor/bundle.json +1 -0
  196. package/dist/vendor/library11.js +1 -0
  197. package/dist/vendor/object-provider.js +42 -0
  198. package/dist/vendor/runtime.js +38 -0
  199. package/dist/vendor/sources.json +1 -0
  200. package/dist/wasm/adapter.d.ts +1 -51
  201. package/dist/wasm/adapter.js +1 -180
  202. package/dist/wasm/node-worker.js +1 -13
  203. package/dist/wasm/object.js +1 -76
  204. package/dist/wasm/worker.js +1 -7
  205. package/docs/contracts/closure-delivery.md +1 -1
  206. package/docs/contracts/closure-delivery.publication.json +1 -1
  207. package/docs/contracts/conformance.json +142 -0
  208. package/docs/contracts/determinism.bound +9 -0
  209. package/docs/contracts/engine-object-projection.publication.json +1 -1
  210. package/docs/contracts/engine.md +21 -1
  211. package/docs/contracts/native-publication.inventory.json +2 -1
  212. package/docs/contracts/optional-wasm-adapter.publication.json +1 -1
  213. package/docs/contracts/reading-identity.md +37 -0
  214. package/docs/contracts/reading-identity.publication.json +25 -0
  215. package/docs/contracts/refusals.bound +51 -0
  216. package/docs/contracts/refusals.md +18 -3
  217. package/docs/contracts/refusals.publication.json +2 -2
  218. package/docs/contracts/views.md +8 -0
  219. package/docs/reference.md +1 -0
  220. package/package.json +23 -34
  221. package/receipts.bound +11627 -10323
  222. package/samples/reading-identity/no.json +20 -0
  223. package/samples/reading-identity/yes.json +46 -0
  224. package/vectors/native/reading-identity.vector.json +101 -0
  225. package/vectors/native/refusals.vector.json +104 -0
  226. package/vendor/syntax/LICENSE.md +7 -0
  227. package/vendor/syntax/parser.js +1 -0
  228. package/.github/workflows/release.yml +0 -67
  229. package/.github/workflows/test.yml +0 -35
  230. package/dist/engine/object.d.ts +0 -17
  231. package/dist/engine/ports.d.ts +0 -37
  232. package/dist/fold/claims.d.ts +0 -29
  233. package/dist/host/call-context.d.ts +0 -20
  234. package/dist/host/commit-result.d.ts +0 -6
  235. package/dist/host/in-process-act.d.ts +0 -82
  236. package/dist/host/in-process-context.d.ts +0 -46
  237. package/dist/host/in-process-root.d.ts +0 -117
  238. package/dist/host/in-process.d.ts +0 -41
  239. package/dist/host/native/module-closure.d.ts +0 -35
  240. package/dist/host/native-receiver.d.ts +0 -19
  241. package/dist/host/place-act-transaction.d.ts +0 -24
  242. package/dist/host/place-clock-selection.d.ts +0 -55
  243. package/dist/host/ports/local-act.d.ts +0 -44
  244. package/dist/host/ports/place-act.d.ts +0 -49
  245. package/dist/host/ports/publication.d.ts +0 -10
  246. package/dist/host/reference-export.d.ts +0 -33
  247. package/dist/host/reference-native.d.ts +0 -30
  248. package/dist/host/reference-profile.d.ts +0 -23
  249. package/dist/host/refusals.d.ts +0 -14
  250. package/dist/host/root-clock-source.d.ts +0 -86
package/dist/land/act.js CHANGED
@@ -1,336 +1,8 @@
1
- import { AsyncLocalStorage } from 'node:async_hooks';
2
- import { randomUUID } from 'node:crypto';
3
- import { basename, dirname, existsSync, join, mkdirSync, rmSync, writeFileSync, realpathSync, resolve } from "../host/io.js";
4
- import { BoundRefusal } from "../host/refusals.js";
5
- import { selfName } from "../fold/claims.js";
6
- import { placesIn } from "../fold/places.js";
7
- import { coordinatesUnder, observeText } from "../observe/files.js";
8
- const hostContext = new AsyncLocalStorage();
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 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};
@@ -1,41 +1 @@
1
- import { ENVELOPE } from '@lapxo/topos/wire';
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
- import { fieldOf } from "../fold/claims.js";
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};
@@ -1,33 +1 @@
1
- import { foldCeilings } from "../fold/ceilings.js";
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};
@@ -1,55 +1 @@
1
- import { readOnly } from "../host/read-only.js";
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};