@mulmoclaude/core 2.1.0 → 3.0.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 (42) hide show
  1. package/dist/collection/registry/server/client.d.ts +4 -4
  2. package/dist/collection/registry/server/collectionFiles.d.ts +3 -2
  3. package/dist/collection/registry/server/importCollection.d.ts +3 -2
  4. package/dist/collection/registry/server/index.cjs +27 -26
  5. package/dist/collection/registry/server/index.cjs.map +1 -1
  6. package/dist/collection/registry/server/index.d.ts +3 -2
  7. package/dist/collection/registry/server/index.js +27 -26
  8. package/dist/collection/registry/server/index.js.map +1 -1
  9. package/dist/collection/registry/server/registriesConfig.d.ts +11 -4
  10. package/dist/collection/server/host.d.ts +42 -5
  11. package/dist/collection/server/index.cjs +5 -3
  12. package/dist/collection/server/index.d.ts +1 -1
  13. package/dist/collection/server/index.js +3 -3
  14. package/dist/collection/server/paths.d.ts +0 -3
  15. package/dist/collection-watchers/index.cjs +79 -12
  16. package/dist/collection-watchers/index.cjs.map +1 -1
  17. package/dist/collection-watchers/index.d.ts +1 -1
  18. package/dist/collection-watchers/index.js +79 -13
  19. package/dist/collection-watchers/index.js.map +1 -1
  20. package/dist/collection-watchers/watcher.d.ts +23 -4
  21. package/dist/{discovery-BvnXyUel.js → discovery-4Z-ZWFam.js} +50 -21
  22. package/dist/discovery-4Z-ZWFam.js.map +1 -0
  23. package/dist/{discovery-B_sHig7n.cjs → discovery-CtiZMlsX.cjs} +67 -26
  24. package/dist/discovery-CtiZMlsX.cjs.map +1 -0
  25. package/dist/feeds/server/index.cjs +2 -2
  26. package/dist/feeds/server/index.js +2 -2
  27. package/dist/google/index.cjs +1 -1
  28. package/dist/google/index.js +1 -1
  29. package/dist/remote-host/server/index.cjs +37 -13
  30. package/dist/remote-host/server/index.cjs.map +1 -1
  31. package/dist/remote-host/server/index.js +37 -13
  32. package/dist/remote-host/server/index.js.map +1 -1
  33. package/dist/remote-host/server/monotonicClock.d.ts +3 -0
  34. package/dist/remote-host/server/presenceBeat.d.ts +3 -2
  35. package/dist/remote-host/server/resilientRunner.d.ts +6 -0
  36. package/dist/{server-DJt6USBQ.js → server-CedIocRS.js} +2 -2
  37. package/dist/{server-DJt6USBQ.js.map → server-CedIocRS.js.map} +1 -1
  38. package/dist/{server-DoyGZMPS.cjs → server-DOZFzx5l.cjs} +2 -2
  39. package/dist/{server-DoyGZMPS.cjs.map → server-DOZFzx5l.cjs.map} +1 -1
  40. package/package.json +1 -1
  41. package/dist/discovery-B_sHig7n.cjs.map +0 -1
  42. package/dist/discovery-BvnXyUel.js.map +0 -1
@@ -42,6 +42,22 @@ function createForwardingLogger(getLogger) {
42
42
  }
43
43
  //#endregion
44
44
  //#region src/collection/server/host.ts
45
+ /** `err.code` on the throw from `getWorkspaceRoot()` under an explicit-root
46
+ * binding: this CALL is missing its `workspaceRoot` option. Exported because
47
+ * the fix differs from a watcher root conflict — that one means another root's
48
+ * watcher is already running — and a host catching both in one place should
49
+ * not have to match on message text to tell them apart. */
50
+ var COLLECTION_ROOT_REQUIRED = "COLLECTION_ROOT_REQUIRED";
51
+ /** Build a change payload, attaching `root` only when the engine call carried
52
+ * an explicit one. Centralised so every publish site states the root the same
53
+ * way, and so a single-workspace host's payload shape stays byte-identical to
54
+ * what it saw before multi-root support. */
55
+ function collectionChangePayload(base, root) {
56
+ return root === void 0 ? base : {
57
+ ...base,
58
+ root
59
+ };
60
+ }
45
61
  var hostSlot = createHostSlot("@mulmoclaude/core/collection/server: configureCollectionHost()");
46
62
  var changePublisher = null;
47
63
  /** Wire the engine to a host. Call once at server startup, before any
@@ -70,9 +86,23 @@ function publishCollectionChange(payload) {
70
86
  function requireHost() {
71
87
  return hostSlot.get();
72
88
  }
73
- /** The configured workspace root. Throws if the host never configured one. */
89
+ /** The configured workspace root. Throws if the host never configured one —
90
+ * and, under an explicit-root binding (`workspaceRoot: null`), throws rather
91
+ * than guessing, which is the whole point of that mode: on a multi-root host
92
+ * a missing `opts.workspaceRoot` must fail loudly instead of silently
93
+ * resolving against some other project. */
74
94
  function getWorkspaceRoot() {
75
- return requireHost().workspaceRoot;
95
+ const root = requireHost().workspaceRoot;
96
+ if (root === null) throw Object.assign(/* @__PURE__ */ new Error("@mulmoclaude/core/collection/server: the host is bound in explicit-root mode (workspaceRoot: null), so there is no ambient workspace root — pass an explicit `workspaceRoot` in this call's options."), { code: COLLECTION_ROOT_REQUIRED });
97
+ return root;
98
+ }
99
+ /** The configured workspace root, or `null` under an explicit-root binding /
100
+ * before the host configures one. Never throws — for callers that need to
101
+ * COMPARE roots (is this the one we are already running for?) rather than
102
+ * operate on one. Anything that will touch the filesystem wants
103
+ * `getWorkspaceRoot()` and its loud failure instead. */
104
+ function peekWorkspaceRoot() {
105
+ return hostSlot.peek()?.workspaceRoot ?? null;
76
106
  }
77
107
  function userSkillsDir() {
78
108
  return requireHost().paths.userSkillsDir;
@@ -89,10 +119,11 @@ function skillsStagingDir(workspaceRoot) {
89
119
  function archiveDir() {
90
120
  return requireHost().paths.archiveDir;
91
121
  }
92
- /** Absolute path to the configured workspace's `collections-registries.json`. */
93
- function collectionsRegistriesConfigPath() {
94
- const host = requireHost();
95
- return host.paths.collectionsRegistriesConfig(host.workspaceRoot);
122
+ /** Absolute path to a workspace's `collections-registries.json`. Takes the
123
+ * root explicitly — reading the ambient one here would throw under an
124
+ * explicit-root binding and take the Discover tab down with it. */
125
+ function collectionsRegistriesConfigPath(workspaceRoot) {
126
+ return requireHost().paths.collectionsRegistriesConfig(workspaceRoot);
96
127
  }
97
128
  function isPresetSlug(slug) {
98
129
  return requireHost().isPresetSlug(slug);
@@ -171,11 +202,6 @@ function isContainedInRoot(absPath, rootPath) {
171
202
  if (ancestorReal === rootReal) return true;
172
203
  return ancestorReal.startsWith(rootReal + path.sep);
173
204
  }
174
- /** Workspace-bound convenience over `isContainedInRoot`. Production
175
- * callers use this; the tests exercise the pure helper. */
176
- function isContainedInWorkspace(absPath) {
177
- return isContainedInRoot(absPath, getWorkspaceRoot());
178
- }
179
205
  /** Resolve a schema-declared dataPath against `rootPath` (default:
180
206
  * the live workspace), refusing anything that escapes — absolute
181
207
  * paths, `..`-segments, empty string, or symlinks pointing outside
@@ -383,11 +409,11 @@ async function writeItem(dataDir, itemId, item, opts = {}) {
383
409
  await handle.close();
384
410
  }
385
411
  } else await writeFileAtomic(filePath, payload);
386
- if (opts.slug) publishCollectionChange({
412
+ if (opts.slug) publishCollectionChange(collectionChangePayload({
387
413
  slug: opts.slug,
388
414
  ids: [safeId],
389
415
  op: "upsert"
390
- });
416
+ }, opts.workspaceRoot));
391
417
  return {
392
418
  kind: "ok",
393
419
  itemId: safeId,
@@ -407,11 +433,11 @@ async function deleteItem(dataDir, itemId, opts = {}) {
407
433
  const filePath = itemFilePath(dataDir, safeId);
408
434
  try {
409
435
  await unlink(filePath);
410
- if (opts.slug) publishCollectionChange({
436
+ if (opts.slug) publishCollectionChange(collectionChangePayload({
411
437
  slug: opts.slug,
412
438
  ids: [safeId],
413
439
  op: "delete"
414
- });
440
+ }, opts.workspaceRoot));
415
441
  return {
416
442
  kind: "ok",
417
443
  itemId: safeId
@@ -1237,11 +1263,11 @@ async function sqliteWrite(absPath, itemId, item, opts) {
1237
1263
  item
1238
1264
  };
1239
1265
  });
1240
- if (outcome.kind === "ok" && opts.slug) publishCollectionChange({
1266
+ if (outcome.kind === "ok" && opts.slug) publishCollectionChange(collectionChangePayload({
1241
1267
  slug: opts.slug,
1242
1268
  ids: [safeId],
1243
1269
  op: "upsert"
1244
- });
1270
+ }, opts.publishRoot));
1245
1271
  return outcome;
1246
1272
  }
1247
1273
  async function sqliteDelete(absPath, itemId, opts) {
@@ -1266,11 +1292,11 @@ async function sqliteDelete(absPath, itemId, opts) {
1266
1292
  itemId: safeId
1267
1293
  };
1268
1294
  });
1269
- if (outcome.kind === "ok" && opts.slug) publishCollectionChange({
1295
+ if (outcome.kind === "ok" && opts.slug) publishCollectionChange(collectionChangePayload({
1270
1296
  slug: opts.slug,
1271
1297
  ids: [safeId],
1272
1298
  op: "delete"
1273
- });
1299
+ }, opts.publishRoot));
1274
1300
  return outcome;
1275
1301
  }
1276
1302
  /** Best-effort full WAL checkpoint so the MAIN db file alone is a
@@ -1301,6 +1327,7 @@ function sqliteStoreFor(collection, opts) {
1301
1327
  const key = collection.schema.primaryKey;
1302
1328
  const slug = opts.slug ?? collection.slug;
1303
1329
  const root = () => opts.workspaceRoot ?? getWorkspaceRoot();
1330
+ const publishRoot = opts.workspaceRoot;
1304
1331
  if (file === void 0) return {
1305
1332
  capabilities: {
1306
1333
  writable: false,
@@ -1326,11 +1353,13 @@ function sqliteStoreFor(collection, opts) {
1326
1353
  read: (itemId) => sqliteRead(file, itemId, root()),
1327
1354
  write: (itemId, item, writeOpts = {}) => sqliteWrite(file, itemId, item, {
1328
1355
  workspaceRoot: root(),
1356
+ publishRoot,
1329
1357
  slug,
1330
1358
  refuseOverwrite: writeOpts.refuseOverwrite
1331
1359
  }),
1332
1360
  delete: (itemId) => sqliteDelete(file, itemId, {
1333
1361
  workspaceRoot: root(),
1362
+ publishRoot,
1334
1363
  slug
1335
1364
  }),
1336
1365
  watch: async (onChange) => closerFor(await watchSingleFile(file, (base, name) => name.startsWith(base), () => onChange({ kind: "collection" })))
@@ -2721,6 +2750,6 @@ function toDetail(collection) {
2721
2750
  };
2722
2751
  }
2723
2752
  //#endregion
2724
- export { skillsStagingDir as $, deleteItem as A, itemFilePath as B, compileCsvQuery as C, MAX_QUERY_ROWS as D, DEFAULT_QUERY_ROWS as E, resolveCreateItemId as F, archiveDir as G, resolveTemplatePath as H, writeItem as I, getWorkspaceRoot as J, collectionsRegistriesConfigPath as K, SCHEMA_FILE as L, isRegularFile as M, listItems as N, BackendUnavailableError as O, readItem as P, setCollectionChangePublisher as Q, isContainedInRoot as R, queryCsv as S, CollectionQueryZ as T, safeRecordId as U, resolveDataDir as V, safeSlugName as W, log as X, isPresetSlug as Y, publishCollectionChange as Z, csvRowToItem as _, toDetail as a, encodeCsvRecordId as b, resolveMutateSet as c, storeFor as d, createForwardingLogger as et, checkpointSqliteDatabase as f, cacheDir as g, MAX_CSV_ROWS as h, resolvePrimaryField as i, generateItemId as j, isBackendUnavailable as k, collectionWritable as l, projectItemFields as m, discoverCollections as n, toSummary as o, pageFromFullRead as p, configureCollectionHost as q, loadCollection as r, CollectionSchemaZ as s, acceptParsedSchema as t, createHostSlot as tt, readOnlyRefusal as u, decodeCsvRecordId as v, compileJsonlQuery as w, normalizeCsvValue as x, dedupeByRecordId as y, isContainedInWorkspace as z };
2753
+ export { publishCollectionChange as $, deleteItem as A, resolveDataDir as B, compileCsvQuery as C, MAX_QUERY_ROWS as D, DEFAULT_QUERY_ROWS as E, resolveCreateItemId as F, archiveDir as G, safeRecordId as H, writeItem as I, configureCollectionHost as J, collectionChangePayload as K, SCHEMA_FILE as L, isRegularFile as M, listItems as N, BackendUnavailableError as O, readItem as P, peekWorkspaceRoot as Q, isContainedInRoot as R, queryCsv as S, CollectionQueryZ as T, safeSlugName as U, resolveTemplatePath as V, COLLECTION_ROOT_REQUIRED as W, isPresetSlug as X, getWorkspaceRoot as Y, log as Z, csvRowToItem as _, toDetail as a, encodeCsvRecordId as b, resolveMutateSet as c, storeFor as d, setCollectionChangePublisher as et, checkpointSqliteDatabase as f, cacheDir as g, MAX_CSV_ROWS as h, resolvePrimaryField as i, generateItemId as j, isBackendUnavailable as k, collectionWritable as l, projectItemFields as m, discoverCollections as n, createForwardingLogger as nt, toSummary as o, pageFromFullRead as p, collectionsRegistriesConfigPath as q, loadCollection as r, createHostSlot as rt, CollectionSchemaZ as s, acceptParsedSchema as t, skillsStagingDir as tt, readOnlyRefusal as u, decodeCsvRecordId as v, compileJsonlQuery as w, normalizeCsvValue as x, dedupeByRecordId as y, itemFilePath as z };
2725
2754
 
2726
- //# sourceMappingURL=discovery-BvnXyUel.js.map
2755
+ //# sourceMappingURL=discovery-4Z-ZWFam.js.map