@triedotdev/mcp 1.0.164 → 1.0.166

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 (62) hide show
  1. package/README.md +16 -2
  2. package/dist/{chunk-5TRCQAOE.js → chunk-2Z3TQNNK.js} +16 -5
  3. package/dist/chunk-2Z3TQNNK.js.map +1 -0
  4. package/dist/{chunk-5BYSJ7XT.js → chunk-GTKYBOXL.js} +13 -2
  5. package/dist/{chunk-5BYSJ7XT.js.map → chunk-GTKYBOXL.js.map} +1 -1
  6. package/dist/{chunk-D6E4Q4I6.js → chunk-HOGKPDZA.js} +302 -58
  7. package/dist/chunk-HOGKPDZA.js.map +1 -0
  8. package/dist/{chunk-LR46VMIE.js → chunk-JEZ7XJQN.js} +5 -5
  9. package/dist/{chunk-ERMLZJTK.js → chunk-JNUOW2JS.js} +13 -13
  10. package/dist/{chunk-62JD7MIS.js → chunk-LG5CBK6A.js} +15 -35
  11. package/dist/chunk-LG5CBK6A.js.map +1 -0
  12. package/dist/{chunk-LLDZDU2Y.js → chunk-LR5M4RTN.js} +79 -1
  13. package/dist/chunk-LR5M4RTN.js.map +1 -0
  14. package/dist/{chunk-Y4B3VEL7.js → chunk-MVVPJ73K.js} +438 -202
  15. package/dist/chunk-MVVPJ73K.js.map +1 -0
  16. package/dist/chunk-OBQ74FOU.js +27 -0
  17. package/dist/chunk-OBQ74FOU.js.map +1 -0
  18. package/dist/{chunk-IRZXBQVQ.js → chunk-S36IO3EE.js} +134 -101
  19. package/dist/chunk-S36IO3EE.js.map +1 -0
  20. package/dist/{chunk-HFVPHQL3.js → chunk-TQOO6A4G.js} +9 -9
  21. package/dist/{chunk-OKK4QNK3.js → chunk-UXRW2YSP.js} +86 -12
  22. package/dist/chunk-UXRW2YSP.js.map +1 -0
  23. package/dist/{chunk-ACU3IXZG.js → chunk-ZKKKLRZZ.js} +7 -7
  24. package/dist/cli/main.js +215 -57
  25. package/dist/cli/main.js.map +1 -1
  26. package/dist/cli/yolo-daemon.js +15 -14
  27. package/dist/cli/yolo-daemon.js.map +1 -1
  28. package/dist/{fast-analyzer-LLZ6FLP5.js → fast-analyzer-NJQO3TFD.js} +3 -3
  29. package/dist/{goal-manager-D6XKE3FY.js → goal-manager-DVX24UPZ.js} +5 -5
  30. package/dist/{goal-validator-4DDL7NBP.js → goal-validator-6Y5CDEMJ.js} +5 -5
  31. package/dist/{hypothesis-RI3Q33JB.js → hypothesis-UKPGOYY2.js} +5 -5
  32. package/dist/index.js +16 -15
  33. package/dist/index.js.map +1 -1
  34. package/dist/{issue-store-DUR5UTYK.js → issue-store-UZAPI5DU.js} +3 -3
  35. package/dist/{ledger-ZTR63P3L.js → ledger-CNFCJKHX.js} +8 -2
  36. package/dist/project-state-AHPA77SM.js +28 -0
  37. package/dist/server/mcp-server.js +16 -15
  38. package/dist/sync-M2FSWPBC.js +12 -0
  39. package/dist/{tiered-storage-FHHAJR4P.js → tiered-storage-OP74NPJY.js} +2 -2
  40. package/dist/tiered-storage-OP74NPJY.js.map +1 -0
  41. package/dist/{trie-agent-NYSPGZYS.js → trie-agent-6SWUHCVO.js} +12 -12
  42. package/dist/trie-agent-6SWUHCVO.js.map +1 -0
  43. package/package.json +1 -1
  44. package/dist/chunk-5TRCQAOE.js.map +0 -1
  45. package/dist/chunk-62JD7MIS.js.map +0 -1
  46. package/dist/chunk-D6E4Q4I6.js.map +0 -1
  47. package/dist/chunk-IRZXBQVQ.js.map +0 -1
  48. package/dist/chunk-LLDZDU2Y.js.map +0 -1
  49. package/dist/chunk-OKK4QNK3.js.map +0 -1
  50. package/dist/chunk-Y4B3VEL7.js.map +0 -1
  51. /package/dist/{chunk-LR46VMIE.js.map → chunk-JEZ7XJQN.js.map} +0 -0
  52. /package/dist/{chunk-ERMLZJTK.js.map → chunk-JNUOW2JS.js.map} +0 -0
  53. /package/dist/{chunk-HFVPHQL3.js.map → chunk-TQOO6A4G.js.map} +0 -0
  54. /package/dist/{chunk-ACU3IXZG.js.map → chunk-ZKKKLRZZ.js.map} +0 -0
  55. /package/dist/{fast-analyzer-LLZ6FLP5.js.map → fast-analyzer-NJQO3TFD.js.map} +0 -0
  56. /package/dist/{goal-manager-D6XKE3FY.js.map → goal-manager-DVX24UPZ.js.map} +0 -0
  57. /package/dist/{goal-validator-4DDL7NBP.js.map → goal-validator-6Y5CDEMJ.js.map} +0 -0
  58. /package/dist/{hypothesis-RI3Q33JB.js.map → hypothesis-UKPGOYY2.js.map} +0 -0
  59. /package/dist/{issue-store-DUR5UTYK.js.map → issue-store-UZAPI5DU.js.map} +0 -0
  60. /package/dist/{ledger-ZTR63P3L.js.map → ledger-CNFCJKHX.js.map} +0 -0
  61. /package/dist/{tiered-storage-FHHAJR4P.js.map → project-state-AHPA77SM.js.map} +0 -0
  62. /package/dist/{trie-agent-NYSPGZYS.js.map → sync-M2FSWPBC.js.map} +0 -0
@@ -5,18 +5,146 @@ import {
5
5
  getTrieDirectory,
6
6
  getWorkingDirectory
7
7
  } from "./chunk-VVITXIHN.js";
8
+ import {
9
+ __require
10
+ } from "./chunk-DGUM43GV.js";
8
11
 
9
12
  // src/memory/ledger.ts
10
13
  import { createHash } from "crypto";
11
- import { mkdir, readFile, writeFile, stat, unlink } from "fs/promises";
12
- import { existsSync as existsSync4 } from "fs";
14
+ import { mkdir as mkdir2, readFile as readFile2, writeFile, stat as stat2, unlink as unlink2 } from "fs/promises";
15
+ import { existsSync as existsSync5 } from "fs";
13
16
  import { createGzip, createGunzip } from "zlib";
14
17
  import { pipeline } from "stream/promises";
15
18
  import { createReadStream, createWriteStream } from "fs";
16
19
  import { join as join3 } from "path";
17
20
 
18
- // src/agent/git.ts
21
+ // src/utils/file-lock.ts
22
+ import { open, unlink, readFile, stat, mkdir } from "fs/promises";
19
23
  import { existsSync } from "fs";
24
+ import { dirname } from "path";
25
+ var activeLocks = /* @__PURE__ */ new Set();
26
+ function setupCleanupHandler() {
27
+ const cleanup = () => {
28
+ for (const lockPath of activeLocks) {
29
+ try {
30
+ const fs = __require("fs");
31
+ if (fs.existsSync(lockPath)) {
32
+ fs.unlinkSync(lockPath);
33
+ }
34
+ } catch {
35
+ }
36
+ }
37
+ };
38
+ process.on("exit", cleanup);
39
+ process.on("SIGINT", () => {
40
+ cleanup();
41
+ process.exit(130);
42
+ });
43
+ process.on("SIGTERM", () => {
44
+ cleanup();
45
+ process.exit(143);
46
+ });
47
+ }
48
+ var cleanupHandlerInstalled = false;
49
+ async function withFileLock(filePath, fn, options = {}) {
50
+ const {
51
+ timeout = 1e4,
52
+ retryDelay = 50,
53
+ maxRetryDelay = 500,
54
+ staleTimeout = 3e4
55
+ } = options;
56
+ const lockPath = `${filePath}.lock`;
57
+ const start = Date.now();
58
+ let currentDelay = retryDelay;
59
+ if (!cleanupHandlerInstalled) {
60
+ setupCleanupHandler();
61
+ cleanupHandlerInstalled = true;
62
+ }
63
+ await mkdir(dirname(lockPath), { recursive: true });
64
+ while (true) {
65
+ try {
66
+ await cleanupStaleLock(lockPath, staleTimeout);
67
+ const lockInfo = {
68
+ pid: process.pid,
69
+ timestamp: Date.now(),
70
+ hostname: __require("os").hostname()
71
+ };
72
+ const handle = await open(lockPath, "wx");
73
+ await handle.writeFile(JSON.stringify(lockInfo));
74
+ await handle.close();
75
+ activeLocks.add(lockPath);
76
+ try {
77
+ return await fn();
78
+ } finally {
79
+ activeLocks.delete(lockPath);
80
+ await unlink(lockPath).catch(() => {
81
+ });
82
+ }
83
+ } catch (err) {
84
+ if (err.code !== "EEXIST") {
85
+ throw err;
86
+ }
87
+ if (Date.now() - start > timeout) {
88
+ let lockHolder = "unknown";
89
+ try {
90
+ const content = await readFile(lockPath, "utf-8");
91
+ const info = JSON.parse(content);
92
+ lockHolder = `PID ${info.pid} on ${info.hostname}`;
93
+ } catch {
94
+ }
95
+ throw new Error(
96
+ `Timeout acquiring lock for ${filePath} after ${timeout}ms. Lock held by: ${lockHolder}`
97
+ );
98
+ }
99
+ await new Promise((resolve) => setTimeout(resolve, currentDelay));
100
+ currentDelay = Math.min(currentDelay * 2, maxRetryDelay);
101
+ }
102
+ }
103
+ }
104
+ async function cleanupStaleLock(lockPath, staleTimeout) {
105
+ if (!existsSync(lockPath)) {
106
+ return;
107
+ }
108
+ try {
109
+ const content = await readFile(lockPath, "utf-8");
110
+ const info = JSON.parse(content);
111
+ const lockAge = Date.now() - info.timestamp;
112
+ if (lockAge > staleTimeout) {
113
+ console.warn(`[FileLock] Removing stale lock (age: ${Math.round(lockAge / 1e3)}s): ${lockPath}`);
114
+ await unlink(lockPath);
115
+ return;
116
+ }
117
+ const currentHostname = __require("os").hostname();
118
+ if (info.hostname === currentHostname) {
119
+ if (!isProcessRunning(info.pid)) {
120
+ console.warn(`[FileLock] Removing orphaned lock (PID ${info.pid} not running): ${lockPath}`);
121
+ await unlink(lockPath);
122
+ return;
123
+ }
124
+ }
125
+ } catch {
126
+ try {
127
+ const stats = await stat(lockPath);
128
+ const fileAge = Date.now() - stats.mtimeMs;
129
+ if (fileAge > staleTimeout) {
130
+ console.warn(`[FileLock] Removing stale/corrupted lock: ${lockPath}`);
131
+ await unlink(lockPath);
132
+ }
133
+ } catch {
134
+ }
135
+ }
136
+ }
137
+ function isProcessRunning(pid) {
138
+ try {
139
+ process.kill(pid, 0);
140
+ return true;
141
+ } catch {
142
+ return false;
143
+ }
144
+ }
145
+
146
+ // src/agent/git.ts
147
+ import { existsSync as existsSync2 } from "fs";
20
148
  import path from "path";
21
149
 
22
150
  // src/utils/command-runner.ts
@@ -319,7 +447,7 @@ async function getChangedFilesSinceTimestamp(projectPath, timestamp) {
319
447
  // src/memory/crypto-keys.ts
320
448
  import * as ed25519 from "@noble/ed25519";
321
449
  import { randomBytes } from "crypto";
322
- import { existsSync as existsSync2, mkdirSync, readFileSync, writeFileSync } from "fs";
450
+ import { existsSync as existsSync3, mkdirSync, readFileSync, writeFileSync } from "fs";
323
451
  import { join } from "path";
324
452
  function getKeysDirectory(workDir) {
325
453
  const trieDir = getTrieDirectory(workDir || process.cwd());
@@ -338,7 +466,7 @@ async function generateKeyPair() {
338
466
  }
339
467
  function saveKeyPair(keyPair, workDir) {
340
468
  const keysDir = getKeysDirectory(workDir);
341
- if (!existsSync2(keysDir)) {
469
+ if (!existsSync3(keysDir)) {
342
470
  mkdirSync(keysDir, { recursive: true });
343
471
  }
344
472
  const keyPath = getDefaultKeyPath(workDir);
@@ -353,7 +481,7 @@ function saveKeyPair(keyPair, workDir) {
353
481
  }
354
482
  function loadKeyPair(workDir) {
355
483
  const keyPath = getDefaultKeyPath(workDir);
356
- if (!existsSync2(keyPath)) {
484
+ if (!existsSync3(keyPath)) {
357
485
  return null;
358
486
  }
359
487
  try {
@@ -410,25 +538,29 @@ async function verifyHashSignature(hash, signatureData) {
410
538
  }
411
539
  return await verifySignature(hash, signatureData.signature, signatureData.publicKey);
412
540
  }
541
+ function getPublicKey(workDir) {
542
+ const keyPair = loadKeyPair(workDir);
543
+ return keyPair?.publicKey || null;
544
+ }
413
545
  function hasSigningKey(workDir) {
414
546
  const keyPath = getDefaultKeyPath(workDir);
415
- return existsSync2(keyPath);
547
+ return existsSync3(keyPath);
416
548
  }
417
549
 
418
550
  // src/memory/git-integration.ts
419
551
  import { exec as exec2 } from "child_process";
420
552
  import { promisify as promisify2 } from "util";
421
- import { existsSync as existsSync3 } from "fs";
553
+ import { existsSync as existsSync4 } from "fs";
422
554
  import { join as join2 } from "path";
423
555
  var execAsync2 = promisify2(exec2);
424
556
  async function isGitIntegrationEnabled(workDir) {
425
557
  try {
426
558
  const gitDir = join2(workDir, ".git");
427
- if (!existsSync3(gitDir)) {
559
+ if (!existsSync4(gitDir)) {
428
560
  return false;
429
561
  }
430
562
  const configPath = join2(getTrieDirectory(workDir), "config.json");
431
- if (!existsSync3(configPath)) {
563
+ if (!existsSync4(configPath)) {
432
564
  return true;
433
565
  }
434
566
  const config = JSON.parse(await import("fs/promises").then((fs) => fs.readFile(configPath, "utf-8")));
@@ -473,7 +605,7 @@ async function ensureKeysIgnored(workDir) {
473
605
  const gitignorePath = join2(workDir, ".gitignore");
474
606
  const fs = await import("fs/promises");
475
607
  let gitignore = "";
476
- if (existsSync3(gitignorePath)) {
608
+ if (existsSync4(gitignorePath)) {
477
609
  gitignore = await fs.readFile(gitignorePath, "utf-8");
478
610
  }
479
611
  if (gitignore.includes(".trie/keys/")) {
@@ -493,6 +625,12 @@ var MANIFEST_FILENAME = "ledger-manifest.json";
493
625
  var SYNC_STATE_FILENAME = "ledger-sync.json";
494
626
  var GENESIS_HASH = "0".repeat(64);
495
627
  var LEDGER_VERSION = 2;
628
+ var ConcurrentModificationError = class extends Error {
629
+ constructor(message) {
630
+ super(message);
631
+ this.name = "ConcurrentModificationError";
632
+ }
633
+ };
496
634
  async function signLedgerEntry(entry, workDir) {
497
635
  try {
498
636
  const signatureData = await signHash(entry.hash, workDir);
@@ -541,42 +679,48 @@ async function appendIssuesToLedger(issues, workDir, author) {
541
679
  if (issues.length === 0) return null;
542
680
  const projectDir = workDir || getWorkingDirectory(void 0, true);
543
681
  const memoryDir = join3(getTrieDirectory(projectDir), "memory");
544
- await mkdir(memoryDir, { recursive: true });
545
- const isRepo = await isGitRepo(projectDir);
546
- const lastCommit = isRepo ? await getLastCommit(projectDir) : null;
547
- const blockAuthor = author || lastCommit?.author || "unknown";
548
- const blocks = await loadLedger(projectDir);
549
- const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
550
- const now = (/* @__PURE__ */ new Date()).toISOString();
551
- const shouldSign = hasSigningKey(projectDir);
552
- let entries = issues.map((issue) => ({
553
- id: issue.id,
554
- hash: issue.hash,
555
- severity: issue.severity,
556
- file: issue.file,
557
- agent: issue.agent,
558
- timestamp: issue.timestamp,
559
- status: "active"
560
- }));
561
- if (shouldSign) {
562
- entries = await Promise.all(entries.map((entry) => signLedgerEntry(entry, projectDir)));
563
- }
564
- const previousBlock = blocks[blocks.length - 1];
565
- const block = previousBlock && previousBlock.date === today ? previousBlock : createSyncableBlock(today, now, previousBlock?.blockHash ?? GENESIS_HASH, blockAuthor, lastCommit?.hash, blocks.length);
566
- if (block !== previousBlock) {
567
- blocks.push(block);
568
- }
569
- block.entries = [...block.entries, ...entries];
570
- block.merkleRoot = computeMerkleRoot(block.entries.map((entry) => entry.hash));
571
- block.blockHash = computeBlockHash(block.previousHash, block.merkleRoot, block.date, block.version);
572
- block.updatedAt = now;
573
- await saveLedger(blocks, projectDir);
574
- if (await isGitRepo(projectDir)) {
575
- await ensureKeysIgnored(projectDir);
576
- const commitMessage = `ledger: append ${entries.length} ${entries.length === 1 ? "entry" : "entries"}`;
577
- await autoCommitLedger(projectDir, commitMessage);
578
- }
579
- return block;
682
+ await mkdir2(memoryDir, { recursive: true });
683
+ const ledgerPath = join3(memoryDir, LEDGER_FILENAME);
684
+ return withFileLock(ledgerPath, async () => {
685
+ const isRepo = await isGitRepo(projectDir);
686
+ const lastCommit = isRepo ? await getLastCommit(projectDir) : null;
687
+ const blockAuthor = author || lastCommit?.author || "unknown";
688
+ const blocks = await loadLedger(projectDir);
689
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
690
+ const now = (/* @__PURE__ */ new Date()).toISOString();
691
+ const shouldSign = hasSigningKey(projectDir);
692
+ let entries = issues.map((issue) => ({
693
+ id: issue.id,
694
+ hash: issue.hash,
695
+ severity: issue.severity,
696
+ file: issue.file,
697
+ agent: issue.agent,
698
+ timestamp: issue.timestamp,
699
+ status: "active",
700
+ // Include semantic content for ambient awareness
701
+ issue: issue.issue,
702
+ fix: issue.fix
703
+ }));
704
+ if (shouldSign) {
705
+ entries = await Promise.all(entries.map((entry) => signLedgerEntry(entry, projectDir)));
706
+ }
707
+ const previousBlock = blocks[blocks.length - 1];
708
+ const block = previousBlock && previousBlock.date === today ? previousBlock : createSyncableBlock(today, now, previousBlock?.blockHash ?? GENESIS_HASH, blockAuthor, lastCommit?.hash, blocks.length);
709
+ if (block !== previousBlock) {
710
+ blocks.push(block);
711
+ }
712
+ block.entries = [...block.entries, ...entries];
713
+ block.merkleRoot = computeMerkleRoot(block.entries.map((entry) => entry.hash));
714
+ block.blockHash = computeBlockHash(block.previousHash, block.merkleRoot, block.date, block.version);
715
+ block.updatedAt = now;
716
+ await saveLedgerInternal(blocks, projectDir);
717
+ if (await isGitRepo(projectDir)) {
718
+ await ensureKeysIgnored(projectDir);
719
+ const commitMessage = `ledger: append ${entries.length} ${entries.length === 1 ? "entry" : "entries"}`;
720
+ await autoCommitLedger(projectDir, commitMessage);
721
+ }
722
+ return block;
723
+ }, { timeout: 15e3 });
580
724
  }
581
725
  async function verifyLedger(workDir) {
582
726
  const projectDir = workDir || getWorkingDirectory(void 0, true);
@@ -649,24 +793,80 @@ function createSyncableBlock(date, now, previousHash, author, gitCommit, chainHe
649
793
  };
650
794
  }
651
795
  async function loadLedger(projectDir) {
796
+ const result = await loadLedgerWithHash(projectDir);
797
+ return result.blocks;
798
+ }
799
+ async function loadLedgerWithHash(projectDir) {
652
800
  const ledgerPath = join3(getTrieDirectory(projectDir), "memory", LEDGER_FILENAME);
653
801
  try {
654
- if (!existsSync4(ledgerPath)) return [];
655
- const content = await readFile(ledgerPath, "utf-8");
802
+ if (!existsSync5(ledgerPath)) {
803
+ return { blocks: [], contentHash: sha256("[]") };
804
+ }
805
+ const content = await readFile2(ledgerPath, "utf-8");
656
806
  const parsed = JSON.parse(content);
657
- if (!Array.isArray(parsed)) return [];
658
- return parsed;
807
+ if (parsed && parsed._format === "ledger-v2") {
808
+ const file = parsed;
809
+ return {
810
+ blocks: file.blocks || [],
811
+ contentHash: file._contentHash
812
+ };
813
+ }
814
+ if (!Array.isArray(parsed)) {
815
+ return { blocks: [], contentHash: sha256("[]") };
816
+ }
817
+ const blocks = parsed;
818
+ const contentHash = sha256(JSON.stringify(blocks));
819
+ return { blocks, contentHash };
659
820
  } catch {
660
- return [];
821
+ return { blocks: [], contentHash: sha256("[]") };
661
822
  }
662
823
  }
663
824
  async function getLedgerBlocks(workDir) {
664
825
  const projectDir = workDir || getWorkingDirectory(void 0, true);
665
826
  return loadLedger(projectDir);
666
827
  }
828
+ async function getLedgerBlocksWithHash(workDir) {
829
+ const projectDir = workDir || getWorkingDirectory(void 0, true);
830
+ return loadLedgerWithHash(projectDir);
831
+ }
832
+ async function saveLedgerOptimistic(blocks, expectedHash, workDir) {
833
+ const projectDir = workDir || getWorkingDirectory(void 0, true);
834
+ const memoryDir = join3(getTrieDirectory(projectDir), "memory");
835
+ const ledgerPath = join3(memoryDir, LEDGER_FILENAME);
836
+ await withFileLock(ledgerPath, async () => {
837
+ await saveLedgerWithConcurrencyCheck(blocks, projectDir, expectedHash);
838
+ }, { timeout: 1e4 });
839
+ }
667
840
  async function saveLedger(blocks, projectDir) {
668
841
  const ledgerPath = join3(getTrieDirectory(projectDir), "memory", LEDGER_FILENAME);
669
- await atomicWriteJSON(ledgerPath, blocks);
842
+ await withFileLock(ledgerPath, async () => {
843
+ await saveLedgerWithFormat(ledgerPath, blocks);
844
+ }, { timeout: 1e4 });
845
+ }
846
+ async function saveLedgerInternal(blocks, projectDir) {
847
+ const ledgerPath = join3(getTrieDirectory(projectDir), "memory", LEDGER_FILENAME);
848
+ await saveLedgerWithFormat(ledgerPath, blocks);
849
+ }
850
+ async function saveLedgerWithConcurrencyCheck(blocks, projectDir, expectedHash) {
851
+ const ledgerPath = join3(getTrieDirectory(projectDir), "memory", LEDGER_FILENAME);
852
+ const { contentHash: currentHash } = await loadLedgerWithHash(projectDir);
853
+ if (currentHash !== expectedHash) {
854
+ throw new ConcurrentModificationError(
855
+ `Ledger was modified by another process. Expected hash: ${expectedHash.slice(0, 16)}..., Current hash: ${currentHash.slice(0, 16)}...`
856
+ );
857
+ }
858
+ await saveLedgerWithFormat(ledgerPath, blocks);
859
+ }
860
+ async function saveLedgerWithFormat(ledgerPath, blocks) {
861
+ const blocksJson = JSON.stringify(blocks);
862
+ const contentHash = sha256(blocksJson);
863
+ const ledgerFile = {
864
+ _format: "ledger-v2",
865
+ _contentHash: contentHash,
866
+ _lastModified: (/* @__PURE__ */ new Date()).toISOString(),
867
+ blocks
868
+ };
869
+ await atomicWriteJSON(ledgerPath, ledgerFile);
670
870
  }
671
871
  function sha256(input) {
672
872
  return createHash("sha256").update(input).digest("hex");
@@ -690,15 +890,15 @@ async function ensureSharedStorageStructure(projectDir) {
690
890
  const sharedDir = getSharedLedgerDir(projectDir);
691
891
  const activeDir = getActiveBlocksDir(projectDir);
692
892
  const archivedDir = getArchivedBlocksDir(projectDir);
693
- await mkdir(sharedDir, { recursive: true });
694
- await mkdir(activeDir, { recursive: true });
695
- await mkdir(archivedDir, { recursive: true });
893
+ await mkdir2(sharedDir, { recursive: true });
894
+ await mkdir2(activeDir, { recursive: true });
895
+ await mkdir2(archivedDir, { recursive: true });
696
896
  }
697
897
  async function loadManifest(projectDir) {
698
898
  const manifestPath = getManifestPath(projectDir);
699
899
  try {
700
- if (!existsSync4(manifestPath)) return null;
701
- const content = await readFile(manifestPath, "utf-8");
900
+ if (!existsSync5(manifestPath)) return null;
901
+ const content = await readFile2(manifestPath, "utf-8");
702
902
  return JSON.parse(content);
703
903
  } catch {
704
904
  return null;
@@ -735,8 +935,8 @@ async function createDefaultManifest(_projectDir) {
735
935
  async function loadSyncState(projectDir) {
736
936
  const syncStatePath = getSyncStatePath(projectDir);
737
937
  try {
738
- if (!existsSync4(syncStatePath)) return null;
739
- const content = await readFile(syncStatePath, "utf-8");
938
+ if (!existsSync5(syncStatePath)) return null;
939
+ const content = await readFile2(syncStatePath, "utf-8");
740
940
  return JSON.parse(content);
741
941
  } catch {
742
942
  return null;
@@ -745,7 +945,7 @@ async function loadSyncState(projectDir) {
745
945
  async function saveSyncState(syncState, projectDir) {
746
946
  const syncStatePath = getSyncStatePath(projectDir);
747
947
  const memoryDir = join3(getTrieDirectory(projectDir), "memory");
748
- await mkdir(memoryDir, { recursive: true });
948
+ await mkdir2(memoryDir, { recursive: true });
749
949
  await atomicWriteJSON(syncStatePath, syncState);
750
950
  }
751
951
  async function initializeSharedLedger(workDir) {
@@ -770,54 +970,62 @@ async function initializeSharedLedger(workDir) {
770
970
  }
771
971
  async function syncLedgerFromShared(workDir) {
772
972
  const projectDir = workDir || getWorkingDirectory(void 0, true);
973
+ const memoryDir = join3(getTrieDirectory(projectDir), "memory");
974
+ const ledgerPath = join3(memoryDir, LEDGER_FILENAME);
773
975
  await initializeSharedLedger(projectDir);
774
- const manifest = await loadManifest(projectDir);
775
- const localBlocks = await loadLedger(projectDir);
776
- const sharedBlocks = await loadSharedBlocks(projectDir);
777
- if (!manifest) {
778
- throw new Error("Failed to load ledger manifest");
779
- }
780
- const mergeResult = await mergeChains(localBlocks, sharedBlocks, "timestamp");
781
- await saveLedger(mergeResult.mergedChain, projectDir);
782
- const syncState = {
783
- lastSyncTimestamp: (/* @__PURE__ */ new Date()).toISOString(),
784
- conflicts: mergeResult.conflicts,
785
- localChanges: false,
786
- sharedChanges: false
787
- };
788
- await saveSyncState(syncState, projectDir);
789
- return mergeResult;
976
+ return withFileLock(ledgerPath, async () => {
977
+ const manifest = await loadManifest(projectDir);
978
+ const localBlocks = await loadLedger(projectDir);
979
+ const sharedBlocks = await loadSharedBlocks(projectDir);
980
+ if (!manifest) {
981
+ throw new Error("Failed to load ledger manifest");
982
+ }
983
+ const mergeResult = await mergeChains(localBlocks, sharedBlocks, "timestamp");
984
+ await saveLedgerInternal(mergeResult.mergedChain, projectDir);
985
+ const syncState = {
986
+ lastSyncTimestamp: (/* @__PURE__ */ new Date()).toISOString(),
987
+ conflicts: mergeResult.conflicts,
988
+ localChanges: false,
989
+ sharedChanges: false
990
+ };
991
+ await saveSyncState(syncState, projectDir);
992
+ return mergeResult;
993
+ }, { timeout: 3e4 });
790
994
  }
791
995
  async function pushLedgerToShared(workDir) {
792
996
  const projectDir = workDir || getWorkingDirectory(void 0, true);
997
+ const memoryDir = join3(getTrieDirectory(projectDir), "memory");
998
+ const ledgerPath = join3(memoryDir, LEDGER_FILENAME);
793
999
  await initializeSharedLedger(projectDir);
794
- const localBlocks = await loadLedger(projectDir);
795
- const manifest = await loadManifest(projectDir) || await createDefaultManifest(projectDir);
796
- const activeDir = getActiveBlocksDir(projectDir);
797
- for (const block of localBlocks) {
798
- const blockFilename = `${block.date}.json`;
799
- const blockPath = join3(activeDir, blockFilename);
800
- if (!existsSync4(blockPath) || block.updatedAt > manifest.lastSync) {
801
- await atomicWriteJSON(blockPath, block);
802
- manifest.index.byDate[block.date] = `active/${blockFilename}`;
803
- const blockAuthor = block.author;
804
- if (blockAuthor) {
805
- if (!manifest.index.byAuthor[blockAuthor]) {
806
- manifest.index.byAuthor[blockAuthor] = [];
1000
+ await withFileLock(ledgerPath, async () => {
1001
+ const localBlocks = await loadLedger(projectDir);
1002
+ const manifest = await loadManifest(projectDir) || await createDefaultManifest(projectDir);
1003
+ const activeDir = getActiveBlocksDir(projectDir);
1004
+ for (const block of localBlocks) {
1005
+ const blockFilename = `${block.date}.json`;
1006
+ const blockPath = join3(activeDir, blockFilename);
1007
+ if (!existsSync5(blockPath) || block.updatedAt > manifest.lastSync) {
1008
+ await atomicWriteJSON(blockPath, block);
1009
+ manifest.index.byDate[block.date] = `active/${blockFilename}`;
1010
+ const blockAuthor = block.author;
1011
+ if (blockAuthor) {
1012
+ if (!manifest.index.byAuthor[blockAuthor]) {
1013
+ manifest.index.byAuthor[blockAuthor] = [];
1014
+ }
1015
+ if (!manifest.index.byAuthor[blockAuthor].includes(`active/${blockFilename}`)) {
1016
+ manifest.index.byAuthor[blockAuthor].push(`active/${blockFilename}`);
1017
+ }
807
1018
  }
808
- if (!manifest.index.byAuthor[blockAuthor].includes(`active/${blockFilename}`)) {
809
- manifest.index.byAuthor[blockAuthor].push(`active/${blockFilename}`);
1019
+ if (!manifest.activeBlocks.includes(blockFilename)) {
1020
+ manifest.activeBlocks.push(blockFilename);
810
1021
  }
811
1022
  }
812
- if (!manifest.activeBlocks.includes(blockFilename)) {
813
- manifest.activeBlocks.push(blockFilename);
814
- }
815
1023
  }
816
- }
817
- manifest.lastSync = (/* @__PURE__ */ new Date()).toISOString();
818
- manifest.totalBlocks = manifest.activeBlocks.length + manifest.archivedBlocks.length;
819
- manifest.totalEntries = localBlocks.reduce((sum, block) => sum + block.entries.length, 0);
820
- await saveManifest(manifest, projectDir);
1024
+ manifest.lastSync = (/* @__PURE__ */ new Date()).toISOString();
1025
+ manifest.totalBlocks = manifest.activeBlocks.length + manifest.archivedBlocks.length;
1026
+ manifest.totalEntries = localBlocks.reduce((sum, block) => sum + block.entries.length, 0);
1027
+ await saveManifest(manifest, projectDir);
1028
+ }, { timeout: 3e4 });
821
1029
  }
822
1030
  async function loadSharedBlocks(projectDir) {
823
1031
  const manifest = await loadManifest(projectDir);
@@ -827,8 +1035,8 @@ async function loadSharedBlocks(projectDir) {
827
1035
  for (const filename of manifest.activeBlocks) {
828
1036
  const blockPath = join3(activeDir, filename);
829
1037
  try {
830
- if (existsSync4(blockPath)) {
831
- const content = await readFile(blockPath, "utf-8");
1038
+ if (existsSync5(blockPath)) {
1039
+ const content = await readFile2(blockPath, "utf-8");
832
1040
  const block = JSON.parse(content);
833
1041
  blocks.push(block);
834
1042
  }
@@ -919,16 +1127,29 @@ function resolveConflict(conflict, strategy) {
919
1127
  if (!conflict.localBlock || !conflict.remoteBlock) {
920
1128
  return null;
921
1129
  }
1130
+ const mergedBlock = mergeBlockEntries(conflict.localBlock, conflict.remoteBlock);
1131
+ mergedBlock.conflictResolved = true;
922
1132
  switch (strategy) {
923
- case "longest":
924
- return conflict.localBlock.entries.length >= conflict.remoteBlock.entries.length ? conflict.localBlock : conflict.remoteBlock;
925
1133
  case "timestamp":
926
- return conflict.localBlock.updatedAt >= conflict.remoteBlock.updatedAt ? conflict.localBlock : conflict.remoteBlock;
1134
+ if (conflict.remoteBlock.updatedAt > conflict.localBlock.updatedAt) {
1135
+ mergedBlock.author = `${conflict.remoteBlock.author}+${conflict.localBlock.author}`;
1136
+ } else {
1137
+ mergedBlock.author = `${conflict.localBlock.author}+${conflict.remoteBlock.author}`;
1138
+ }
1139
+ break;
1140
+ case "longest":
1141
+ if (conflict.remoteBlock.entries.length > conflict.localBlock.entries.length) {
1142
+ mergedBlock.author = `${conflict.remoteBlock.author}+${conflict.localBlock.author}`;
1143
+ } else {
1144
+ mergedBlock.author = `${conflict.localBlock.author}+${conflict.remoteBlock.author}`;
1145
+ }
1146
+ break;
927
1147
  case "manual":
928
- return { ...conflict.localBlock, conflictResolved: false };
929
1148
  default:
930
- return conflict.localBlock;
1149
+ mergedBlock.author = `${conflict.localBlock.author}+${conflict.remoteBlock.author}`;
1150
+ break;
931
1151
  }
1152
+ return mergedBlock;
932
1153
  }
933
1154
  function mergeBlockEntries(localBlock, remoteBlock) {
934
1155
  const entryMap = /* @__PURE__ */ new Map();
@@ -959,7 +1180,7 @@ function mergeBlockEntries(localBlock, remoteBlock) {
959
1180
  async function migrateLegacyLedger(workDir) {
960
1181
  const projectDir = workDir || getWorkingDirectory(void 0, true);
961
1182
  const legacyLedgerPath = join3(getTrieDirectory(projectDir), "memory", LEDGER_FILENAME);
962
- if (!existsSync4(legacyLedgerPath)) {
1183
+ if (!existsSync5(legacyLedgerPath)) {
963
1184
  return false;
964
1185
  }
965
1186
  try {
@@ -994,7 +1215,7 @@ async function migrateLegacyLedger(workDir) {
994
1215
  async function detectLegacyLedger(workDir) {
995
1216
  const projectDir = workDir || getWorkingDirectory(void 0, true);
996
1217
  const legacyLedgerPath = join3(getTrieDirectory(projectDir), "memory", LEDGER_FILENAME);
997
- if (!existsSync4(legacyLedgerPath)) {
1218
+ if (!existsSync5(legacyLedgerPath)) {
998
1219
  return false;
999
1220
  }
1000
1221
  try {
@@ -1047,7 +1268,7 @@ async function compressOldBlocks(workDir) {
1047
1268
  }
1048
1269
  for (const [monthKey, blockFiles] of blocksByMonth) {
1049
1270
  const archivePath = join3(archivedDir, `${monthKey}.tar.gz`);
1050
- if (existsSync4(archivePath)) {
1271
+ if (existsSync5(archivePath)) {
1051
1272
  continue;
1052
1273
  }
1053
1274
  console.log(`Archiving ${blockFiles.length} blocks for ${monthKey}...`);
@@ -1055,9 +1276,9 @@ async function compressOldBlocks(workDir) {
1055
1276
  for (const blockFile of blockFiles) {
1056
1277
  const blockPath = join3(activeDir, blockFile);
1057
1278
  try {
1058
- const stats = await stat(blockPath);
1279
+ const stats = await stat2(blockPath);
1059
1280
  originalSize += stats.size;
1060
- const content = await readFile(blockPath, "utf-8");
1281
+ const content = await readFile2(blockPath, "utf-8");
1061
1282
  const block = JSON.parse(content);
1062
1283
  monthlyBlocks.push(block);
1063
1284
  } catch (error) {
@@ -1072,13 +1293,13 @@ async function compressOldBlocks(workDir) {
1072
1293
  createGzip({ level: manifest.compressionConfig.compressionLevel }),
1073
1294
  createWriteStream(tempPath)
1074
1295
  );
1075
- const compressedStats = await stat(tempPath);
1296
+ const compressedStats = await stat2(tempPath);
1076
1297
  compressedSize += compressedStats.size;
1077
- await writeFile(archivePath, await readFile(tempPath));
1078
- await unlink(tempPath);
1298
+ await writeFile(archivePath, await readFile2(tempPath));
1299
+ await unlink2(tempPath);
1079
1300
  for (const blockFile of blockFiles) {
1080
1301
  const blockPath = join3(activeDir, blockFile);
1081
- await unlink(blockPath);
1302
+ await unlink2(blockPath);
1082
1303
  const index = manifest.activeBlocks.indexOf(blockFile);
1083
1304
  if (index > -1) {
1084
1305
  manifest.activeBlocks.splice(index, 1);
@@ -1099,7 +1320,7 @@ async function compressOldBlocks(workDir) {
1099
1320
  async function loadArchivedBlocks(projectDir, monthKey) {
1100
1321
  const archivedDir = getArchivedBlocksDir(projectDir);
1101
1322
  const archivePath = join3(archivedDir, `${monthKey}.tar.gz`);
1102
- if (!existsSync4(archivePath)) {
1323
+ if (!existsSync5(archivePath)) {
1103
1324
  return [];
1104
1325
  }
1105
1326
  try {
@@ -1141,8 +1362,8 @@ async function getStorageStats(workDir) {
1141
1362
  for (const blockFile of manifest.activeBlocks) {
1142
1363
  const blockPath = join3(activeDir, blockFile);
1143
1364
  try {
1144
- if (existsSync4(blockPath)) {
1145
- const stats = await stat(blockPath);
1365
+ if (existsSync5(blockPath)) {
1366
+ const stats = await stat2(blockPath);
1146
1367
  activeSize += stats.size;
1147
1368
  }
1148
1369
  } catch {
@@ -1151,8 +1372,8 @@ async function getStorageStats(workDir) {
1151
1372
  for (const archiveFile of manifest.archivedBlocks) {
1152
1373
  const archivePath = join3(archivedDir, archiveFile);
1153
1374
  try {
1154
- if (existsSync4(archivePath)) {
1155
- const stats = await stat(archivePath);
1375
+ if (existsSync5(archivePath)) {
1376
+ const stats = await stat2(archivePath);
1156
1377
  archivedSize += stats.size;
1157
1378
  }
1158
1379
  } catch {
@@ -1201,94 +1422,100 @@ async function correctLedgerEntries(entryIds, reason, correctionType = "correcte
1201
1422
  };
1202
1423
  }
1203
1424
  const projectDir = workDir || getWorkingDirectory(void 0, true);
1204
- const blocks = await loadLedger(projectDir);
1205
- const entriesToCorrect = [];
1206
- for (const block of blocks) {
1207
- for (const entry of block.entries) {
1208
- if (entryIds.includes(entry.id) && entry.status === "active") {
1209
- entriesToCorrect.push(entry);
1210
- }
1211
- }
1212
- }
1213
- if (entriesToCorrect.length === 0) {
1214
- return {
1215
- success: false,
1216
- correctedEntries: 0,
1217
- error: "No active entries found with the provided IDs"
1218
- };
1219
- }
1220
- try {
1221
- const now = (/* @__PURE__ */ new Date()).toISOString();
1222
- const isRepo = await isGitRepo(projectDir);
1223
- const lastCommit = isRepo ? await getLastCommit(projectDir) : null;
1224
- const correctionAuthor = author || lastCommit?.author || "unknown";
1225
- const correctionEntries = entriesToCorrect.map((entry) => {
1226
- const correctionId = `correction-${entry.id}-${Date.now()}`;
1227
- return {
1228
- id: correctionId,
1229
- hash: sha256(`${correctionId}:${entry.hash}:${reason}:${now}`),
1230
- severity: "info",
1231
- file: entry.file,
1232
- agent: "ledger-correction",
1233
- timestamp: now,
1234
- status: "active",
1235
- correction: `Correcting entry ${entry.id}: ${reason}`,
1236
- correctedBy: entry.id
1237
- };
1238
- });
1425
+ const memoryDir = join3(getTrieDirectory(projectDir), "memory");
1426
+ const ledgerPath = join3(memoryDir, LEDGER_FILENAME);
1427
+ return withFileLock(ledgerPath, async () => {
1428
+ const blocks = await loadLedger(projectDir);
1429
+ const entriesToCorrect = [];
1239
1430
  for (const block of blocks) {
1240
- let blockModified = false;
1241
1431
  for (const entry of block.entries) {
1242
1432
  if (entryIds.includes(entry.id) && entry.status === "active") {
1243
- entry.status = correctionType;
1244
- entry.correctionTimestamp = now;
1245
- entry.correction = reason;
1246
- blockModified = true;
1433
+ entriesToCorrect.push(entry);
1247
1434
  }
1248
1435
  }
1249
- if (blockModified) {
1250
- block.merkleRoot = computeMerkleRoot(block.entries.map((e) => e.hash));
1251
- block.blockHash = computeBlockHash(
1252
- block.previousHash,
1253
- block.merkleRoot,
1254
- block.date,
1255
- block.version
1256
- );
1257
- block.updatedAt = now;
1436
+ }
1437
+ if (entriesToCorrect.length === 0) {
1438
+ return {
1439
+ success: false,
1440
+ correctedEntries: 0,
1441
+ error: "No active entries found with the provided IDs"
1442
+ };
1443
+ }
1444
+ try {
1445
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1446
+ const isRepo = await isGitRepo(projectDir);
1447
+ const lastCommit = isRepo ? await getLastCommit(projectDir) : null;
1448
+ const correctionAuthor = author || lastCommit?.author || "unknown";
1449
+ const correctionEntries = entriesToCorrect.map((entry) => {
1450
+ const correctionId = `correction-${entry.id}-${Date.now()}`;
1451
+ return {
1452
+ id: correctionId,
1453
+ hash: sha256(`${correctionId}:${entry.hash}:${reason}:${now}`),
1454
+ severity: "info",
1455
+ file: entry.file,
1456
+ agent: "ledger-correction",
1457
+ timestamp: now,
1458
+ status: "active",
1459
+ correction: `Correcting entry ${entry.id}: ${reason}`,
1460
+ correctedBy: entry.id
1461
+ };
1462
+ });
1463
+ for (const block of blocks) {
1464
+ let blockModified = false;
1465
+ for (const entry of block.entries) {
1466
+ if (entryIds.includes(entry.id) && entry.status === "active") {
1467
+ entry.status = correctionType;
1468
+ entry.correctionTimestamp = now;
1469
+ entry.correction = reason;
1470
+ blockModified = true;
1471
+ }
1472
+ }
1473
+ if (blockModified) {
1474
+ block.merkleRoot = computeMerkleRoot(block.entries.map((e) => e.hash));
1475
+ block.blockHash = computeBlockHash(
1476
+ block.previousHash,
1477
+ block.merkleRoot,
1478
+ block.date,
1479
+ block.version
1480
+ );
1481
+ block.updatedAt = now;
1482
+ }
1258
1483
  }
1484
+ await saveLedgerInternal(blocks, projectDir);
1485
+ const correctionBlock = await appendCorrectionEntries(
1486
+ correctionEntries,
1487
+ projectDir,
1488
+ correctionAuthor
1489
+ );
1490
+ return {
1491
+ success: true,
1492
+ correctedEntries: entriesToCorrect.length,
1493
+ ...correctionBlock && { correctionBlock }
1494
+ };
1495
+ } catch (error) {
1496
+ return {
1497
+ success: false,
1498
+ correctedEntries: 0,
1499
+ error: `Failed to correct entries: ${error instanceof Error ? error.message : "Unknown error"}`
1500
+ };
1259
1501
  }
1260
- await saveLedger(blocks, projectDir);
1261
- const correctionBlock = await appendIssuesToLedger(
1262
- correctionEntries.map((entry) => ({
1263
- id: entry.id,
1264
- hash: entry.hash,
1265
- severity: entry.severity,
1266
- issue: entry.correction || "",
1267
- fix: "",
1268
- file: entry.file,
1269
- line: 0,
1270
- agent: entry.agent,
1271
- category: "correction",
1272
- timestamp: entry.timestamp,
1273
- project: "",
1274
- resolved: false,
1275
- resolvedAt: void 0
1276
- })),
1277
- projectDir,
1278
- correctionAuthor
1279
- );
1280
- return {
1281
- success: true,
1282
- correctedEntries: entriesToCorrect.length,
1283
- ...correctionBlock && { correctionBlock }
1284
- };
1285
- } catch (error) {
1286
- return {
1287
- success: false,
1288
- correctedEntries: 0,
1289
- error: `Failed to correct entries: ${error instanceof Error ? error.message : "Unknown error"}`
1290
- };
1502
+ }, { timeout: 15e3 });
1503
+ }
1504
+ async function appendCorrectionEntries(correctionEntries, projectDir, author) {
1505
+ const blocks = await loadLedger(projectDir);
1506
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
1507
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1508
+ const previousBlock = blocks[blocks.length - 1];
1509
+ const block = previousBlock && previousBlock.date === today ? previousBlock : createSyncableBlock(today, now, previousBlock?.blockHash ?? GENESIS_HASH, author, void 0, blocks.length);
1510
+ if (block !== previousBlock) {
1511
+ blocks.push(block);
1291
1512
  }
1513
+ block.entries = [...block.entries, ...correctionEntries];
1514
+ block.merkleRoot = computeMerkleRoot(block.entries.map((entry) => entry.hash));
1515
+ block.blockHash = computeBlockHash(block.previousHash, block.merkleRoot, block.date, block.version);
1516
+ block.updatedAt = now;
1517
+ await saveLedgerInternal(blocks, projectDir);
1518
+ return block;
1292
1519
  }
1293
1520
  async function getLedgerEntries(workDir, includeStatus) {
1294
1521
  const projectDir = workDir || getWorkingDirectory(void 0, true);
@@ -1355,6 +1582,7 @@ async function getCorrectionStats(workDir) {
1355
1582
  }
1356
1583
 
1357
1584
  export {
1585
+ withFileLock,
1358
1586
  formatAuditLog,
1359
1587
  getAuditStatistics,
1360
1588
  getRecentAuditLogs,
@@ -1367,6 +1595,12 @@ export {
1367
1595
  getWorkingTreeDiff,
1368
1596
  isGitRepo,
1369
1597
  getChangedFilesSinceTimestamp,
1598
+ generateKeyPair,
1599
+ saveKeyPair,
1600
+ loadKeyPair,
1601
+ getPublicKey,
1602
+ hasSigningKey,
1603
+ ConcurrentModificationError,
1370
1604
  signLedgerEntry,
1371
1605
  verifyLedgerEntry,
1372
1606
  verifyBlockSignatures,
@@ -1374,6 +1608,8 @@ export {
1374
1608
  verifyLedger,
1375
1609
  computeMerkleRoot,
1376
1610
  getLedgerBlocks,
1611
+ getLedgerBlocksWithHash,
1612
+ saveLedgerOptimistic,
1377
1613
  initializeSharedLedger,
1378
1614
  syncLedgerFromShared,
1379
1615
  pushLedgerToShared,
@@ -1389,4 +1625,4 @@ export {
1389
1625
  getEntryCorrectionHistory,
1390
1626
  getCorrectionStats
1391
1627
  };
1392
- //# sourceMappingURL=chunk-Y4B3VEL7.js.map
1628
+ //# sourceMappingURL=chunk-MVVPJ73K.js.map