@almadar/workspace 0.11.4 → 0.11.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.d.ts CHANGED
@@ -10,6 +10,7 @@ export { openWorkspace } from './open-workspace.js';
10
10
  export { listWorkspaces } from './list-workspaces.js';
11
11
  export { deleteWorkspace } from './delete-workspace.js';
12
12
  export { openAccount } from './account.js';
13
- export type { WorkspaceService, InstantiateWorkspaceSeed, WorkspaceObserver, WorkspaceWriteEvent, WorkspaceWatchEvent, OpenWorkspaceOptions, ListWorkspacesOptions, WorkspaceSummary, RestoreBackend, GitHubConfig, GitStatusInfo, SnapshotMeta, WorkspaceArchiveBackend, FileTreeNode, AccountService, AccountConfig, ProviderCredential, AuthToken, AccountIdentity, OpenAccountOptions, } from './types.js';
14
- export type { WorkspaceIndex, EmbedderPort, ResolveResult, ResolveOptions, TraitRefEmit, WorkspaceIndexStats, OrbitalIndexEntry, ExtraTraitIdentity, RetrievalResult, RetrievalOptions, RecentlyEditedOptions, EventEdge, EntityBinding, RuleBinding, RecencyEntry, IntentMaps, ComposedMaps, BM25Document, BM25Table, BM25Options, WorkspaceIndexManifest, } from './workspace-index/types.js';
15
- export { DEFAULT_COERCION_THRESHOLD, DEFAULT_RETRIEVAL_TOP_K, RRF_K, WORKSPACE_INDEX_SCHEMA_VERSION, } from './workspace-index/types.js';
13
+ export type { WorkspaceService, InstantiateWorkspaceSeed, WorkspaceObserver, WorkspaceWriteEvent, WorkspaceWatchEvent, OpenWorkspaceOptions, MountEntry, ListWorkspacesOptions, WorkspaceSummary, RestoreBackend, GitHubConfig, GitStatusInfo, SnapshotMeta, WorkspaceArchiveBackend, FileTreeNode, AccountService, AccountConfig, ProviderCredential, AuthToken, AccountIdentity, OpenAccountOptions, } from './types.js';
14
+ export type { WorkspaceIndex, EmbedderPort, WorkspaceIndexStats, OrbitalIndexEntry, ExtraTraitIdentity, RetrievalResult, RetrievalOptions, RecentlyEditedOptions, EventEdge, EntityBinding, RuleBinding, RecencyEntry, IntentMaps, ComposedMaps, BM25Document, BM25Table, BM25Options, WorkspaceIndexManifest, } from './workspace-index/types.js';
15
+ export { DEFAULT_RETRIEVAL_TOP_K, RRF_K, WORKSPACE_INDEX_SCHEMA_VERSION, } from './workspace-index/types.js';
16
+ export type { WorkspaceLedger } from './workspace-ledger/types.js';
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ import fs, { existsSync } from 'fs';
3
3
  import { execFile } from 'child_process';
4
4
  import dugite from 'dugite';
5
5
  import { randomBytes, createHash } from 'crypto';
6
+ import { ledgerResolveName, mintId, ledgerRename, ledgerCurName, IdentityLedgerSchema } from '@almadar/core';
6
7
  import { EmbeddingClient } from '@almadar/llm';
7
8
  import os from 'os';
8
9
 
@@ -22,6 +23,10 @@ var LocalBackend = class {
22
23
  fs.mkdirSync(path2.dirname(absPath), { recursive: true });
23
24
  fs.writeFileSync(absPath, content, "utf-8");
24
25
  }
26
+ async appendFile(absPath, content) {
27
+ await fs.promises.mkdir(path2.dirname(absPath), { recursive: true });
28
+ await fs.promises.appendFile(absPath, content, "utf-8");
29
+ }
25
30
  async readFileBytes(absPath) {
26
31
  return fs.promises.readFile(absPath);
27
32
  }
@@ -102,6 +107,9 @@ var MemoryBackend = class {
102
107
  writeFileSync(absPath, content) {
103
108
  this.files.set(absPath, content);
104
109
  }
110
+ async appendFile(absPath, content) {
111
+ this.files.set(absPath, (this.files.get(absPath) ?? "") + content);
112
+ }
105
113
  async readFileBytes(absPath) {
106
114
  const b = this.bytes.get(absPath);
107
115
  if (b === void 0) throw new Error(`ENOENT: ${absPath}`);
@@ -293,7 +301,10 @@ function appMarkerFile(workDir) {
293
301
  function workspaceIndexManifestFile(workDir) {
294
302
  return path2.join(workDir, WORKSPACE_LAYOUT.ALMADAR_DIR, "index.json");
295
303
  }
296
- function sandboxedPath(workDir, relPath) {
304
+ function workspaceLedgerFile(workDir) {
305
+ return path2.join(workDir, WORKSPACE_LAYOUT.ALMADAR_DIR, "ledger.json");
306
+ }
307
+ function sandboxedPath(workDir, relPath, mounts) {
297
308
  if (typeof relPath !== "string" || relPath.length === 0) {
298
309
  throw new Error("sandbox: empty relative path");
299
310
  }
@@ -303,6 +314,20 @@ function sandboxedPath(workDir, relPath) {
303
314
  if (/^[a-zA-Z]:[\\/]/.test(relPath)) {
304
315
  throw new Error(`sandbox: drive-letter paths are not allowed (${relPath})`);
305
316
  }
317
+ if (mounts) {
318
+ for (const [prefix, mountRoot] of mounts) {
319
+ const prefixSep = prefix + "/";
320
+ if (relPath === prefix || relPath.startsWith(prefixSep)) {
321
+ const mountAbs = path2.resolve(mountRoot);
322
+ const rest = relPath === prefix ? "." : relPath.slice(prefixSep.length);
323
+ const target2 = path2.resolve(mountAbs, rest);
324
+ if (target2 !== mountAbs && !target2.startsWith(mountAbs + path2.sep)) {
325
+ throw new Error(`sandbox: mount path escapes mount root (${relPath})`);
326
+ }
327
+ return target2;
328
+ }
329
+ }
330
+ }
306
331
  const rootAbs = path2.resolve(workDir);
307
332
  const target = path2.resolve(rootAbs, relPath);
308
333
  if (target !== rootAbs && !target.startsWith(rootAbs + path2.sep)) {
@@ -662,14 +687,11 @@ async function writeJsonFile(backend, absPath, value) {
662
687
  await backend.writeFile(absPath, JSON.stringify(value, null, 2));
663
688
  }
664
689
  async function appendJsonLine(backend, absPath, value) {
665
- const existing = backend.exists(absPath) ? await backend.readFile(absPath) : "";
666
- const ending = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
667
- await backend.writeFile(absPath, existing + ending + JSON.stringify(value) + "\n");
690
+ await backend.appendFile(absPath, JSON.stringify(value) + "\n");
668
691
  }
669
692
 
670
693
  // src/workspace-index/types.ts
671
694
  var WORKSPACE_INDEX_SCHEMA_VERSION = 2;
672
- var DEFAULT_COERCION_THRESHOLD = 0.85;
673
695
  var RRF_K = 60;
674
696
  var DEFAULT_RETRIEVAL_TOP_K = 3;
675
697
 
@@ -1325,62 +1347,6 @@ var WorkspaceIndexImpl = class {
1325
1347
  }
1326
1348
  await this.rebuildManifest();
1327
1349
  }
1328
- async resolveOrbitalName(name, opts) {
1329
- const threshold = opts?.threshold ?? DEFAULT_COERCION_THRESHOLD;
1330
- if (this.entries.size === 0) {
1331
- return { coercedTo: null, similarity: 0, method: "identity-vector" };
1332
- }
1333
- let vector;
1334
- try {
1335
- [vector] = await this.embedOne(name);
1336
- } catch (err) {
1337
- const reason = err instanceof Error ? err.message : String(err);
1338
- console.warn(`[workspace-index] resolveOrbitalName: embedder failed, returning null (${reason})`);
1339
- return { coercedTo: null, similarity: 0, method: "identity-vector" };
1340
- }
1341
- let bestOrbital = null;
1342
- let bestSim = 0;
1343
- for (const [orbital, entry] of this.entries) {
1344
- const sim = cosineSimilarity(vector, entry.identityVector);
1345
- if (sim > bestSim) {
1346
- bestSim = sim;
1347
- bestOrbital = orbital;
1348
- }
1349
- }
1350
- if (bestOrbital !== null && bestSim >= threshold) {
1351
- return { coercedTo: bestOrbital, similarity: bestSim, method: "identity-vector" };
1352
- }
1353
- return { coercedTo: null, similarity: bestSim, method: "identity-vector" };
1354
- }
1355
- async resolveTraitRef(emit, orbitalContext, opts) {
1356
- const threshold = opts?.threshold ?? DEFAULT_COERCION_THRESHOLD;
1357
- const entry = this.entries.get(orbitalContext.orbitalName);
1358
- if (!entry || entry.extraTraitIdentities.length === 0) {
1359
- return { coercedTo: null, similarity: 0, method: "identity-vector" };
1360
- }
1361
- const fingerprint = composeExtraTraitIdentityFingerprint(emit);
1362
- let vector;
1363
- try {
1364
- [vector] = await this.embedOne(fingerprint);
1365
- } catch (err) {
1366
- const reason = err instanceof Error ? err.message : String(err);
1367
- console.warn(`[workspace-index] resolveTraitRef: embedder failed, returning null (${reason})`);
1368
- return { coercedTo: null, similarity: 0, method: "identity-vector" };
1369
- }
1370
- let bestAlias = null;
1371
- let bestSim = 0;
1372
- for (const candidate of entry.extraTraitIdentities) {
1373
- const sim = cosineSimilarity(vector, candidate.vector);
1374
- if (sim > bestSim) {
1375
- bestSim = sim;
1376
- bestAlias = candidate.alias;
1377
- }
1378
- }
1379
- if (bestAlias !== null && bestSim >= threshold) {
1380
- return { coercedTo: bestAlias, similarity: bestSim, method: "identity-vector" };
1381
- }
1382
- return { coercedTo: null, similarity: bestSim, method: "identity-vector" };
1383
- }
1384
1350
  stats() {
1385
1351
  let extraTraitIdentityCount = 0;
1386
1352
  for (const entry of this.entries.values()) {
@@ -1750,6 +1716,172 @@ function serializeMapOfArrays(map, projectOne) {
1750
1716
  }
1751
1717
  return out;
1752
1718
  }
1719
+ function ledgerPath(workDir) {
1720
+ return workspaceLedgerFile(workDir);
1721
+ }
1722
+ async function readLedger(backend, workDir) {
1723
+ const p = ledgerPath(workDir);
1724
+ if (!backend.exists(p)) return null;
1725
+ try {
1726
+ const raw = await backend.readFile(p);
1727
+ const result = IdentityLedgerSchema.safeParse(JSON.parse(raw));
1728
+ return result.success ? result.data : null;
1729
+ } catch {
1730
+ return null;
1731
+ }
1732
+ }
1733
+ async function writeLedger(backend, workDir, ledger) {
1734
+ await backend.writeFile(ledgerPath(workDir), JSON.stringify(serializeLedger(ledger), null, 2));
1735
+ }
1736
+ function serializeLedger(ledger) {
1737
+ const entries = {};
1738
+ for (const [id, entry] of Object.entries(ledger.entries)) {
1739
+ entries[id] = serializeEntry(entry);
1740
+ }
1741
+ return { schemaVersion: ledger.schemaVersion, entries };
1742
+ }
1743
+ function serializeEntry(entry) {
1744
+ const row = {
1745
+ id: entry.id,
1746
+ kind: entry.kind,
1747
+ bakedName: entry.bakedName,
1748
+ curName: entry.curName,
1749
+ renames: entry.renames.map((r) => ({ from: r.from, to: r.to, at: r.at })),
1750
+ owner: entry.owner
1751
+ };
1752
+ if (entry.parent !== void 0) row.parent = entry.parent;
1753
+ return row;
1754
+ }
1755
+
1756
+ // src/workspace-ledger/ledger-impl.ts
1757
+ var WorkspaceLedgerImpl = class {
1758
+ constructor(deps) {
1759
+ this.deps = deps;
1760
+ this.ledger = emptyLedger();
1761
+ /** Serialized persists so concurrent writes don't race the file. */
1762
+ this.persistQueue = Promise.resolve();
1763
+ this.deps.sinks.subscribe({
1764
+ onWrite: (event) => this.onWorkspaceWrite(event)
1765
+ });
1766
+ }
1767
+ async onWorkspaceWrite(event) {
1768
+ if (event.kind !== "orbital") return;
1769
+ const slice = extractLedgerSlice(event.content);
1770
+ if (slice !== null) {
1771
+ this.ingestOrbSlice(slice);
1772
+ } else if (isJsonObject(event.content) && this.resolve("orbital", event.name) === null) {
1773
+ this.mint("orbital", event.name);
1774
+ }
1775
+ await this.persistQueue;
1776
+ }
1777
+ resolve(kind, name) {
1778
+ return ledgerResolveName(this.ledger, kind, name);
1779
+ }
1780
+ mint(kind, name) {
1781
+ if (kind === "palette") {
1782
+ throw new Error("WorkspaceLedger.mint: palette ids are manifest-owned, not name-ledger rows");
1783
+ }
1784
+ if (this.resolve(kind, name) !== null) {
1785
+ throw new Error(`WorkspaceLedger.mint: duplicate curName "${name}" within kind "${kind}"`);
1786
+ }
1787
+ const id = mintId(kind);
1788
+ const entry = {
1789
+ id,
1790
+ kind,
1791
+ bakedName: name,
1792
+ curName: name,
1793
+ renames: [],
1794
+ owner: "workspace"
1795
+ };
1796
+ this.ledger = { ...this.ledger, entries: { ...this.ledger.entries, [id]: entry } };
1797
+ void this.persist();
1798
+ return id;
1799
+ }
1800
+ rename(id, to, at) {
1801
+ if (this.ledger.entries[id] === void 0) {
1802
+ throw new Error(`WorkspaceLedger.rename: unknown id "${id}"`);
1803
+ }
1804
+ this.ledger = ledgerRename(this.ledger, id, to, String(at));
1805
+ void this.persist();
1806
+ }
1807
+ curName(id) {
1808
+ return ledgerCurName(this.ledger, id);
1809
+ }
1810
+ entry(id) {
1811
+ return this.ledger.entries[id] ?? null;
1812
+ }
1813
+ snapshot() {
1814
+ return cloneLedger(this.ledger);
1815
+ }
1816
+ ingestOrbSlice(slice) {
1817
+ const entries = { ...this.ledger.entries };
1818
+ let changed = false;
1819
+ for (const [id, entry] of Object.entries(slice.entries)) {
1820
+ if (entries[id] === void 0) {
1821
+ entries[id] = entry;
1822
+ changed = true;
1823
+ }
1824
+ }
1825
+ if (!changed) return;
1826
+ this.ledger = { ...this.ledger, entries };
1827
+ void this.persist();
1828
+ }
1829
+ async warm() {
1830
+ const loaded = await readLedger(this.deps.backend, this.deps.workDir);
1831
+ this.ledger = loaded ?? emptyLedger();
1832
+ const names = this.deps.listOrbitals();
1833
+ for (const name of names) {
1834
+ const content = this.deps.readOrbital(name);
1835
+ if (content === null) continue;
1836
+ const slice = extractLedgerSlice(content);
1837
+ if (slice !== null) this.ingestOrbSlice(slice);
1838
+ }
1839
+ for (const name of names) {
1840
+ if (this.resolve("orbital", name) === null) this.mint("orbital", name);
1841
+ }
1842
+ await this.persistQueue;
1843
+ }
1844
+ persist() {
1845
+ const snapshot = this.ledger;
1846
+ const next = this.persistQueue.then(async () => {
1847
+ await writeLedger(this.deps.backend, this.deps.workDir, snapshot);
1848
+ await this.deps.sinks.notifyAll({
1849
+ kind: "workspace-ledger",
1850
+ content: serializeLedger(snapshot)
1851
+ });
1852
+ });
1853
+ this.persistQueue = next.catch(() => void 0);
1854
+ return next;
1855
+ }
1856
+ };
1857
+ function emptyLedger() {
1858
+ return { schemaVersion: 1, entries: {} };
1859
+ }
1860
+ function cloneLedger(ledger) {
1861
+ const entries = {};
1862
+ for (const [id, entry] of Object.entries(ledger.entries)) {
1863
+ entries[id] = { ...entry, renames: entry.renames.map((r) => ({ ...r })) };
1864
+ }
1865
+ return { schemaVersion: ledger.schemaVersion, entries };
1866
+ }
1867
+ function isJsonObject(content) {
1868
+ try {
1869
+ const root = JSON.parse(content);
1870
+ return root !== null && typeof root === "object" && !Array.isArray(root);
1871
+ } catch {
1872
+ return false;
1873
+ }
1874
+ }
1875
+ function extractLedgerSlice(content) {
1876
+ try {
1877
+ const root = JSON.parse(content);
1878
+ if (root === null || typeof root !== "object" || Array.isArray(root)) return null;
1879
+ const result = IdentityLedgerSchema.safeParse(root.ledger);
1880
+ return result.success ? result.data : null;
1881
+ } catch {
1882
+ return null;
1883
+ }
1884
+ }
1753
1885
 
1754
1886
  // src/service.ts
1755
1887
  var COORD_FILES = {
@@ -1770,6 +1902,8 @@ var WorkspaceServiceImpl = class {
1770
1902
  constructor(args) {
1771
1903
  /** Per-absolute-path serial queue. */
1772
1904
  this.writeQueue = /* @__PURE__ */ new Map();
1905
+ /** Mount prefix → resolved absolute directory. Built from constructor `mounts` + runtime `mountReadonly`. */
1906
+ this.mountMap = /* @__PURE__ */ new Map();
1773
1907
  this.workDir = args.workDir;
1774
1908
  this.backend = args.backend;
1775
1909
  this.sinks = args.sinks;
@@ -1787,6 +1921,16 @@ var WorkspaceServiceImpl = class {
1787
1921
  readSchema: () => this.readSchema(),
1788
1922
  readHistory: (orbital) => this.readHistory(orbital)
1789
1923
  });
1924
+ this.ledger = new WorkspaceLedgerImpl({
1925
+ workDir: this.workDir,
1926
+ backend: this.backend,
1927
+ sinks: this.sinks,
1928
+ listOrbitals: () => this.listOrbitals(),
1929
+ readOrbital: (name) => this.readOrbital(name)
1930
+ });
1931
+ if (args.mounts) {
1932
+ for (const m of args.mounts) this.mountMap.set(m.prefix, path2.resolve(m.absPath));
1933
+ }
1790
1934
  }
1791
1935
  // === Identity ===
1792
1936
  get appId() {
@@ -2109,7 +2253,7 @@ var WorkspaceServiceImpl = class {
2109
2253
  }
2110
2254
  // === Sandboxed generic file I/O ===
2111
2255
  async readFile(relPath) {
2112
- const abs = sandboxedPath(this.workDir, relPath);
2256
+ const abs = this.sandbox(relPath);
2113
2257
  if (!this.backend.exists(abs)) return null;
2114
2258
  try {
2115
2259
  return await this.backend.readFile(abs);
@@ -2118,7 +2262,8 @@ var WorkspaceServiceImpl = class {
2118
2262
  }
2119
2263
  }
2120
2264
  async writeFile(relPath, content) {
2121
- const abs = sandboxedPath(this.workDir, relPath);
2265
+ this.assertNotMounted(relPath);
2266
+ const abs = this.sandbox(relPath);
2122
2267
  await this.withLock(abs, async () => {
2123
2268
  await this.ensureParent(abs);
2124
2269
  await this.backend.writeFile(abs, content);
@@ -2126,7 +2271,8 @@ var WorkspaceServiceImpl = class {
2126
2271
  await this.emit({ kind: "file", relPath, content });
2127
2272
  }
2128
2273
  async removeFile(relPath) {
2129
- const abs = sandboxedPath(this.workDir, relPath);
2274
+ this.assertNotMounted(relPath);
2275
+ const abs = this.sandbox(relPath);
2130
2276
  let removed = false;
2131
2277
  await this.withLock(abs, async () => {
2132
2278
  if (!this.backend.exists(abs)) return;
@@ -2136,7 +2282,7 @@ var WorkspaceServiceImpl = class {
2136
2282
  if (removed) await this.emit({ kind: "file-removed", relPath });
2137
2283
  }
2138
2284
  async listTree(relPath) {
2139
- const base = relPath === void 0 ? this.workDir : sandboxedPath(this.workDir, relPath);
2285
+ const base = relPath === void 0 ? this.workDir : this.sandbox(relPath);
2140
2286
  if (!this.backend.exists(base)) return [];
2141
2287
  const out = [];
2142
2288
  await walk(this.backend, base, this.workDir, out);
@@ -2145,12 +2291,39 @@ var WorkspaceServiceImpl = class {
2145
2291
  async exists(relPath) {
2146
2292
  let abs;
2147
2293
  try {
2148
- abs = sandboxedPath(this.workDir, relPath);
2294
+ abs = this.sandbox(relPath);
2149
2295
  } catch {
2150
2296
  return false;
2151
2297
  }
2152
2298
  return this.backend.exists(abs);
2153
2299
  }
2300
+ // === Read-only mounts ===
2301
+ mountReadonly(prefix, absPath) {
2302
+ if (this.mountMap.has(prefix)) {
2303
+ throw new Error(`mount: prefix "${prefix}" already registered`);
2304
+ }
2305
+ this.mountMap.set(prefix, path2.resolve(absPath));
2306
+ }
2307
+ isMounted(relPath) {
2308
+ try {
2309
+ for (const [prefix] of this.mountMap) {
2310
+ if (relPath === prefix || relPath.startsWith(prefix + "/")) return true;
2311
+ }
2312
+ return false;
2313
+ } catch {
2314
+ return false;
2315
+ }
2316
+ }
2317
+ /** Resolve a sandboxed path through mounts. */
2318
+ sandbox(relPath) {
2319
+ return sandboxedPath(this.workDir, relPath, this.mountMap.size > 0 ? this.mountMap : void 0);
2320
+ }
2321
+ /** Throw if relPath resolves to a mount (write/remove are blocked). */
2322
+ assertNotMounted(relPath) {
2323
+ if (this.isMounted(relPath)) {
2324
+ throw new Error(`sandbox: cannot write to read-only mount (${relPath})`);
2325
+ }
2326
+ }
2154
2327
  // === Git ===
2155
2328
  async commitAndPush(opts) {
2156
2329
  if (!this.git) return null;
@@ -2361,6 +2534,25 @@ async function openWorkspace(opts) {
2361
2534
  }
2362
2535
  return openWorkspaceInternal(opts);
2363
2536
  }
2537
+ var WORKSPACE_OWNED_ENTRIES = /* @__PURE__ */ new Set([".almadar", "orbitals", "schema.orb", ".git", ".gitignore"]);
2538
+ async function guardForeignMintTarget(backend, workDir) {
2539
+ if (readAppMarker(backend, workDir) !== null) return;
2540
+ if (backend.exists(path2.join(workDir, "schema.orb"))) return;
2541
+ if (backend.exists(path2.join(workDir, ".almadar", "sessions"))) return;
2542
+ if (!backend.exists(workDir)) return;
2543
+ if (process.env["ALMADAR_WORKSPACE_ADOPT_NONEMPTY"] === "1") return;
2544
+ let entries;
2545
+ try {
2546
+ entries = await backend.readdir(workDir);
2547
+ } catch {
2548
+ return;
2549
+ }
2550
+ const foreign = entries.filter((e) => !WORKSPACE_OWNED_ENTRIES.has(e));
2551
+ if (foreign.length === 0) return;
2552
+ throw new Error(
2553
+ `refusing to mint a workspace into ${workDir} \u2014 it already contains non-workspace content (${foreign.slice(0, 5).join(", ")}${foreign.length > 5 ? ", \u2026" : ""}). Pass an empty/dedicated workDir, or set ALMADAR_WORKSPACE_ADOPT_NONEMPTY=1 to adopt this directory anyway.`
2554
+ );
2555
+ }
2364
2556
  async function openWorkspaceInternal(opts) {
2365
2557
  const backend = opts.backend === "memory" ? new MemoryBackend() : new LocalBackend();
2366
2558
  const sinks = new SinkManager();
@@ -2368,6 +2560,7 @@ async function openWorkspaceInternal(opts) {
2368
2560
  if (resolved === null) return null;
2369
2561
  const bare = opts.bare === true && opts.adopt !== void 0;
2370
2562
  if (!bare) {
2563
+ await guardForeignMintTarget(backend, resolved.workDir);
2371
2564
  await ensureSkeleton(backend, resolved.workDir);
2372
2565
  await writeMintTemplatesIfMissing(
2373
2566
  backend,
@@ -2405,10 +2598,12 @@ async function openWorkspaceInternal(opts) {
2405
2598
  appId: resolved.appId,
2406
2599
  git,
2407
2600
  github: opts.github,
2408
- archiveBackend: opts.archiveBackend
2601
+ archiveBackend: opts.archiveBackend,
2602
+ mounts: opts.mounts
2409
2603
  });
2410
2604
  if (!bare) {
2411
2605
  await service.index.warm();
2606
+ await service.ledger.warm();
2412
2607
  }
2413
2608
  return service;
2414
2609
  }
@@ -2598,6 +2793,6 @@ async function openAccount(opts = {}) {
2598
2793
  };
2599
2794
  }
2600
2795
 
2601
- export { DEFAULT_COERCION_THRESHOLD, DEFAULT_RETRIEVAL_TOP_K, RRF_K, WORKSPACE_INDEX_SCHEMA_VERSION, deleteWorkspace, listWorkspaces, openAccount, openWorkspace };
2796
+ export { DEFAULT_RETRIEVAL_TOP_K, RRF_K, WORKSPACE_INDEX_SCHEMA_VERSION, deleteWorkspace, listWorkspaces, openAccount, openWorkspace };
2602
2797
  //# sourceMappingURL=index.js.map
2603
2798
  //# sourceMappingURL=index.js.map