@mulmoclaude/core 0.25.1 → 0.26.0

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 (30) hide show
  1. package/assets/helps/billing-clients-worklog.md +3 -2
  2. package/assets/helps/collection-skills.md +3 -1
  3. package/assets/helps/todo-collection.md +2 -2
  4. package/dist/collection/core/fieldText.d.ts +11 -0
  5. package/dist/collection/index.cjs +14 -9
  6. package/dist/collection/index.cjs.map +1 -1
  7. package/dist/collection/index.d.ts +1 -0
  8. package/dist/collection/index.js +13 -10
  9. package/dist/collection/index.js.map +1 -1
  10. package/dist/collection/registry/server/index.cjs +1 -1
  11. package/dist/collection/registry/server/index.js +1 -1
  12. package/dist/collection/server/index.cjs +1 -1
  13. package/dist/collection/server/index.js +1 -1
  14. package/dist/collection-watchers/index.cjs +48 -10
  15. package/dist/collection-watchers/index.cjs.map +1 -1
  16. package/dist/collection-watchers/index.js +50 -12
  17. package/dist/collection-watchers/index.js.map +1 -1
  18. package/dist/feeds/server/index.cjs +1 -1
  19. package/dist/feeds/server/index.js +1 -1
  20. package/dist/{promptSafety-Boz5qOs-.js → promptSafety-B5KPkaNY.js} +32 -9
  21. package/dist/promptSafety-B5KPkaNY.js.map +1 -0
  22. package/dist/{promptSafety-Co4cYQ_Z.cjs → promptSafety-BOc1B3im.cjs} +43 -8
  23. package/dist/promptSafety-BOc1B3im.cjs.map +1 -0
  24. package/dist/{server-CKdWENZ-.cjs → server-B7mtx4Cd.cjs} +66 -11
  25. package/dist/{server-CKdWENZ-.cjs.map → server-B7mtx4Cd.cjs.map} +1 -1
  26. package/dist/{server-BI3wnTwl.js → server-CNLZZONa.js} +66 -11
  27. package/dist/{server-BI3wnTwl.js.map → server-CNLZZONa.js.map} +1 -1
  28. package/package.json +1 -1
  29. package/dist/promptSafety-Boz5qOs-.js.map +0 -1
  30. package/dist/promptSafety-Co4cYQ_Z.cjs.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { f as storageKindFor, l as embedTargetId, o as COMPUTED_TYPES, u as isFieldDrivenEvery } from "./ids-P2T89Gou.js";
2
- import { D as rollupValue, E as projectBacklinkRow, O as actionVisible, S as itemIsDone, T as coerceNumeric, b as resolveIcon, d as parseIsoDateTime, g as deriveAll, t as defangForPrompt, u as parseIsoDate, w as backlinkRows, x as selectDynamicRecord, y as firstDateField } from "./promptSafety-Boz5qOs-.js";
2
+ import { D as rollupValue, E as projectBacklinkRow, O as actionVisible, S as itemIsDone, T as coerceNumeric, b as resolveIcon, d as parseIsoDateTime, g as deriveAll, t as defangForPrompt, u as parseIsoDate, w as backlinkRows, x as selectDynamicRecord, y as firstDateField } from "./promptSafety-B5KPkaNY.js";
3
3
  import { $ as isPresetSlug$1, B as writeFileAtomic, C as compileJsonlQuery, G as resolveDataDir, H as isContainedInRoot, J as safeSlugName, K as resolveTemplatePath, Q as getWorkspaceRoot, R as resolveCreateItemId, V as SCHEMA_FILE$1, Y as archiveDir, b as normalizeCsvValue, d as checkpointSqliteDatabase, et as log, h as cacheDir, j as isRegularFile, l as readOnlyRefusal, n as discoverCollections, o as CollectionSchemaZ, r as loadCollection, rt as skillsStagingDir, s as resolveMutateSet, u as storeFor, w as CollectionQueryZ, x as queryCsv } from "./discovery-QUi_7aNG.js";
4
4
  import { dataSkillDir, mirrorSkillWrite } from "./skill-bridge/index.js";
5
5
  import path from "node:path";
@@ -1318,6 +1318,44 @@ async function handlePutItems(collection, args, deps) {
1318
1318
  rejected
1319
1319
  });
1320
1320
  }
1321
+ /** Delete records by id, through the store — so it works on any writable
1322
+ * backend, not just file records. Same read-only refusal as putItems (an
1323
+ * absent `delete` IS the refusal), and the same per-id result shape so a
1324
+ * partially-bad batch reports per id instead of failing whole. */
1325
+ async function handleDeleteItems(collection, ids, deps) {
1326
+ const { delete: removeItem } = storeFor(collection, { workspaceRoot: deps.workspaceRoot });
1327
+ if (!removeItem) return `manageCollection: ${readOnlyRefusal(collection.slug)} (its records are the rows of '${collection.schema.dataSource?.path}'; edit that file to change the data).`;
1328
+ const deleted = [];
1329
+ const rejected = [];
1330
+ for (const itemId of ids) {
1331
+ const outcome = await deleteOneItem(removeItem, itemId);
1332
+ if (outcome.deleted) deleted.push(outcome.deleted);
1333
+ if (outcome.rejected) rejected.push(outcome.rejected);
1334
+ }
1335
+ return JSON.stringify({
1336
+ collection: collection.slug,
1337
+ deleted,
1338
+ rejected
1339
+ });
1340
+ }
1341
+ /** A missing id is a rejection, not a silent success: deleting by a typo'd
1342
+ * id would otherwise report "done" while the real record survives. */
1343
+ async function deleteOneItem(removeItem, itemId) {
1344
+ const result = await removeItem(itemId);
1345
+ if (result.kind === "ok") return { deleted: result.itemId };
1346
+ const reject = (problem) => ({ rejected: {
1347
+ id: defangForPrompt(itemId),
1348
+ problem: defangForPrompt(problem)
1349
+ } });
1350
+ if (result.kind === "invalid-id") return reject(`'${itemId}' is not a valid record id (letters/digits at the ends; -, _, or . inside; no '..' or path characters)`);
1351
+ if (result.kind === "not-found") return reject(`'${itemId}' not found — nothing was deleted; confirm the id with getItems`);
1352
+ return reject("delete refused: the collection's data dir escapes the workspace");
1353
+ }
1354
+ function parseDeleteIds(args) {
1355
+ const { ids } = args;
1356
+ if (!(Array.isArray(ids) && ids.length > 0 && ids.every((entry) => typeof entry === "string" && entry.trim().length > 0))) return "manageCollection: `ids` is required for deleteItems — a non-empty array of record ids.";
1357
+ return ids;
1358
+ }
1321
1359
  function parsePutItems(args, slug) {
1322
1360
  const { items, mode } = args;
1323
1361
  if (!(Array.isArray(items) && items.length > 0 && items.every((entry) => Boolean(entry) && typeof entry === "object" && !Array.isArray(entry)))) return "manageCollection: `items` is required for putItems — a non-empty array of record objects.";
@@ -1426,7 +1464,7 @@ async function handlePutSchema(slug, schemaArg, deps) {
1426
1464
  written: true
1427
1465
  });
1428
1466
  }
1429
- var MANAGE_COLLECTION_PROMPT = "Use `manageCollection` instead of raw Read/Write/Edit when working with a collection's records OR its schema (raw file I/O stays available as the escape hatch). Before authoring or changing a collection's `schema.json`, call `schemaDocs` to load the field/DSL reference, then read with `getSchema` and write with `putSchema` — `putSchema` validates the whole schema before writing and returns actionable errors instead of silently failing discovery's validation. `getItems` is the only way to see computed values — `derived` fields (e.g. a portfolio's value), `toggle` projections, and `embed` records are host-computed and never present in the stored JSON files. On large collections pass `ids` and/or `fields` to keep the result small. For a question that spans collections (\"which clients have unpaid invoices?\"), start with `getOntology`: it lists every collection with its primaryKey, record count, and outbound `ref`/`embed` relations, so you know which collections to join before reading any records. `putItems` validates every row against the schema before writing (required fields, enum values, primaryKey = record id) and returns `{ written, rejected }`; fix each rejected row using its `problem` text and retry just those rows. Never include computed fields in a row you write. To update a few fields of an existing record, use `mode: \"merge\"` with a partial row ({ id, <changed fields> }) — the default upsert replaces the WHOLE record, so a partial upsert would silently erase every optional field it omits. Answer aggregation questions (counts, sums, averages, group-bys) with `queryItems` on ANY collection — on a dataSource (CSV) collection it scans the whole file (getItems is row-capped, so aggregates computed from its output can be silently wrong on large files); on a file-backed collection it aggregates the enriched records, so computed fields (derived/rollup/toggle) are queryable columns.";
1467
+ var MANAGE_COLLECTION_PROMPT = "Use `manageCollection` instead of raw Read/Write/Edit when working with a collection's records OR its schema (raw file I/O stays available as the escape hatch). Before authoring or changing a collection's `schema.json`, call `schemaDocs` to load the field/DSL reference, then read with `getSchema` and write with `putSchema` — `putSchema` validates the whole schema before writing and returns actionable errors instead of silently failing discovery's validation. `getItems` is the only way to see computed values — `derived` fields (e.g. a portfolio's value), `toggle` projections, and `embed` records are host-computed and never present in the stored JSON files. On large collections pass `ids` and/or `fields` to keep the result small. For a question that spans collections (\"which clients have unpaid invoices?\"), start with `getOntology`: it lists every collection with its primaryKey, record count, and outbound `ref`/`embed` relations, so you know which collections to join before reading any records. `putItems` validates every row against the schema before writing (required fields, enum values, primaryKey = record id) and returns `{ written, rejected }`; fix each rejected row using its `problem` text and retry just those rows. Never include computed fields in a row you write. To update a few fields of an existing record, use `mode: \"merge\"` with a partial row ({ id, <changed fields> }) — the default upsert replaces the WHOLE record, so a partial upsert would silently erase every optional field it omits. `deleteItems` removes records by id and returns `{ deleted, rejected }`; an id that doesn't exist comes back rejected rather than counted as deleted, so check `rejected` before reporting a deletion as done. Answer aggregation questions (counts, sums, averages, group-bys) with `queryItems` on ANY collection — on a dataSource (CSV) collection it scans the whole file (getItems is row-capped, so aggregates computed from its output can be silently wrong on large files); on a file-backed collection it aggregates the enriched records, so computed fields (derived/rollup/toggle) are queryable columns.";
1430
1468
  /** Validate getItems' optional `ids`/`fields` args, then delegate. */
1431
1469
  async function dispatchGetItems(collection, args, deps) {
1432
1470
  const ids = optionalStringArray(args.ids, "ids");
@@ -1439,6 +1477,26 @@ async function dispatchGetItems(collection, args, deps) {
1439
1477
  fields: fields.value
1440
1478
  }, deps);
1441
1479
  }
1480
+ /** Actions that operate on a collection's RECORDS — i.e. the ones that
1481
+ * need the collection loaded first. Schema/workspace actions don't. */
1482
+ var RECORD_ACTIONS = /* @__PURE__ */ new Set([
1483
+ "getItems",
1484
+ "putItems",
1485
+ "deleteItems",
1486
+ "queryItems"
1487
+ ]);
1488
+ /** Record-action dispatch, split from `manageCollectionHandler` to keep
1489
+ * both within the cognitive-complexity budget. */
1490
+ async function dispatchRecordAction(action, collection, args, deps) {
1491
+ if (action === "getItems") return dispatchGetItems(collection, args, deps);
1492
+ if (action === "queryItems") return handleQueryItems(collection, args.query, deps);
1493
+ if (action === "deleteItems") {
1494
+ const ids = parseDeleteIds(args);
1495
+ return typeof ids === "string" ? ids : handleDeleteItems(collection, ids, deps);
1496
+ }
1497
+ const parsed = parsePutItems(args, collection.slug);
1498
+ return typeof parsed === "string" ? parsed : handlePutItems(collection, parsed, deps);
1499
+ }
1442
1500
  async function manageCollectionHandler(deps, args) {
1443
1501
  const action = typeof args.action === "string" ? args.action : "";
1444
1502
  if (action === "schemaDocs") return handleSchemaDocs(deps);
@@ -1447,18 +1505,14 @@ async function manageCollectionHandler(deps, args) {
1447
1505
  if (!slug) return "manageCollection: `slug` is required (the collection's slug).";
1448
1506
  if (action === "getSchema") return handleGetSchema(slug, deps);
1449
1507
  if (action === "putSchema") return handlePutSchema(slug, args.schema, deps);
1450
- if (action !== "getItems" && action !== "putItems" && action !== "queryItems") return "manageCollection: `action` must be \"getItems\", \"putItems\", \"queryItems\", \"getOntology\", \"schemaDocs\", \"getSchema\", or \"putSchema\".";
1508
+ if (!RECORD_ACTIONS.has(action)) return "manageCollection: `action` must be \"getItems\", \"putItems\", \"deleteItems\", \"queryItems\", \"getOntology\", \"schemaDocs\", \"getSchema\", or \"putSchema\".";
1451
1509
  const collection = await loadCollection(slug, deps);
1452
1510
  if (!collection) return unknownCollection(slug);
1453
- if (action === "getItems") return dispatchGetItems(collection, args, deps);
1454
- if (action === "queryItems") return handleQueryItems(collection, args.query, deps);
1455
- const parsed = parsePutItems(args, slug);
1456
- if (typeof parsed === "string") return parsed;
1457
- return handlePutItems(collection, parsed, deps);
1511
+ return dispatchRecordAction(action, collection, args, deps);
1458
1512
  }
1459
1513
  var MANAGE_COLLECTION_DEFINITION = {
1460
1514
  name: "manageCollection",
1461
- description: "Read and write a schema-driven collection through the host — both its records and its structure. getItems returns records WITH computed values (derived formulas, toggles, embeds) the stored JSON files don't contain; putItems validates each row against the schema before writing. getOntology maps the whole workspace: every collection with its record count and outbound ref/embed relations — call it first for cross-collection questions. schemaDocs returns the collection-authoring reference; getSchema/putSchema read and validate-then-write the collection's schema.json. Prefer it over raw file I/O on collections.",
1515
+ description: "Read and write a schema-driven collection through the host — both its records and its structure. getItems returns records WITH computed values (derived formulas, toggles, embeds) the stored JSON files don't contain; putItems validates each row against the schema before writing; deleteItems removes records by id. getOntology maps the whole workspace: every collection with its record count and outbound ref/embed relations — call it first for cross-collection questions. schemaDocs returns the collection-authoring reference; getSchema/putSchema read and validate-then-write the collection's schema.json. Prefer it over raw file I/O on collections.",
1462
1516
  inputSchema: {
1463
1517
  type: "object",
1464
1518
  properties: {
@@ -1467,6 +1521,7 @@ var MANAGE_COLLECTION_DEFINITION = {
1467
1521
  enum: [
1468
1522
  "getItems",
1469
1523
  "putItems",
1524
+ "deleteItems",
1470
1525
  "queryItems",
1471
1526
  "getOntology",
1472
1527
  "schemaDocs",
@@ -1482,7 +1537,7 @@ var MANAGE_COLLECTION_DEFINITION = {
1482
1537
  ids: {
1483
1538
  type: "array",
1484
1539
  items: { type: "string" },
1485
- description: "getItems: only these record ids (primary-key values). Omit for all records."
1540
+ description: "getItems: only these record ids (primary-key values); omit for all records. deleteItems: the record ids to delete — required, and never optional there."
1486
1541
  },
1487
1542
  fields: {
1488
1543
  type: "array",
@@ -1526,4 +1581,4 @@ function makeManageCollectionTool(deps = {}) {
1526
1581
  //#endregion
1527
1582
  export { validateCollectionRecords as C, runCollectionQuery as D, recordFieldProblem as E, enrichItems as O, firstMutateParamProblem as S, compileRecordZ as T, errorMessage as _, deleteCollection as a, schemaRelations as b, computeSuccessor as c, isTriggerDue as d, maybeSpawnSuccessor as f, ONE_SECOND_MS as g, successorId as h, deleteCustomView as i, runQueryOverRows as k, daysInMonth as l, resolveEvery as m, MAX_UNSELECTIVE_ITEMS as n, deleteCollectionRefusalMessage as o, parseCivil as p, makeManageCollectionTool as r, advanceTriggerDate as s, MAX_SCHEMA_ISSUES as t, formatCivil as u, computeCollectionIcon as v, validateRecordObject as w, applyMutateAction as x, buildWorkspaceOntology as y };
1528
1583
 
1529
- //# sourceMappingURL=server-BI3wnTwl.js.map
1584
+ //# sourceMappingURL=server-CNLZZONa.js.map