@mulmoclaude/mulmoscript-plugin 4.5.0 → 4.5.2

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.
package/dist/server.js CHANGED
@@ -18,6 +18,29 @@ async function fileToDataUri(filePath, mimeType) {
18
18
  return `data:${mimeType};base64,${(await readFile(filePath)).toString("base64")}`;
19
19
  }
20
20
  //#endregion
21
+ //#region src/server/types.ts
22
+ /**
23
+ * Host capabilities the server ops run against. Only genuinely
24
+ * host-specific transport lives here — the mulmocast orchestration, path
25
+ * containment, and generation-state tracking are all in-package.
26
+ */
27
+ /**
28
+ * Which named-root capabilities a host has NOT wired.
29
+ *
30
+ * Pure and exported so the rule can be tested without building a server: the
31
+ * condition used to key on the root COUNT alone, so a host that HAD passed
32
+ * `artifactsFor` was told at every boot that its writes land in the default
33
+ * root — the opposite of what the code then did (#3022).
34
+ *
35
+ * Reads and uploads need nothing from the host, so they never appear here.
36
+ */
37
+ function missingRootCapabilities(backend) {
38
+ const missing = [];
39
+ if (backend.rootScopedGenerationState !== true) missing.push("GENERATION is refused until this host declares `rootScopedGenerationState` (its pending-generation state must carry the root, or it must keep none)");
40
+ if (backend.artifactsFor === void 0) missing.push("save/update land in the DEFAULT root until this host passes `artifactsFor`");
41
+ return missing;
42
+ }
43
+ //#endregion
21
44
  //#region src/server/mulmoErrorCapture.ts
22
45
  var capturedErrors = new AsyncLocalStorage();
23
46
  var loggerInstalled = false;
@@ -194,7 +217,29 @@ function createMulmoScriptServerOps(backend) {
194
217
  if (rootDirs.has(trimmed)) throw new Error(`mulmoScript: extraRoots keys must be distinct after trimming — "${trimmed}" is registered twice`);
195
218
  rootDirs.set(trimmed, path.resolve(dir));
196
219
  }
197
- if (rootDirs.size > 1) log.warn(backend.rootScopedGenerationState === true ? "extra stories roots registered — reads, uploads and generation work; save/update still land in the DEFAULT root until this host passes `artifactsFor` (#3019)" : "extra stories roots registered — reads and uploads work, but GENERATION is refused until this host declares `rootScopedGenerationState` (its pending-generation state must carry the root, or it must keep none), and save/update land in the DEFAULT root until it passes `artifactsFor` (#3019)", { roots: [...rootDirs.keys()].filter((id) => id !== "") });
220
+ warnAboutUnwiredRoots();
221
+ /**
222
+ * Tell a host which named-root capabilities it has not wired — and nothing
223
+ * when it has wired them all.
224
+ *
225
+ * The condition used to be the root COUNT alone, so a host that had passed
226
+ * `artifactsFor` was still told, at every boot, that its writes land in the
227
+ * default root. That is not a stale wording: it is the opposite of what the
228
+ * code then does, read by the hosts that got the wiring RIGHT (#3022, from
229
+ * the consuming host).
230
+ *
231
+ * Silence when nothing is missing, because a warning that always fires is
232
+ * one people learn to skip — and then the host that really did forget
233
+ * `artifactsFor` cannot tell either. Each clause is emitted only when that
234
+ * capability is actually absent, so the message says what is true for THIS
235
+ * host rather than what was true when it was written.
236
+ */
237
+ function warnAboutUnwiredRoots() {
238
+ if (rootDirs.size <= 1) return;
239
+ const missing = missingRootCapabilities(backend);
240
+ if (missing.length === 0) return;
241
+ log.warn(`extra stories roots registered — reads and uploads work, but ${missing.join(", and ")} (#3019)`, { roots: [...rootDirs.keys()].filter((id) => id !== "") });
242
+ }
198
243
  /** The registered directory for a wire `root`, or null when the host never
199
244
  * registered it. Null is a REJECTION, not a fallback to the default: an
200
245
  * unknown root must not quietly read the workspace's file of the same
@@ -335,12 +380,21 @@ function createMulmoScriptServerOps(backend) {
335
380
  * It opens per root, not globally: the host answers `artifactsFor` for the
336
381
  * roots it can serve, and a root it cannot is still refused. A host that
337
382
  * wires nothing keeps the shipped refusal (#3019).
383
+ *
384
+ * The two refusals say different things because they are fixed in different
385
+ * places. No `artifactsFor` at all is a capability this host has not turned
386
+ * on. `artifactsFor` present but answering `null` for a REGISTERED root is a
387
+ * wiring mistake inside that host — and it is the quiet one, because the
388
+ * boot warning stays silent (the resolver WAS passed) while every write is
389
+ * refused. One message for both read as "the plugin cannot do this yet",
390
+ * which sends the host looking in the wrong place (#3024).
338
391
  */
339
392
  function guardStoryWriteRoot(root) {
340
393
  if (normalizeRoot(root) === "") return null;
341
394
  const registered = guardStoryRootRegistered(root);
342
395
  if (registered) return registered;
343
- return artifactsForRoot(root) === null ? opBadRequest("writing to a non-default stories root is not supported yet") : null;
396
+ if (artifactsForRoot(root) !== null) return null;
397
+ return backend.artifactsFor === void 0 ? opBadRequest("writing to a non-default stories root is not supported yet") : opBadRequest(`this host's \`artifactsFor\` returned no FileOps for the registered stories root "${normalizeRoot(root)}"`);
344
398
  }
345
399
  /**
346
400
  * The FileOps a write to this root must go through.