@mulmoclaude/core 5.5.1 → 5.6.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.
- package/assets/helps/collection-skills.md +6 -2
- package/assets/helps/error-recovery.md +3 -1
- package/assets/helps/google-calendar-collection.md +11 -4
- package/dist/collection/index.cjs +8 -1
- package/dist/collection/index.cjs.map +1 -1
- package/dist/collection/index.js +8 -1
- package/dist/collection/index.js.map +1 -1
- package/dist/collection/registry/server/index.cjs +1 -1
- package/dist/collection/registry/server/index.js +1 -1
- package/dist/collection/server/index.cjs +1 -1
- package/dist/collection/server/index.js +1 -1
- package/dist/collection-watchers/index.cjs +1 -1
- package/dist/collection-watchers/index.js +1 -1
- package/dist/feeds/server/index.cjs +1 -1
- package/dist/feeds/server/index.js +1 -1
- package/dist/{server-DZ7Cq7s_.js → server--34TYvGP.js} +19 -3
- package/dist/server--34TYvGP.js.map +1 -0
- package/dist/{server-BUbU9G-J.cjs → server-DZdM2cLD.cjs} +19 -3
- package/dist/server-DZdM2cLD.cjs.map +1 -0
- package/package.json +3 -3
- package/dist/server-BUbU9G-J.cjs.map +0 -1
- package/dist/server-DZ7Cq7s_.js.map +0 -1
|
@@ -450,13 +450,29 @@ function enforcedProblem(key, spec, value) {
|
|
|
450
450
|
/** Named in the lint's own message, so the shape is shown rather than
|
|
451
451
|
* described. */
|
|
452
452
|
var CANONICAL_SERVER_TIME_EXAMPLE = "2026-08-15T01:45:54.605987654Z";
|
|
453
|
+
/** The shapes a `datetime` field may hold.
|
|
454
|
+
*
|
|
455
|
+
* A bare date is an all-day value: `…T00:00` is how a real midnight start is
|
|
456
|
+
* written, so it cannot also mean "all day", and a bare date is the shape the
|
|
457
|
+
* push already sends as Google's `start.date`.
|
|
458
|
+
*
|
|
459
|
+
* The server-stamped instant is not a loosening of the civil shape. A SHARED
|
|
460
|
+
* collection can pin a field to the server's clock, and what is stored there is
|
|
461
|
+
* a Firestore timestamp the rules require; by the time it reaches here it is the
|
|
462
|
+
* canonical instant string (`../core/serverTime`). Only that exact form is
|
|
463
|
+
* accepted — RFC3339 in general is not, because two values with different
|
|
464
|
+
* offsets do not sort in time order, and the order is the whole reason the
|
|
465
|
+
* field exists. */
|
|
466
|
+
function isStoredDateTime(value) {
|
|
467
|
+
return require_itemId.parseIsoDateTime(value) !== null || require_itemId.parseIsoDate(value) !== null || require_itemId.isCanonicalServerTime(value);
|
|
468
|
+
}
|
|
453
469
|
function strictTypeProblem(key, spec, value) {
|
|
454
470
|
switch (spec.type) {
|
|
455
471
|
case "number":
|
|
456
472
|
case "money": return Number.isFinite(require_promptSafety.coerceNumeric(value)) ? null : `'${key}' = '${String(value)}' is not numeric (a '${spec.type}' field stores a plain number)`;
|
|
457
473
|
case "boolean": return value === true || value === false ? null : `'${key}' = '${String(value)}' is not a boolean (store true or false, unquoted)`;
|
|
458
474
|
case "date": return require_itemId.parseIsoDate(value) !== null ? null : `'${key}' = '${String(value)}' is not a real YYYY-MM-DD date`;
|
|
459
|
-
case "datetime": return
|
|
475
|
+
case "datetime": return isStoredDateTime(value) ? null : `'${key}' = '${String(value)}' is not a YYYY-MM-DDTHH:MM datetime (seconds optional, no timezone suffix — the shape the calendar parses), nor a YYYY-MM-DD all-day date, nor a server-stamped instant (${CANONICAL_SERVER_TIME_EXAMPLE})`;
|
|
460
476
|
default: return null;
|
|
461
477
|
}
|
|
462
478
|
}
|
|
@@ -2301,7 +2317,7 @@ async function handlePutSchema(slug, schemaArg, deps) {
|
|
|
2301
2317
|
written: true
|
|
2302
2318
|
});
|
|
2303
2319
|
}
|
|
2304
|
-
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 — the default reply is the core authoring guide plus a table of contents; fetch advanced sections (actions, bells, calendar/kanban views, dataSource, storage) by passing their heading as `topic` rather than dumping `topic: \"all\"`. 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` GATES every row on what would make the record unopenable — 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. That gate does NOT check the SHAPE of a value: a `datetime` written as an instant (`2026-08-17T15:00:00.000Z`, what `toISOString()` produces) rather than as a wall clock, a `number` holding something that is not a number at all, a `date` that is not a real day are all WRITTEN, and come back in a `lint` block beside `written`. Read it — a full `getItems` listing warns about the same rows and publishing a shared app REFUSES them, so a silent `lint` is the only proof the values are right. Before generating a large set, read the exact stored form of each type in the `Field types` section of `schemaDocs` (`topic: \"Field types\"` fetches just that one), then write ONE batch and check that `lint` is absent. `datetime` in particular is a local wall clock (`YYYY-MM-DDTHH:MM`, no timezone suffix), so `new Date(...).toISOString()` is wrong twice over — the suffix, and the hours the conversion moved. The one `Z`-suffixed datetime the strict tier accepts is a shared app's server-stamped instant, written by the SERVER with nine fractional digits; you never produce that value. When the rows come from a script rather than from you (a generated schedule, an imported set, anything past a few dozen records), write them to a JSON file UNDER THE WORKSPACE and pass its absolute path as `itemsFile` instead of `items` — the host reads the file, so the rows never pass through your context. Do NOT hand-transcribe a generated file into `items`, and never drive the collection by spawning the MCP bridge yourself. 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.";
|
|
2320
|
+
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 — the default reply is the core authoring guide plus a table of contents; fetch advanced sections (actions, bells, calendar/kanban views, dataSource, storage) by passing their heading as `topic` rather than dumping `topic: \"all\"`. 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` GATES every row on what would make the record unopenable — 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. That gate does NOT check the SHAPE of a value: a `datetime` written as an instant (`2026-08-17T15:00:00.000Z`, what `toISOString()` produces) rather than as a wall clock, a `number` holding something that is not a number at all, a `date` that is not a real day are all WRITTEN, and come back in a `lint` block beside `written`. Read it — a full `getItems` listing warns about the same rows and publishing a shared app REFUSES them, so a silent `lint` is the only proof the values are right. Before generating a large set, read the exact stored form of each type in the `Field types` section of `schemaDocs` (`topic: \"Field types\"` fetches just that one), then write ONE batch and check that `lint` is absent. `datetime` in particular is a local wall clock (`YYYY-MM-DDTHH:MM`, no timezone suffix; a bare `YYYY-MM-DD` means ALL DAY and is not the same as `…T00:00`, a real midnight start), so `new Date(...).toISOString()` is wrong twice over — the suffix, and the hours the conversion moved. The one `Z`-suffixed datetime the strict tier accepts is a shared app's server-stamped instant, written by the SERVER with nine fractional digits; you never produce that value. When the rows come from a script rather than from you (a generated schedule, an imported set, anything past a few dozen records), write them to a JSON file UNDER THE WORKSPACE and pass its absolute path as `itemsFile` instead of `items` — the host reads the file, so the rows never pass through your context. Do NOT hand-transcribe a generated file into `items`, and never drive the collection by spawning the MCP bridge yourself. 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.";
|
|
2305
2321
|
/** Validate getItems' optional `ids`/`fields` args, then delegate. */
|
|
2306
2322
|
async function dispatchGetItems(collection, args, deps) {
|
|
2307
2323
|
const ids = optionalStringArray(args.ids, "ids");
|
|
@@ -2673,4 +2689,4 @@ Object.defineProperty(exports, "validateRecordObject", {
|
|
|
2673
2689
|
}
|
|
2674
2690
|
});
|
|
2675
2691
|
|
|
2676
|
-
//# sourceMappingURL=server-
|
|
2692
|
+
//# sourceMappingURL=server-DZdM2cLD.cjs.map
|