@mulmoclaude/core 5.7.0 → 5.7.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.
@@ -584,6 +584,28 @@ guide it returns says `data/skills/`, this root does have a bridge and the
584
584
  problem is something else — check that `schema.json` passed validation (a
585
585
  schema that fails is silently skipped at discovery).
586
586
 
587
+ ## A `schema.json` change is not reflected — it was written with Bash or a script
588
+
589
+ You changed `data/skills/<slug>/schema.json`, and `getSchema` shows the new
590
+ content, but the collection still behaves as before — the old fields, a missing
591
+ view, or a 404. No tool reported an error.
592
+
593
+ ### Why
594
+
595
+ The server runs `.claude/skills/<slug>/schema.json`, not the staging copy. The
596
+ skill-bridge hook copies staging files across only when they are written with
597
+ the **Write / Edit** tools. A `schema.json` written through Bash (`cat >`,
598
+ `sed -i`, `python`, `jq`) or by a script is never mirrored, so the two copies
599
+ drift apart silently. When they differ, `getSchema` says so in a
600
+ `manageCollection: NOTE` line above the JSON.
601
+
602
+ ### Fix
603
+
604
+ Pass the schema to `manageCollection` `putSchema`. It validates the schema,
605
+ writes the staging copy and mirrors it into `.claude/skills/<slug>/` in one
606
+ step, and the collection reloads without a restart. Make every later schema
607
+ change the same way — `getSchema`, edit, `putSchema` — never with Bash.
608
+
587
609
  ## dataSource (CSV) collection reads fail — "DuckDB is unavailable on this host"
588
610
 
589
611
  A collection whose schema declares `dataSource` (external CSV) reads its rows
@@ -6,7 +6,7 @@ const require_relPath = require("../../../relPath-CTAjGdCL.cjs");
6
6
  const require_utils_fetch = require("../../../utils/fetch.cjs");
7
7
  const require_discovery = require("../../../discovery-CwBXvtyn.cjs");
8
8
  const require_templatePath = require("../../../templatePath-27vUZowm.cjs");
9
- const require_server = require("../../../server-ObUrsDs2.cjs");
9
+ const require_server = require("../../../server-CLhww8NL.cjs");
10
10
  const require_skill_bridge_index = require("../../../skill-bridge/index.cjs");
11
11
  const require_types = require("../../../types-CNqkLT4M.cjs");
12
12
  let node_fs = require("node:fs");
@@ -4,7 +4,7 @@ import { n as toPosixRelPath } from "../../../relPath-DW8MC8VO.js";
4
4
  import { fetchWithTimeout } from "../../../utils/fetch.js";
5
5
  import { K as safeRecordId, et as collectionsRegistriesConfigPath, ht as skillsStagingDir, lt as projectSkillsDir, r as loadCollection, rt as getWorkspaceRoot, s as CollectionSchemaZ, st as log, t as acceptParsedSchema } from "../../../discovery-XoYJI2Ot.js";
6
6
  import { t as isSafeActionTemplatePath } from "../../../templatePath-k_WNbL_Q.js";
7
- import { y as ONE_SECOND_MS } from "../../../server-CM5XNicg.js";
7
+ import { y as ONE_SECOND_MS } from "../../../server-CTkTHqEL.js";
8
8
  import { claudeSkillDir, dataSkillDir, mirrorSkillWrite } from "../../../skill-bridge/index.js";
9
9
  import { n as parseRegistryIndex, r as isRecord, t as OFFICIAL_REGISTRY_NAME } from "../../../types-BKVZrtyc.js";
10
10
  import { readFileSync } from "node:fs";
@@ -3,7 +3,7 @@ const require_root = require("../../root-BvwBUcol.cjs");
3
3
  const require_itemId = require("../../itemId-CVrNibwT.cjs");
4
4
  const require_discovery = require("../../discovery-CwBXvtyn.cjs");
5
5
  const require_templatePath = require("../../templatePath-27vUZowm.cjs");
6
- const require_server = require("../../server-ObUrsDs2.cjs");
6
+ const require_server = require("../../server-CLhww8NL.cjs");
7
7
  exports.APP_MANIFEST_FILE = require_discovery.APP_MANIFEST_FILE;
8
8
  exports.BackendUnavailableError = require_discovery.BackendUnavailableError;
9
9
  exports.COLLECTION_ROOT_REQUIRED = require_discovery.COLLECTION_ROOT_REQUIRED;
@@ -2,5 +2,5 @@ import { t as canonicalRoot } from "../../root-BcS4-Kge.js";
2
2
  import { K as COMPUTED_TYPES } from "../../itemId-C9s-Jd5s.js";
3
3
  import { $ as collectionChangePayload, A as readItem, B as SCHEMA_FILE, C as CollectionQueryZ, D as generateItemId, E as deleteItem, F as loadAppManifest, G as resolveTemplatePath, H as isUnderRealRoot, I as parseAppManifest, J as BackendUnavailableError, K as safeRecordId, L as sharedItemsPath, M as writeItem, N as APP_MANIFEST_FILE, O as isRegularFile, P as appManifestReason, Q as collectionChangeKey, R as pageFromFullRead, S as compileJsonlQuery, T as MAX_QUERY_ROWS, U as itemFilePath, V as isContainedInRoot, W as resolveDataDir, X as COLLECTION_ROOT_REQUIRED, Y as isBackendUnavailable, _ as dedupeByRecordId, a as toDetail, ct as peekWorkspaceRoot, d as storeFor, dt as setCollectionChangePublisher, ft as setFirestoreAccessor, g as decodeCsvRecordId, h as csvRowToItem, i as resolvePrimaryField, it as hostSupportsSharedCollections, j as resolveCreateItemId, k as listItems, l as collectionWritable, mt as sharedCollectionChangePayload, n as discoverCollections, nt as firestoreHandle, o as toSummary, ot as localCollectionKey, p as MAX_CSV_ROWS, pt as setSharedCollectionsSupport, q as safeSlugName, r as loadCollection, rt as getWorkspaceRoot, s as CollectionSchemaZ, st as log, t as acceptParsedSchema, tt as configureCollectionHost, u as readOnlyRefusal, ut as publishCollectionChange, v as encodeCsvRecordId, w as DEFAULT_QUERY_ROWS, x as compileCsvQuery, y as normalizeCsvValue, z as projectItemFields } from "../../discovery-XoYJI2Ot.js";
4
4
  import { i as isSafeTemplatePath, n as isSafeCustomViewI18nPath, r as isSafeCustomViewPath, t as isSafeActionTemplatePath } from "../../templatePath-k_WNbL_Q.js";
5
- import { A as recordFieldProblem, B as stagedSkillDir, C as applyMutateAction, D as validateCollectionRecords, E as STORE_UNREADABLE, F as buildCollectionActionSeedPrompt, I as promptPathsFor, L as readCustomViewHtml, M as enrichItems, N as runQueryOverRows, O as validateRecordObject, P as buildActionSeedPrompt, R as readCustomViewI18n, S as schemaRelations, T as MAX_RECORD_ISSUES, _ as resolveEvery, a as MAX_UNSELECTIVE_ITEMS, b as computeCollectionIcon, c as deleteCollection, d as computeSuccessor, f as daysInMonth, g as parseCivil, h as maybeSpawnSuccessor, i as MAX_SCHEMA_ISSUES, j as runCollectionQuery, k as compileRecordZ, l as deleteCollectionRefusalMessage, m as isTriggerDue, n as MAX_PUT_ITEMS, o as makeManageCollectionTool, p as formatCivil, r as MAX_PUT_LINT, s as deleteCustomView, t as MAX_ITEMS_FILE_BYTES, u as advanceTriggerDate, v as successorId, w as firstMutateParamProblem, x as buildWorkspaceOntology, z as readSkillTemplate } from "../../server-CM5XNicg.js";
5
+ import { A as recordFieldProblem, B as stagedSkillDir, C as applyMutateAction, D as validateCollectionRecords, E as STORE_UNREADABLE, F as buildCollectionActionSeedPrompt, I as promptPathsFor, L as readCustomViewHtml, M as enrichItems, N as runQueryOverRows, O as validateRecordObject, P as buildActionSeedPrompt, R as readCustomViewI18n, S as schemaRelations, T as MAX_RECORD_ISSUES, _ as resolveEvery, a as MAX_UNSELECTIVE_ITEMS, b as computeCollectionIcon, c as deleteCollection, d as computeSuccessor, f as daysInMonth, g as parseCivil, h as maybeSpawnSuccessor, i as MAX_SCHEMA_ISSUES, j as runCollectionQuery, k as compileRecordZ, l as deleteCollectionRefusalMessage, m as isTriggerDue, n as MAX_PUT_ITEMS, o as makeManageCollectionTool, p as formatCivil, r as MAX_PUT_LINT, s as deleteCustomView, t as MAX_ITEMS_FILE_BYTES, u as advanceTriggerDate, v as successorId, w as firstMutateParamProblem, x as buildWorkspaceOntology, z as readSkillTemplate } from "../../server-CTkTHqEL.js";
6
6
  export { APP_MANIFEST_FILE, BackendUnavailableError, COLLECTION_ROOT_REQUIRED, COMPUTED_TYPES, CollectionQueryZ, CollectionSchemaZ, DEFAULT_QUERY_ROWS, MAX_CSV_ROWS, MAX_ITEMS_FILE_BYTES, MAX_PUT_ITEMS, MAX_PUT_LINT, MAX_QUERY_ROWS, MAX_RECORD_ISSUES, MAX_SCHEMA_ISSUES, MAX_UNSELECTIVE_ITEMS, SCHEMA_FILE, STORE_UNREADABLE, acceptParsedSchema, advanceTriggerDate, appManifestReason, applyMutateAction, buildActionSeedPrompt, buildCollectionActionSeedPrompt, buildWorkspaceOntology, canonicalRoot, collectionChangeKey, collectionChangePayload, collectionWritable, compileCsvQuery, compileJsonlQuery, compileRecordZ, computeCollectionIcon, computeSuccessor, configureCollectionHost, csvRowToItem, daysInMonth, decodeCsvRecordId, dedupeByRecordId, deleteCollection, deleteCollectionRefusalMessage, deleteCustomView, deleteItem, discoverCollections, encodeCsvRecordId, enrichItems, firestoreHandle, firstMutateParamProblem, formatCivil, generateItemId, getWorkspaceRoot, hostSupportsSharedCollections, isBackendUnavailable, isContainedInRoot, isRegularFile, isSafeActionTemplatePath, isSafeCustomViewI18nPath, isSafeCustomViewPath, isSafeTemplatePath, isTriggerDue, isUnderRealRoot, itemFilePath, listItems, loadAppManifest, loadCollection, localCollectionKey, log, makeManageCollectionTool, maybeSpawnSuccessor, normalizeCsvValue, pageFromFullRead, parseAppManifest, parseCivil, peekWorkspaceRoot, projectItemFields, promptPathsFor, publishCollectionChange, readCustomViewHtml, readCustomViewI18n, readItem, readOnlyRefusal, readSkillTemplate, recordFieldProblem, resolveCreateItemId, resolveDataDir, resolveEvery, resolvePrimaryField, resolveTemplatePath, runCollectionQuery, runQueryOverRows, safeRecordId, safeSlugName, schemaRelations, setCollectionChangePublisher, setFirestoreAccessor, setSharedCollectionsSupport, sharedCollectionChangePayload, sharedItemsPath, stagedSkillDir, storeFor, successorId, toDetail, toSummary, validateCollectionRecords, validateRecordObject, writeItem };
@@ -0,0 +1,4 @@
1
+ /** The reply for `getSchema`: the staging copy when there is one, else the active
2
+ * copy; prefixed with a notice when both exist and differ. `null` when neither
3
+ * copy could be read. */
4
+ export declare function schemaReadReply(slug: string, staging: string | null, active: string | null): string | null;
@@ -4,7 +4,7 @@ const require_itemId = require("../itemId-CVrNibwT.cjs");
4
4
  const require_promptSafety = require("../promptSafety-BGV1wrE6.cjs");
5
5
  require("../collection/index.cjs");
6
6
  const require_discovery = require("../discovery-CwBXvtyn.cjs");
7
- const require_server = require("../server-ObUrsDs2.cjs");
7
+ const require_server = require("../server-CLhww8NL.cjs");
8
8
  const require_notifier = require("../notifier-B65Mvngb.cjs");
9
9
  let node_fs_promises = require("node:fs/promises");
10
10
  //#region src/collection-watchers/config.ts
@@ -3,7 +3,7 @@ import { $ as fieldText, P as isValidCollectionName } from "../itemId-C9s-Jd5s.j
3
3
  import { E as whenMatches, f as itemIsDone } from "../promptSafety-B5uGroik.js";
4
4
  import "../collection/index.js";
5
5
  import { $ as collectionChangePayload, U as itemFilePath, ct as peekWorkspaceRoot, d as storeFor, mt as sharedCollectionChangePayload, n as discoverCollections, nt as firestoreHandle, r as loadCollection, ut as publishCollectionChange } from "../discovery-XoYJI2Ot.js";
6
- import { h as maybeSpawnSuccessor, m as isTriggerDue } from "../server-CM5XNicg.js";
6
+ import { h as maybeSpawnSuccessor, m as isTriggerDue } from "../server-CTkTHqEL.js";
7
7
  import { d as publish, m as updateForPlugin, n as clear, s as listAll } from "../notifier-vAp5t6wL.js";
8
8
  import { access } from "node:fs/promises";
9
9
  //#region src/collection-watchers/config.ts
@@ -5,7 +5,7 @@ const require_root = require("../../root-BvwBUcol.cjs");
5
5
  const require_itemId = require("../../itemId-CVrNibwT.cjs");
6
6
  const require_project = require("../../project-C1ep9pvo.cjs");
7
7
  const require_discovery = require("../../discovery-CwBXvtyn.cjs");
8
- const require_server = require("../../server-ObUrsDs2.cjs");
8
+ const require_server = require("../../server-CLhww8NL.cjs");
9
9
  const require_feeds_paths = require("../paths.cjs");
10
10
  const require_ingestTypes = require("../../ingestTypes-DS9HiR2I.cjs");
11
11
  const require_notifier = require("../../notifier-B65Mvngb.cjs");
@@ -3,7 +3,7 @@ import { t as canonicalRoot } from "../../root-BcS4-Kge.js";
3
3
  import { J as INGEST_KINDS, q as FEED_SCHEDULES } from "../../itemId-C9s-Jd5s.js";
4
4
  import { t as mergeIntoExisting } from "../../project-B0j_Vf_Q.js";
5
5
  import { W as resolveDataDir, _t as createForwardingLogger, d as storeFor, k as listItems, n as discoverCollections, q as safeSlugName, vt as createHostSlot } from "../../discovery-XoYJI2Ot.js";
6
- import { F as buildCollectionActionSeedPrompt, I as promptPathsFor, z as readSkillTemplate } from "../../server-CM5XNicg.js";
6
+ import { F as buildCollectionActionSeedPrompt, I as promptPathsFor, z as readSkillTemplate } from "../../server-CTkTHqEL.js";
7
7
  import { FEEDS_DIR, feedDir, feedStatePath, feedsRoot, ingestStateDir, ingestStatePath } from "../paths.js";
8
8
  import { n as DEFAULT_FEED_MAX_ITEMS, r as isFeedSchedule, t as AGENT_INGEST_KIND } from "../../ingestTypes-Bs31Xt5c.js";
9
9
  import { d as publish, n as clear } from "../../notifier-vAp5t6wL.js";
@@ -1605,6 +1605,30 @@ function renderSchemaDocs(rawDoc, topic, variant = "staged") {
1605
1605
  if (sections.length === 0) return doc;
1606
1606
  return clip(requested ? renderTopic(lines, sections, requested) : renderDefault(lines, sections), SCHEMA_DOCS_RESULT_BUDGET);
1607
1607
  }
1608
+ //#endregion
1609
+ //#region src/collection/server/schemaReadReply.ts
1610
+ /** The note prefixed when the two copies differ. Kept separate from the JSON by a
1611
+ * blank line so the schema below it is still copyable as-is. */
1612
+ function divergenceNotice(slug) {
1613
+ return [
1614
+ `manageCollection: NOTE — the schema below is data/skills/${slug}/schema.json, and it DIFFERS from .claude/skills/${slug}/schema.json, the copy the server is running.`,
1615
+ "The staging copy was changed without being mirrored (Write / Edit are mirrored; Bash and scripts are not).",
1616
+ `To apply it, pass the JSON below to putSchema. To keep the running schema instead, Read .claude/skills/${slug}/schema.json and putSchema that.`
1617
+ ].join("\n");
1618
+ }
1619
+ /** The reply for `getSchema`: the staging copy when there is one, else the active
1620
+ * copy; prefixed with a notice when both exist and differ. `null` when neither
1621
+ * copy could be read. */
1622
+ function schemaReadReply(slug, staging, active) {
1623
+ const primary = staging ?? active;
1624
+ if (primary === null) return null;
1625
+ if (staging === null || active === null || staging === active) return primary;
1626
+ return [
1627
+ divergenceNotice(slug),
1628
+ "",
1629
+ staging
1630
+ ].join("\n");
1631
+ }
1608
1632
  /** True for a launcher-managed preset slug (`mc-<something>`). The sync logic uses
1609
1633
  * this to bound which active skills it may refresh/prune, so user-authored skills are
1610
1634
  * never touched. */
@@ -2222,19 +2246,24 @@ async function handleSchemaDocs(deps, topic) {
2222
2246
  } catch {}
2223
2247
  return `manageCollection: could not read the collection-authoring reference (${SCHEMA_DOCS_FILE}).`;
2224
2248
  }
2249
+ async function readTextOrNull(filePath) {
2250
+ try {
2251
+ return await (0, node_fs_promises.readFile)(filePath, "utf-8");
2252
+ } catch {
2253
+ return null;
2254
+ }
2255
+ }
2225
2256
  /** Return the raw schema.json of an existing collection, for editing.
2226
- * Staging (the canonical writable copy) first, the active mirror as a
2227
- * fallback for user-scope skills that have no staging copy. Raw text —
2257
+ * A project collection's staging copy (the canonical writable one) first,
2258
+ * else the discovered skill dir's copy. Raw text —
2228
2259
  * not the parsed schema — so the agent edits the true on-disk source. */
2229
2260
  async function handleGetSchema(slug, deps) {
2230
2261
  const collection = await require_discovery.loadCollection(slug, deps);
2231
2262
  if (!collection) return unknownCollection(slug);
2232
2263
  const { stagingDir } = authoringTarget(deps, collection.slug);
2233
- const candidates = [...stagingDir === null ? [] : [node_path.default.join(stagingDir, SCHEMA_FILE)], node_path.default.join(collection.skillDir, SCHEMA_FILE)];
2234
- for (const candidate of candidates) try {
2235
- return await (0, node_fs_promises.readFile)(candidate, "utf-8");
2236
- } catch {}
2237
- return `manageCollection: '${require_promptSafety.defangForPrompt(slug)}' has no readable ${SCHEMA_FILE}.`;
2264
+ const staging = stagingDir !== null && collection.source === "project" ? await readTextOrNull(node_path.default.join(stagingDir, SCHEMA_FILE)) : null;
2265
+ const active = await readTextOrNull(node_path.default.join(collection.skillDir, SCHEMA_FILE));
2266
+ return schemaReadReply(collection.slug, staging, active) ?? `manageCollection: '${require_promptSafety.defangForPrompt(slug)}' has no readable ${SCHEMA_FILE}.`;
2238
2267
  }
2239
2268
  /** Where the agent should CREATE a collection skill in this root, named in the
2240
2269
  * messages that tell it to. Naming `data/skills/` under a root that has no
@@ -2689,4 +2718,4 @@ Object.defineProperty(exports, "validateRecordObject", {
2689
2718
  }
2690
2719
  });
2691
2720
 
2692
- //# sourceMappingURL=server-ObUrsDs2.cjs.map
2721
+ //# sourceMappingURL=server-CLhww8NL.cjs.map