arcane-os 0.1.0-dev.5 → 0.1.1

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 (44) hide show
  1. package/NOTICE +10 -0
  2. package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +162 -0
  3. package/browser-runtime/ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json +69 -0
  4. package/browser-runtime/ai/browser-wasm-llm-provider.mjs +1151 -0
  5. package/browser-runtime/ai/browser-wasm.mjs +44 -0
  6. package/browser-runtime/ai/browser-wllama-runtime.mjs +390 -0
  7. package/browser-runtime/ai/internal/sha256.mjs +166 -0
  8. package/browser-runtime/ai/model-controller.mjs +581 -0
  9. package/browser-runtime/ai/wllama/LICENCE +21 -0
  10. package/browser-runtime/ai/wllama/index.mjs +3494 -0
  11. package/browser-runtime/ai/wllama/llama.cpp-LICENSE +21 -0
  12. package/browser-runtime/ai/wllama/wllama.wasm +0 -0
  13. package/browser-runtime/dependencies/event-pubsub/index.js +141 -0
  14. package/browser-runtime/dependencies/event-pubsub/licence +21 -0
  15. package/browser-runtime/dependencies/event-pubsub/package.json +59 -0
  16. package/browser-runtime/dependencies/strong-type/index.js +1151 -0
  17. package/browser-runtime/dependencies/strong-type/licence +21 -0
  18. package/browser-runtime/dependencies/strong-type/package.json +61 -0
  19. package/browser-runtime/dom-event-instrumentation.mjs +594 -0
  20. package/browser-runtime/event-manager.mjs +1342 -0
  21. package/docs/publishing.md +65 -67
  22. package/docs/reference/README.md +2 -1
  23. package/docs/reference/cli.md +86 -3
  24. package/docs/reference/event-manager.md +20 -11
  25. package/docs/reference/inventory/package-api.json +1 -1
  26. package/docs/reference/protocols.md +112 -14
  27. package/docs/reference/sdk-api.md +40 -11
  28. package/docs/work-amplification.md +4 -3
  29. package/package.json +15 -8
  30. package/runtime/ARCANE_RUNTIME_RELEASE.json +1 -1
  31. package/schemas/arcane-lock.schema.json +97 -1
  32. package/src/cli/main.mjs +5 -0
  33. package/src/dev-server.mjs +78 -34
  34. package/src/doctor.mjs +77 -3
  35. package/src/import-map.mjs +2352 -0
  36. package/src/packager/core.mjs +607 -29
  37. package/src/scaffold.mjs +122 -5
  38. package/src/sdk-browser-runtime.mjs +702 -0
  39. package/src/targets/index.mjs +31 -4
  40. package/src/templates/workspace-template.mjs +141 -23
  41. package/src/toolchain.mjs +288 -55
  42. package/src/workspace-operation-lock.mjs +716 -0
  43. package/src/workspace-runtime.mjs +841 -0
  44. package/src/workspace.mjs +292 -37
@@ -0,0 +1,716 @@
1
+ import {randomUUID} from 'node:crypto';
2
+ import {constants as FS_CONSTANTS} from 'node:fs';
3
+ import {lstat,mkdir,open,realpath,rename,rm} from 'node:fs/promises';
4
+ import path from 'node:path';
5
+
6
+ const LOCK_DIRECTORY='.arcane';
7
+ const LOCK_NAME='workspace-operation.lock.json';
8
+ const LOCK_TTL_MILLISECONDS=6*60*60*1000;
9
+ const MAX_LOCK_BYTES=64*1024;
10
+ const OPEN_EXCLUSIVE=FS_CONSTANTS.O_CREAT|FS_CONSTANTS.O_EXCL|FS_CONSTANTS.O_RDWR
11
+ |(FS_CONSTANTS.O_NOFOLLOW??0);
12
+ const OPEN_READ=FS_CONSTANTS.O_RDONLY|(FS_CONSTANTS.O_NOFOLLOW??0);
13
+ const RELEASE_PROCEDURE=
14
+ 'The owning Arcane process removes this identity-checked lock after the operation settles.';
15
+ const STALE_RECOVERY=
16
+ 'Only after expiresAt, confirm the recorded owner process is absent, preserve workspace '
17
+ +'changes, and remove this exact identity-checked lock. A live owner is never displaced.';
18
+ const SECURITY_BOUNDARY=
19
+ 'This lock coordinates cooperative Arcane SDK mutators. Privileged or non-cooperating '
20
+ +'filesystem mutation is outside the portable JavaScript security boundary.';
21
+ const DOCUMENT_KEYS=Object.freeze([
22
+ 'acquiredAt',
23
+ 'expiresAt',
24
+ 'kind',
25
+ 'nonce',
26
+ 'operation',
27
+ 'owner',
28
+ 'releaseProcedure',
29
+ 'schemaVersion',
30
+ 'scope',
31
+ 'securityBoundary',
32
+ 'staleRecovery',
33
+ 'ttlMilliseconds'
34
+ ].sort());
35
+ const OWNER_KEYS=Object.freeze(['pid']);
36
+ const activeRoots=new Map();
37
+ const leaseStates=new WeakMap();
38
+
39
+ function fail(message,code='ARCANE_WORKSPACE_BUSY'){
40
+ const error=new Error(message);
41
+ error.code=code;
42
+ throw error;
43
+ }
44
+
45
+ function workspaceBusy(message){
46
+ const error=new Error(message);
47
+ error.code='ARCANE_WORKSPACE_BUSY';
48
+ return error;
49
+ }
50
+
51
+ function trackedLeaseState(fields){
52
+ let resolveSettled;
53
+ const settled=new Promise(resolve=>{resolveSettled=resolve;});
54
+ return {
55
+ ...fields,
56
+ releasePromise:null,
57
+ settled,
58
+ settledComplete:false,
59
+ resolveSettled
60
+ };
61
+ }
62
+
63
+ function settleLeaseState(state){
64
+ if(state.settledComplete)return;
65
+ state.settledComplete=true;
66
+ state.resolveSettled();
67
+ }
68
+
69
+ function throwIfAborted(signal){
70
+ if(!signal?.aborted)return;
71
+ const error=signal.reason instanceof Error?signal.reason:new Error('Operation cancelled.');
72
+ error.code=error.code||'ARCANE_CANCELLED';
73
+ throw error;
74
+ }
75
+
76
+ function sameLocation(left,right){
77
+ return left.dev===right.dev&&left.ino===right.ino;
78
+ }
79
+
80
+ function sameFileState(left,right){
81
+ return sameLocation(left,right)&&left.size===right.size
82
+ &&left.mtimeNs===right.mtimeNs&&left.ctimeNs===right.ctimeNs
83
+ &&left.nlink===right.nlink&&left.mode===right.mode;
84
+ }
85
+
86
+ function samePath(left,right){
87
+ const normalize=value=>{
88
+ const resolved=path.resolve(value);
89
+ return process.platform==='win32'?resolved.toLocaleLowerCase('en-US'):resolved;
90
+ };
91
+ return normalize(left)===normalize(right);
92
+ }
93
+
94
+ function exactKeys(value,expected){
95
+ return value!==null&&typeof value==='object'&&!Array.isArray(value)
96
+ &&JSON.stringify(Object.keys(value).sort())===JSON.stringify(expected);
97
+ }
98
+
99
+ async function captureRealDirectoryChain(directory,label){
100
+ const resolved=path.resolve(directory);
101
+ let requestedIdentity;
102
+ try{requestedIdentity=await lstat(resolved,{bigint:true});}
103
+ catch(error){
104
+ if(error?.code==='ENOENT'){
105
+ fail(`${label} does not exist.`, 'ARCANE_POLICY_DENIED');
106
+ }
107
+ throw error;
108
+ }
109
+ if(requestedIdentity.isSymbolicLink()||!requestedIdentity.isDirectory()){
110
+ fail(`${label} must be a physical directory, not a symbolic link or junction.`,
111
+ 'ARCANE_POLICY_DENIED');
112
+ }
113
+ const canonical=await realpath(resolved);
114
+ const root=path.parse(canonical).root;
115
+ const relative=path.relative(root,canonical);
116
+ const segments=relative===''?[]:relative.split(path.sep).filter(Boolean);
117
+ const records=[];
118
+ let current=root;
119
+ for(const segment of [null,...segments]){
120
+ if(segment!==null)current=path.join(current,segment);
121
+ let info;
122
+ try{info=await lstat(current,{bigint:true});}
123
+ catch(error){
124
+ if(error?.code==='ENOENT'){
125
+ fail(`${label} does not exist.`, 'ARCANE_POLICY_DENIED');
126
+ }
127
+ throw error;
128
+ }
129
+ if(info.isSymbolicLink()||!info.isDirectory()){
130
+ fail(`${label} must not contain a symbolic link, junction, or non-directory ancestor.`,
131
+ 'ARCANE_POLICY_DENIED');
132
+ }
133
+ records.push(Object.freeze({path:current,identity:info}));
134
+ }
135
+ const identity=records.at(-1).identity;
136
+ if(!sameLocation(requestedIdentity,identity)){
137
+ fail(`${label} must resolve to its captured directory identity.`,
138
+ 'ARCANE_POLICY_DENIED');
139
+ }
140
+ return Object.freeze({
141
+ requested:resolved,
142
+ requestedIdentity,
143
+ canonical,
144
+ identity,
145
+ records:Object.freeze(records)
146
+ });
147
+ }
148
+
149
+ async function assertDirectoryChain(chain,label){
150
+ for(const record of chain.records){
151
+ let current;
152
+ try{current=await lstat(record.path,{bigint:true});}
153
+ catch(error){
154
+ if(error?.code==='ENOENT'){
155
+ fail(`${label} changed while its operation boundary was active.`,
156
+ 'ARCANE_POLICY_DENIED');
157
+ }
158
+ throw error;
159
+ }
160
+ if(current.isSymbolicLink()||!current.isDirectory()
161
+ ||!sameLocation(current,record.identity)){
162
+ fail(`${label} changed while its operation boundary was active.`,
163
+ 'ARCANE_POLICY_DENIED');
164
+ }
165
+ }
166
+ let canonical;
167
+ let requestedIdentity;
168
+ try{
169
+ canonical=await realpath(chain.requested);
170
+ requestedIdentity=await lstat(chain.requested,{bigint:true});
171
+ }catch(error){
172
+ if(error?.code==='ENOENT'){
173
+ fail(`${label} changed while its operation boundary was active.`,
174
+ 'ARCANE_POLICY_DENIED');
175
+ }
176
+ throw error;
177
+ }
178
+ if(!samePath(canonical,chain.canonical)
179
+ ||requestedIdentity.isSymbolicLink()||!requestedIdentity.isDirectory()
180
+ ||!sameLocation(requestedIdentity,chain.requestedIdentity)
181
+ ||!sameLocation(requestedIdentity,chain.identity)){
182
+ fail(`${label} changed while its operation boundary was active.`,
183
+ 'ARCANE_POLICY_DENIED');
184
+ }
185
+ }
186
+
187
+ async function ensureLockDirectory(workspace){
188
+ await assertDirectoryChain(workspace,'Arcane workspace');
189
+ const requested=path.join(workspace.canonical,LOCK_DIRECTORY);
190
+ try{await mkdir(requested,{mode:0o700});}
191
+ catch(error){if(error?.code!=='EEXIST')throw error;}
192
+ const directory=await captureRealDirectoryChain(
193
+ requested,
194
+ 'Workspace operation-lock directory'
195
+ );
196
+ if(!samePath(path.dirname(directory.canonical),workspace.canonical)){
197
+ fail('Workspace operation-lock directory must remain directly inside the workspace.',
198
+ 'ARCANE_POLICY_DENIED');
199
+ }
200
+ await assertDirectoryChain(workspace,'Arcane workspace');
201
+ return directory;
202
+ }
203
+
204
+ function ownerIsAlive(pid){
205
+ if(!Number.isSafeInteger(pid)||pid<=0)return true;
206
+ try{
207
+ process.kill(pid,0);
208
+ return true;
209
+ }catch(error){
210
+ return error?.code==='EPERM';
211
+ }
212
+ }
213
+
214
+ function validOperation(operation){
215
+ return typeof operation==='string'&&/^[a-z0-9][a-z0-9.-]*$/u.test(operation);
216
+ }
217
+
218
+ function recoverableDocument(document,{workspaceRoot,now}){
219
+ if(!exactKeys(document,DOCUMENT_KEYS)||!exactKeys(document.owner,OWNER_KEYS))return false;
220
+ const acquired=Date.parse(document.acquiredAt);
221
+ const expires=Date.parse(document.expiresAt);
222
+ return document.schemaVersion===1
223
+ &&document.kind==='arcane-workspace-operation-lock'
224
+ &&validOperation(document.operation)
225
+ &&Number.isSafeInteger(document.owner.pid)
226
+ &&document.owner.pid>0
227
+ &&typeof document.scope==='string'
228
+ &&samePath(document.scope,workspaceRoot)
229
+ &&typeof document.nonce==='string'
230
+ &&/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu
231
+ .test(document.nonce)
232
+ &&Number.isFinite(acquired)
233
+ &&Number.isFinite(expires)
234
+ &&document.ttlMilliseconds===LOCK_TTL_MILLISECONDS
235
+ &&expires===acquired+LOCK_TTL_MILLISECONDS
236
+ &&expires<=now
237
+ &&document.releaseProcedure===RELEASE_PROCEDURE
238
+ &&document.staleRecovery===STALE_RECOVERY
239
+ &&document.securityBoundary===SECURITY_BOUNDARY
240
+ &&!ownerIsAlive(document.owner.pid);
241
+ }
242
+
243
+ async function existingRegularLock(lockPath){
244
+ let current;
245
+ try{current=await lstat(lockPath,{bigint:true});}
246
+ catch(error){
247
+ if(error?.code==='ENOENT')return null;
248
+ throw error;
249
+ }
250
+ if(current.isSymbolicLink()||!current.isFile()){
251
+ fail('Workspace operation lock path is a symbolic link, junction, or non-file.',
252
+ 'ARCANE_POLICY_DENIED');
253
+ }
254
+ return current;
255
+ }
256
+
257
+ async function restoreQuarantinedLock({directory,lockPath,quarantinePath,identity}){
258
+ await assertDirectoryChain(directory,'Workspace operation-lock directory');
259
+ const quarantined=await existingRegularLock(quarantinePath);
260
+ if(quarantined===null||!sameLocation(quarantined,identity))return false;
261
+ if(await existingRegularLock(lockPath)!==null)return false;
262
+ await rename(quarantinePath,lockPath);
263
+ const restored=await existingRegularLock(lockPath);
264
+ return restored!==null&&sameLocation(restored,identity);
265
+ }
266
+
267
+ async function recoverExpiredLock(lockPath,directory,workspaceRoot,onEvent){
268
+ await assertDirectoryChain(directory,'Workspace operation-lock directory');
269
+ const initial=await existingRegularLock(lockPath);
270
+ if(initial===null)return true;
271
+ let handle;
272
+ try{handle=await open(lockPath,OPEN_READ);}
273
+ catch(error){
274
+ if(error?.code==='ENOENT')return true;
275
+ if(error?.code==='ELOOP'){
276
+ fail('Workspace operation lock path is a symbolic link or junction.',
277
+ 'ARCANE_POLICY_DENIED');
278
+ }
279
+ throw error;
280
+ }
281
+ try{
282
+ const before=await handle.stat({bigint:true});
283
+ if(!before.isFile()||before.size>BigInt(MAX_LOCK_BYTES)
284
+ ||!sameFileState(before,initial))return false;
285
+ const bytes=await handle.readFile();
286
+ const after=await handle.stat({bigint:true});
287
+ const current=await existingRegularLock(lockPath);
288
+ if(current===null)return true;
289
+ await assertDirectoryChain(directory,'Workspace operation-lock directory');
290
+ if(!sameFileState(before,after)||!sameFileState(after,current))return false;
291
+ let document;
292
+ try{document=JSON.parse(bytes.toString('utf8'));}
293
+ catch{return false;}
294
+ if(!recoverableDocument(document,{workspaceRoot,now:Date.now()}))return false;
295
+ const canonical=Buffer.from(`${JSON.stringify(document,null,2)}\n`,'utf8');
296
+ if(!canonical.equals(bytes))return false;
297
+ await handle.close();
298
+ handle=null;
299
+ await assertDirectoryChain(directory,'Workspace operation-lock directory');
300
+ const final=await existingRegularLock(lockPath);
301
+ if(final===null)return true;
302
+ if(!sameFileState(final,current))return false;
303
+
304
+ const quarantinePath=path.join(
305
+ directory.canonical,
306
+ `.${LOCK_NAME}.arcane-stale-${String(process.pid)}-${randomUUID()}`
307
+ );
308
+ await rename(lockPath,quarantinePath);
309
+ let quarantinedHandle;
310
+ let quarantineIdentity=await existingRegularLock(quarantinePath);
311
+ if(quarantineIdentity===null||!sameLocation(quarantineIdentity,final)){
312
+ return false;
313
+ }
314
+ let valid=false;
315
+ try{
316
+ await onEvent?.(Object.freeze({
317
+ type:'workspace.operation.stale-quarantined',
318
+ workspaceRoot,
319
+ quarantinePath
320
+ }));
321
+ await assertDirectoryChain(directory,'Workspace operation-lock directory');
322
+ const quarantined=await existingRegularLock(quarantinePath);
323
+ if(quarantined===null||!sameFileState(quarantined,quarantineIdentity))return false;
324
+ quarantinedHandle=await open(quarantinePath,OPEN_READ);
325
+ const quarantineBefore=await quarantinedHandle.stat({bigint:true});
326
+ if(!sameFileState(quarantineBefore,quarantineIdentity))return false;
327
+ const quarantineBytes=await quarantinedHandle.readFile();
328
+ const quarantineAfter=await quarantinedHandle.stat({bigint:true});
329
+ const quarantineCurrent=await existingRegularLock(quarantinePath);
330
+ if(quarantineCurrent===null
331
+ ||!sameFileState(quarantineBefore,quarantineAfter)
332
+ ||!sameFileState(quarantineAfter,quarantineCurrent)
333
+ ||!quarantineBytes.equals(bytes))return false;
334
+ let quarantineDocument;
335
+ try{quarantineDocument=JSON.parse(quarantineBytes.toString('utf8'));}
336
+ catch{return false;}
337
+ const quarantineCanonical=Buffer.from(
338
+ `${JSON.stringify(quarantineDocument,null,2)}\n`,
339
+ 'utf8'
340
+ );
341
+ if(!quarantineCanonical.equals(quarantineBytes)
342
+ ||!recoverableDocument(quarantineDocument,{workspaceRoot,now:Date.now()})){
343
+ return false;
344
+ }
345
+ valid=true;
346
+ }finally{
347
+ await quarantinedHandle?.close().catch(()=>{});
348
+ if(!valid){
349
+ await restoreQuarantinedLock({
350
+ directory,lockPath,quarantinePath,identity:quarantineIdentity
351
+ }).catch(()=>{});
352
+ }
353
+ }
354
+ await assertDirectoryChain(directory,'Workspace operation-lock directory');
355
+ const deletionCandidate=await existingRegularLock(quarantinePath);
356
+ if(deletionCandidate===null||!sameFileState(deletionCandidate,quarantineIdentity)){
357
+ await restoreQuarantinedLock({
358
+ directory,lockPath,quarantinePath,identity:quarantineIdentity
359
+ }).catch(()=>{});
360
+ return false;
361
+ }
362
+ await rm(quarantinePath);
363
+ return true;
364
+ }finally{
365
+ await handle?.close().catch(()=>{});
366
+ }
367
+ }
368
+
369
+ async function validateOwnedLock({workspace,directory,lockPath,handle,identity,bytes,label}){
370
+ await assertDirectoryChain(workspace,'Arcane workspace');
371
+ await assertDirectoryChain(directory,'Workspace operation-lock directory');
372
+ let opened;
373
+ let current;
374
+ try{
375
+ opened=await handle.stat({bigint:true});
376
+ current=await lstat(lockPath,{bigint:true});
377
+ }catch(error){
378
+ if(error?.code==='ENOENT'){
379
+ fail(`Workspace operation lock disappeared ${label}.`, 'ARCANE_POLICY_DENIED');
380
+ }
381
+ throw error;
382
+ }
383
+ if(!opened.isFile()||opened.size!==BigInt(bytes.length)
384
+ ||!sameLocation(opened,identity)||current.isSymbolicLink()||!current.isFile()
385
+ ||!sameLocation(current,identity)){
386
+ fail(`Workspace operation lock changed ${label}.`, 'ARCANE_POLICY_DENIED');
387
+ }
388
+ const read=Buffer.alloc(bytes.length);
389
+ const result=await handle.read(read,0,read.length,0);
390
+ const after=await handle.stat({bigint:true});
391
+ if(result.bytesRead!==bytes.length||!read.equals(bytes)
392
+ ||!sameLocation(after,identity)||after.size!==BigInt(bytes.length)){
393
+ fail(`Workspace operation lock contents changed ${label}.`, 'ARCANE_POLICY_DENIED');
394
+ }
395
+ }
396
+
397
+ async function removeOwnedLock({directory,lockPath,handle,identity}){
398
+ if(!handle||!identity)return {handle:null,removed:false};
399
+ let owned=false;
400
+ try{
401
+ await assertDirectoryChain(directory,'Workspace operation-lock directory');
402
+ const opened=await handle.stat({bigint:true});
403
+ const current=await existingRegularLock(lockPath);
404
+ owned=current!==null&&sameLocation(opened,identity)&&sameLocation(current,identity);
405
+ }finally{
406
+ await handle.close().catch(()=>{});
407
+ handle=null;
408
+ }
409
+ if(!owned)return {handle,removed:false};
410
+ await assertDirectoryChain(directory,'Workspace operation-lock directory');
411
+ const final=await existingRegularLock(lockPath);
412
+ if(final===null)return {handle,removed:true};
413
+ if(!sameLocation(final,identity))return {handle,removed:false};
414
+ await rm(lockPath);
415
+ return {handle,removed:true};
416
+ }
417
+
418
+ function leaseFor(state,operation){
419
+ const lease=Object.freeze({
420
+ workspaceRoot:state.root.workspace.canonical,
421
+ operation,
422
+ nonce:randomUUID(),
423
+ lockPath:state.root.lockPath
424
+ });
425
+ leaseStates.set(lease,state);
426
+ return lease;
427
+ }
428
+
429
+ function inheritedLease(workspace,operation,supplied){
430
+ const parent=leaseStates.get(supplied);
431
+ const root=parent?.root;
432
+ if(!parent?.active||!root?.active
433
+ ||!samePath(parent.root.workspace.canonical,workspace.canonical)
434
+ ||activeRoots.get(workspace.canonical)!==root.lease){
435
+ fail('Arcane workspace operation lease is missing, inactive, or belongs to another workspace.',
436
+ 'ARCANE_POLICY_DENIED');
437
+ }
438
+ if(parent.child!==null){
439
+ fail('The supplied Arcane workspace operation lease already has active nested work.');
440
+ }
441
+ const state=trackedLeaseState({active:true,child:null,parent,root});
442
+ const lease=leaseFor(state,operation);
443
+ state.lease=lease;
444
+ parent.child=state;
445
+ return {
446
+ inherited:true,
447
+ lease,
448
+ release(){
449
+ if(state.releasePromise)return state.releasePromise;
450
+ state.active=false;
451
+ state.releasePromise=(async()=>{
452
+ const child=state.child;
453
+ const misuseError=child===null?null:workspaceBusy(
454
+ 'A nested Arcane workspace operation was still active when its parent settled.'
455
+ );
456
+ try{
457
+ if(child!==null)await child.settled;
458
+ }finally{
459
+ leaseStates.delete(lease);
460
+ if(parent.child===state)parent.child=null;
461
+ settleLeaseState(state);
462
+ }
463
+ if(misuseError)throw misuseError;
464
+ })();
465
+ return state.releasePromise;
466
+ }
467
+ };
468
+ }
469
+
470
+ async function acquire({
471
+ workspaceRoot,
472
+ operation,
473
+ workspaceOperationLease,
474
+ signal,
475
+ onEvent
476
+ }){
477
+ throwIfAborted(signal);
478
+ if(typeof workspaceRoot!=='string'||!workspaceRoot.trim()){
479
+ throw new TypeError('workspaceRoot is required for an Arcane workspace operation lock.');
480
+ }
481
+ if(!validOperation(operation)){
482
+ throw new TypeError('operation must be a stable lowercase Arcane operation name.');
483
+ }
484
+ const workspace=await captureRealDirectoryChain(path.resolve(workspaceRoot),'Arcane workspace');
485
+ if(workspaceOperationLease!==undefined){
486
+ return inheritedLease(workspace,operation,workspaceOperationLease);
487
+ }
488
+ if(activeRoots.has(workspace.canonical)){
489
+ fail(`Another Arcane operation already owns ${workspace.canonical}.`);
490
+ }
491
+ const reservation=Object.freeze({kind:'arcane-workspace-operation-reservation'});
492
+ activeRoots.set(workspace.canonical,reservation);
493
+ let directory;
494
+ let lockPath;
495
+ let handle;
496
+ let identity;
497
+ let rootState;
498
+ try{
499
+ directory=await ensureLockDirectory(workspace);
500
+ lockPath=path.join(directory.canonical,LOCK_NAME);
501
+ let recovered=false;
502
+ for(;;){
503
+ try{
504
+ handle=await open(lockPath,OPEN_EXCLUSIVE,0o600);
505
+ break;
506
+ }catch(error){
507
+ if(error?.code==='EEXIST'){
508
+ if(recovered){
509
+ fail(
510
+ `Workspace is locked by another Arcane operation: ${lockPath}. `
511
+ +'Inspect its owner, expiry, and staleRecovery before retrying.'
512
+ );
513
+ }
514
+ const didRecover=await recoverExpiredLock(
515
+ lockPath,
516
+ directory,
517
+ workspace.canonical,
518
+ onEvent
519
+ );
520
+ if(!didRecover){
521
+ fail(
522
+ `Workspace is locked by another Arcane operation: ${lockPath}. `
523
+ +'Inspect its owner, expiry, and staleRecovery before retrying.'
524
+ );
525
+ }
526
+ recovered=true;
527
+ continue;
528
+ }
529
+ if(error?.code==='ELOOP'){
530
+ fail('Workspace operation lock path is a symbolic link or junction.',
531
+ 'ARCANE_POLICY_DENIED');
532
+ }
533
+ throw error;
534
+ }
535
+ }
536
+ // Claim cleanup ownership immediately after O_EXCL succeeds. This identity remains
537
+ // usable even if a later write, sync, callback, or cancellation boundary fails.
538
+ identity=await handle.stat({bigint:true});
539
+ if(!identity.isFile()){
540
+ fail('Workspace operation lock must be a regular file.','ARCANE_POLICY_DENIED');
541
+ }
542
+ const nonce=randomUUID();
543
+ const acquiredAt=new Date();
544
+ const document=Object.freeze({
545
+ schemaVersion:1,
546
+ kind:'arcane-workspace-operation-lock',
547
+ operation,
548
+ owner:Object.freeze({pid:process.pid}),
549
+ scope:workspace.canonical,
550
+ nonce,
551
+ acquiredAt:acquiredAt.toISOString(),
552
+ expiresAt:new Date(acquiredAt.getTime()+LOCK_TTL_MILLISECONDS).toISOString(),
553
+ ttlMilliseconds:LOCK_TTL_MILLISECONDS,
554
+ releaseProcedure:RELEASE_PROCEDURE,
555
+ staleRecovery:STALE_RECOVERY,
556
+ securityBoundary:SECURITY_BOUNDARY
557
+ });
558
+ const bytes=Buffer.from(`${JSON.stringify(document,null,2)}\n`,'utf8');
559
+ await handle.writeFile(bytes);
560
+ await handle.sync();
561
+ await validateOwnedLock({
562
+ workspace,directory,lockPath,handle,identity,bytes,label:'while it was acquired'
563
+ });
564
+ rootState=trackedLeaseState({
565
+ active:true,
566
+ child:null,
567
+ workspace,
568
+ directory,
569
+ lockPath,
570
+ handle,
571
+ identity,
572
+ bytes
573
+ });
574
+ rootState.root=rootState;
575
+ const lease=Object.freeze({
576
+ workspaceRoot:workspace.canonical,
577
+ operation,
578
+ nonce,
579
+ lockPath
580
+ });
581
+ rootState.lease=lease;
582
+ leaseStates.set(lease,rootState);
583
+ activeRoots.set(workspace.canonical,lease);
584
+ await onEvent?.(Object.freeze({
585
+ type:'workspace.operation.locked',
586
+ workspaceRoot:workspace.canonical,
587
+ operation
588
+ }));
589
+ throwIfAborted(signal);
590
+ await validateOwnedLock({
591
+ workspace,directory,lockPath,handle,identity,bytes,
592
+ label:'after the acquisition callback'
593
+ });
594
+ return {
595
+ inherited:false,
596
+ lease,
597
+ release(){
598
+ if(rootState.releasePromise)return rootState.releasePromise;
599
+ rootState.active=false;
600
+ rootState.releasePromise=(async()=>{
601
+ const child=rootState.child;
602
+ const misuseError=child===null?null:workspaceBusy(
603
+ 'A nested Arcane workspace operation was still active when its root settled.'
604
+ );
605
+ let releaseError;
606
+ let observerError;
607
+ if(child!==null)await child.settled;
608
+ try{
609
+ await validateOwnedLock({
610
+ workspace,directory,lockPath,handle,identity,bytes,
611
+ label:'before release'
612
+ });
613
+ const removed=await removeOwnedLock({directory,lockPath,handle,identity});
614
+ handle=removed.handle;
615
+ rootState.handle=handle;
616
+ if(!removed.removed){
617
+ fail('Workspace operation lock path changed before cleanup.',
618
+ 'ARCANE_POLICY_DENIED');
619
+ }
620
+ }catch(error){
621
+ releaseError=error;
622
+ if(misuseError)releaseError.nestedLeaseError=misuseError;
623
+ if(handle){
624
+ try{
625
+ const removed=await removeOwnedLock({
626
+ directory,lockPath,handle,identity
627
+ });
628
+ handle=removed.handle;
629
+ rootState.handle=handle;
630
+ }catch(cleanupError){
631
+ releaseError.cleanupError=cleanupError;
632
+ }
633
+ }
634
+ }finally{
635
+ if(activeRoots.get(workspace.canonical)===lease){
636
+ activeRoots.delete(workspace.canonical);
637
+ }
638
+ leaseStates.delete(lease);
639
+ await handle?.close().catch(()=>{});
640
+ handle=null;
641
+ rootState.handle=null;
642
+ settleLeaseState(rootState);
643
+ }
644
+ if(releaseError)throw releaseError;
645
+ try{
646
+ await onEvent?.(Object.freeze({
647
+ type:'workspace.operation.released',
648
+ workspaceRoot:workspace.canonical,
649
+ operation
650
+ }));
651
+ }catch(error){observerError=error;}
652
+ if(misuseError){
653
+ if(observerError)misuseError.observerError=observerError;
654
+ throw misuseError;
655
+ }
656
+ return observerError;
657
+ })();
658
+ return rootState.releasePromise;
659
+ }
660
+ };
661
+ }catch(error){
662
+ if(rootState){
663
+ rootState.active=false;
664
+ if(rootState.lease)leaseStates.delete(rootState.lease);
665
+ settleLeaseState(rootState);
666
+ }
667
+ if(activeRoots.get(workspace.canonical)===reservation
668
+ ||activeRoots.get(workspace.canonical)===rootState?.lease){
669
+ activeRoots.delete(workspace.canonical);
670
+ }
671
+ if(handle&&directory&&lockPath&&identity){
672
+ try{
673
+ const removed=await removeOwnedLock({directory,lockPath,handle,identity});
674
+ handle=removed.handle;
675
+ }catch(cleanupError){
676
+ error.cleanupError=cleanupError;
677
+ }
678
+ }
679
+ await handle?.close().catch(()=>{});
680
+ throw error;
681
+ }
682
+ }
683
+
684
+ function attachReleaseError(workError,releaseError){
685
+ try{
686
+ workError.releaseError=releaseError;
687
+ return workError;
688
+ }catch{
689
+ return new AggregateError(
690
+ [workError,releaseError],
691
+ 'The Arcane workspace operation and its lock release both failed.',
692
+ {cause:workError}
693
+ );
694
+ }
695
+ }
696
+
697
+ export async function withWorkspaceOperationLock(options,work){
698
+ if(typeof work!=='function')throw new TypeError('Workspace operation lock work must be a function.');
699
+ const acquired=await acquire(options);
700
+ let result;
701
+ let workError;
702
+ try{
703
+ result=await work(acquired.lease);
704
+ }catch(error){workError=error;}
705
+ let releaseObserverError;
706
+ try{releaseObserverError=await acquired.release();}
707
+ catch(releaseError){
708
+ if(workError)workError=attachReleaseError(workError,releaseError);
709
+ else throw releaseError;
710
+ }
711
+ if(workError&&releaseObserverError){
712
+ workError=attachReleaseError(workError,releaseObserverError);
713
+ }
714
+ if(workError)throw workError;
715
+ return result;
716
+ }