@mulmoclaude/core 0.23.1 → 0.24.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 (40) hide show
  1. package/assets/helps/collection-skills.md +27 -3
  2. package/dist/collection/core/completion.d.ts +18 -0
  3. package/dist/collection/core/deriveAll.d.ts +14 -9
  4. package/dist/collection/core/schema.d.ts +9 -4
  5. package/dist/collection/core/schemaZ.d.ts +97 -43
  6. package/dist/collection/index.cjs +2 -1
  7. package/dist/collection/index.cjs.map +1 -1
  8. package/dist/collection/index.d.ts +1 -0
  9. package/dist/collection/index.js +2 -2
  10. package/dist/collection/index.js.map +1 -1
  11. package/dist/collection/registry/server/index.cjs +1 -1
  12. package/dist/collection/registry/server/index.js +1 -1
  13. package/dist/collection/server/index.cjs +2 -2
  14. package/dist/collection/server/index.js +2 -2
  15. package/dist/collection-watchers/index.cjs +5 -14
  16. package/dist/collection-watchers/index.cjs.map +1 -1
  17. package/dist/collection-watchers/index.js +2 -11
  18. package/dist/collection-watchers/index.js.map +1 -1
  19. package/dist/collection-watchers/reconciler.d.ts +2 -4
  20. package/dist/feeds/index.cjs +2 -2
  21. package/dist/feeds/index.js +2 -2
  22. package/dist/feeds/server/index.cjs +3 -3
  23. package/dist/feeds/server/index.js +3 -3
  24. package/dist/{ingestTypes-B-dXxUF9.js → ingestTypes-CFEgTItj.js} +2 -2
  25. package/dist/{ingestTypes-B-dXxUF9.js.map → ingestTypes-CFEgTItj.js.map} +1 -1
  26. package/dist/{ingestTypes-Cev9q77C.cjs → ingestTypes-Stc7iQyA.cjs} +2 -2
  27. package/dist/{ingestTypes-Cev9q77C.cjs.map → ingestTypes-Stc7iQyA.cjs.map} +1 -1
  28. package/dist/{promptSafety-rDWA9_JS.js → promptSafety-BLUcImzd.js} +54 -26
  29. package/dist/promptSafety-BLUcImzd.js.map +1 -0
  30. package/dist/{promptSafety-DRd15gQ6.cjs → promptSafety-DI_1Rvhk.cjs} +59 -25
  31. package/dist/promptSafety-DI_1Rvhk.cjs.map +1 -0
  32. package/dist/{server-D2ibbixF.js → server-BpEo0FOd.js} +121 -39
  33. package/dist/server-BpEo0FOd.js.map +1 -0
  34. package/dist/{server-Jaogu3Ky.cjs → server-CkysfLh4.cjs} +121 -39
  35. package/dist/server-CkysfLh4.cjs.map +1 -0
  36. package/package.json +1 -1
  37. package/dist/promptSafety-DRd15gQ6.cjs.map +0 -1
  38. package/dist/promptSafety-rDWA9_JS.js.map +0 -1
  39. package/dist/server-D2ibbixF.js.map +0 -1
  40. package/dist/server-Jaogu3Ky.cjs.map +0 -1
@@ -1,5 +1,5 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-D6vf50IK.cjs");
2
- const require_promptSafety = require("./promptSafety-DRd15gQ6.cjs");
2
+ const require_promptSafety = require("./promptSafety-DI_1Rvhk.cjs");
3
3
  const require_collection_paths = require("./collection/paths.cjs");
4
4
  const require_skill_bridge_index = require("./skill-bridge/index.cjs");
5
5
  let node_path = require("node:path");
@@ -1505,6 +1505,32 @@ var WhenZ = zod.z.object({
1505
1505
  field: zod.z.string().trim().min(1),
1506
1506
  in: zod.z.array(zod.z.string().trim().min(1)).min(1)
1507
1507
  });
1508
+ var ValueRefZ = zod.z.object({
1509
+ record: zod.z.string().trim().min(1).optional(),
1510
+ field: zod.z.string().trim().min(1)
1511
+ });
1512
+ var WhereCondZ = zod.z.object({
1513
+ field: zod.z.string().trim().min(1),
1514
+ op: zod.z.enum([
1515
+ "eq",
1516
+ "ne",
1517
+ "in",
1518
+ "gt",
1519
+ "gte",
1520
+ "lt",
1521
+ "lte",
1522
+ "contains"
1523
+ ]),
1524
+ value: zod.z.union([zod.z.string(), zod.z.array(zod.z.string())]).optional(),
1525
+ valueFrom: ValueRefZ.optional()
1526
+ }).refine((cond) => cond.value !== void 0 !== (cond.valueFrom !== void 0), {
1527
+ message: "a where condition must declare exactly one of `value` (a literal) or `valueFrom` (a reference to another record's field), never both or neither",
1528
+ path: ["value"]
1529
+ }).refine((cond) => cond.value === void 0 || cond.op === "in" === Array.isArray(cond.value), {
1530
+ message: "`in` requires an array `value` (the allowed set); every other op requires a single string `value`",
1531
+ path: ["value"]
1532
+ });
1533
+ var WhereZ = zod.z.array(WhereCondZ);
1508
1534
  var fieldBase = {
1509
1535
  label: zod.z.string().min(1),
1510
1536
  primary: zod.z.boolean().optional(),
@@ -1715,6 +1741,30 @@ var ToggleFieldZ = zod.z.object({
1715
1741
  onValue: zod.z.string().trim().min(1),
1716
1742
  offValue: zod.z.string().trim().min(1)
1717
1743
  });
1744
+ /** A computed boolean: the record matched against a `where` predicate
1745
+ * (the same AND-of-conditions shape `dynamicIcon` uses; evaluated by
1746
+ * `./where`'s `matchesWhere`). Generic state summaries — isDone,
1747
+ * isPassed, isQualified — become declared fields, so every
1748
+ * field-driven mechanism (table cells, detail view, completion via
1749
+ * `completionField`) picks them up without special cases. Never
1750
+ * stored; computed by `deriveAll` on both server and client in the
1751
+ * same saturation loop as `derived`, so a flag may read derived /
1752
+ * rollup values — and other flags (`matchesWhere` stringifies, so
1753
+ * `eq "true"` composes). Deliberately a STRUCTURED field, not formula
1754
+ * syntax — the derived evaluator's no-string-literals boundary stays
1755
+ * untouched (same reasoning as `rollup`). Cross-record
1756
+ * `valueFrom.record` is rejected here: per-record evaluation has no
1757
+ * `recordsById`, so it could only ever silently never-match.
1758
+ * `where` condition fields are validated to exist by a schema-level
1759
+ * refine below (a field can't see its siblings). */
1760
+ var FlagFieldZ = zod.z.object({
1761
+ type: zod.z.literal("flag"),
1762
+ ...fieldBase,
1763
+ where: WhereZ.min(1)
1764
+ }).refine((spec) => spec.where.every((cond) => cond.valueFrom?.record === void 0), {
1765
+ message: "a flag's `where` cannot use `valueFrom.record` (cross-record references are unresolvable in per-record evaluation); use a literal `value` or a same-record `valueFrom` (field-to-field)",
1766
+ path: ["where"]
1767
+ });
1718
1768
  var FieldSpecZ = zod.z.discriminatedUnion("type", [
1719
1769
  ScalarFieldZ,
1720
1770
  RefFieldZ,
@@ -1725,7 +1775,8 @@ var FieldSpecZ = zod.z.discriminatedUnion("type", [
1725
1775
  EmbedFieldZ,
1726
1776
  BacklinksFieldZ,
1727
1777
  RollupFieldZ,
1728
- ToggleFieldZ
1778
+ ToggleFieldZ,
1779
+ FlagFieldZ
1729
1780
  ]);
1730
1781
  var actionBase = {
1731
1782
  id: zod.z.string().trim().min(1),
@@ -1874,32 +1925,6 @@ var AgentIngestZ = zod.z.object({
1874
1925
  * discovered from `<workspace>/feeds/` are REQUIRED to carry it (gated by
1875
1926
  * `acceptParsedSchema`). */
1876
1927
  var IngestZ = zod.z.discriminatedUnion("kind", [DeclarativeIngestZ, AgentIngestZ]);
1877
- var ValueRefZ = zod.z.object({
1878
- record: zod.z.string().trim().min(1).optional(),
1879
- field: zod.z.string().trim().min(1)
1880
- });
1881
- var WhereCondZ = zod.z.object({
1882
- field: zod.z.string().trim().min(1),
1883
- op: zod.z.enum([
1884
- "eq",
1885
- "ne",
1886
- "in",
1887
- "gt",
1888
- "gte",
1889
- "lt",
1890
- "lte",
1891
- "contains"
1892
- ]),
1893
- value: zod.z.union([zod.z.string(), zod.z.array(zod.z.string())]).optional(),
1894
- valueFrom: ValueRefZ.optional()
1895
- }).refine((cond) => cond.value !== void 0 !== (cond.valueFrom !== void 0), {
1896
- message: "a where condition must declare exactly one of `value` (a literal) or `valueFrom` (a reference to another record's field), never both or neither",
1897
- path: ["value"]
1898
- }).refine((cond) => cond.value === void 0 || cond.op === "in" === Array.isArray(cond.value), {
1899
- message: "`in` requires an array `value` (the allowed set); every other op requires a single string `value`",
1900
- path: ["value"]
1901
- });
1902
- var WhereZ = zod.z.array(WhereCondZ);
1903
1928
  var DynamicIconSourceZ = zod.z.object({
1904
1929
  collection: zod.z.string().trim().min(1),
1905
1930
  from: zod.z.enum([
@@ -1994,12 +2019,12 @@ function fieldDrivenFromFieldCarried(schema) {
1994
2019
  * workspace-relative and containment-checked exactly like `dataPath`. The
1995
2020
  * row-id column is the schema's existing `primaryKey` — there is
1996
2021
  * deliberately no second key concept here.
1997
- * See plans/feat-collection-csv-duckdb-source.md. */
2022
+ * See plans/done/feat-collection-csv-duckdb-source.md. */
1998
2023
  var DataSourceZ = zod.z.object({
1999
2024
  type: zod.z.literal("csv"),
2000
2025
  path: zod.z.string().min(1)
2001
2026
  });
2002
- var CollectionSchemaZ = zod.z.object({
2027
+ var BareCollectionSchemaZ = zod.z.object({
2003
2028
  title: zod.z.string().min(1),
2004
2029
  icon: zod.z.string().min(1),
2005
2030
  dataPath: zod.z.string().min(1).optional(),
@@ -2059,8 +2084,11 @@ var CollectionSchemaZ = zod.z.object({
2059
2084
  }).refine((schema) => collectCurrencyFieldRefs(schema.fields).every((name) => CODE_FIELD_TYPES.has(schema.fields[name]?.type ?? "")), {
2060
2085
  message: "a money field's `currencyField` must name a top-level `string`, `text`, or `enum` field that holds the currency code",
2061
2086
  path: ["fields"]
2062
- }).refine((schema) => schema.completionField === void 0 === (schema.completionDoneValues === void 0), {
2063
- message: "schema `completionField` and `completionDoneValues` must be declared together (both set, or both omitted)",
2087
+ }).refine((schema) => {
2088
+ if (schema.completionField !== void 0 && schema.fields[schema.completionField]?.type === "flag") return schema.completionDoneValues === void 0;
2089
+ return schema.completionField === void 0 === (schema.completionDoneValues === void 0);
2090
+ }, {
2091
+ message: "schema `completionField` and `completionDoneValues` must be declared together (both set, or both omitted) — unless `completionField` names a `flag` field, in which case `completionDoneValues` must be omitted (done ⇔ the flag matches)",
2064
2092
  path: ["completionField"]
2065
2093
  }).refine((schema) => schema.completionField === void 0 || schema.fields[schema.completionField] !== void 0, {
2066
2094
  message: "schema `completionField` must name a top-level field declared in `fields`",
@@ -2071,6 +2099,22 @@ var CollectionSchemaZ = zod.z.object({
2071
2099
  }).refine((schema) => Object.values(schema.fields).every((field) => field.when === void 0 || schema.fields[field.when.field] !== void 0), {
2072
2100
  message: "a field's `when.field` must name a top-level field declared in `fields`",
2073
2101
  path: ["fields"]
2102
+ }).refine((schema) => Object.values(schema.fields).every((field) => field.type !== "flag" || field.where.every((cond) => schema.fields[cond.field] !== void 0 && (cond.valueFrom === void 0 || schema.fields[cond.valueFrom.field] !== void 0))), {
2103
+ message: "a flag field's `where` conditions must name top-level fields declared in `fields` (both `field` and a same-record `valueFrom.field`)",
2104
+ path: ["fields"]
2105
+ }).refine((schema) => {
2106
+ const spec = schema.completionField === void 0 ? void 0 : schema.fields[schema.completionField];
2107
+ if (spec?.type !== "flag") return true;
2108
+ return spec.where.every((cond) => [cond.field, ...cond.valueFrom ? [cond.valueFrom.field] : []].every((name) => {
2109
+ const target = schema.fields[name];
2110
+ return target !== void 0 && !require_promptSafety.COMPUTED_TYPES.has(target.type);
2111
+ }));
2112
+ }, {
2113
+ message: "a `flag` named by `completionField` may only reference STORED fields in its `where` — completion is evaluated against the raw record (before deriveAll), where computed values (derived/rollup/toggle/flag/embed/backlinks) are absent",
2114
+ path: ["completionField"]
2115
+ }).refine((schema) => schema.spawn === void 0 || schema.spawn.when !== void 0 || schema.fields[schema.completionField ?? ""]?.type !== "flag", {
2116
+ message: "a schema whose `completionField` names a `flag` field must declare an explicit `spawn.when` (the spawn-inert check cannot statically evaluate a flag's `where`)",
2117
+ path: ["spawn"]
2074
2118
  }).refine((schema) => Object.values(schema.fields).every((field) => {
2075
2119
  if (field.type !== "embed" || field.idField === void 0) return true;
2076
2120
  const target = schema.fields[field.idField];
@@ -2145,6 +2189,46 @@ var CollectionSchemaZ = zod.z.object({
2145
2189
  message: "schema `views` must have unique `id`s",
2146
2190
  path: ["views"]
2147
2191
  });
2192
+ var PROTOTYPE_KEYS = [
2193
+ "__proto__",
2194
+ "constructor",
2195
+ "prototype"
2196
+ ];
2197
+ /** The first own prototype-sensitive key of `value`, or null. */
2198
+ function ownPrototypeKey(value) {
2199
+ if (value === null || typeof value !== "object") return null;
2200
+ for (const key of PROTOTYPE_KEYS) if (Object.hasOwn(value, key)) return key;
2201
+ return null;
2202
+ }
2203
+ /** Dotted path of the first prototype-sensitive field name in the raw
2204
+ * schema input — top-level `fields`, each table field's `of`, and each
2205
+ * action's `params` (the three records that DEFINE names) — or null. */
2206
+ function prototypeFieldKeyPath(input) {
2207
+ if (input === null || typeof input !== "object") return null;
2208
+ const schema = input;
2209
+ const bad = ownPrototypeKey(schema.fields);
2210
+ if (bad !== null) return `fields.${bad}`;
2211
+ for (const [key, spec] of Object.entries(schema.fields ?? {})) {
2212
+ const badSub = ownPrototypeKey(spec?.of);
2213
+ if (badSub !== null) return `fields.${key}.of.${badSub}`;
2214
+ }
2215
+ for (const [listName, list] of [["actions", schema.actions], ["collectionActions", schema.collectionActions]]) for (const action of Array.isArray(list) ? list : []) {
2216
+ const badParam = ownPrototypeKey(action?.params);
2217
+ if (badParam !== null) return `${listName}.params.${badParam}`;
2218
+ }
2219
+ return null;
2220
+ }
2221
+ var CollectionSchemaZ = zod.z.preprocess((input, ctx) => {
2222
+ const bad = prototypeFieldKeyPath(input);
2223
+ if (bad !== null) {
2224
+ ctx.addIssue({
2225
+ code: "custom",
2226
+ message: `'${bad}': field names must not be prototype-sensitive keys (\`__proto__\`, \`constructor\`, \`prototype\`)`
2227
+ });
2228
+ return zod.z.NEVER;
2229
+ }
2230
+ return input;
2231
+ }, BareCollectionSchemaZ);
2148
2232
  //#endregion
2149
2233
  //#region src/collection/server/discovery.ts
2150
2234
  function applyFeedSchemaDefaults(parsed, slug) {
@@ -2705,17 +2789,15 @@ function successorId(sourceId, next) {
2705
2789
  }
2706
2790
  /** True iff `item` satisfies the spawn predicate. With an explicit
2707
2791
  * `when`, matches `String(item[when.field]) ∈ when.in`. Without one,
2708
- * defaults to the completion-done condition. Self-contained (no import
2709
- * from notifications.ts) to keep the module graph acyclic. */
2792
+ * defaults to the completion-done condition the shared, flag-aware
2793
+ * `itemIsDone` (core/completion; downhill import, so the module graph
2794
+ * stays acyclic). */
2710
2795
  function matchesWhen(when, schema, item) {
2711
2796
  if (when) {
2712
2797
  const raw = item[when.field];
2713
2798
  return raw !== void 0 && raw !== null && when.in.includes(String(raw));
2714
2799
  }
2715
- const { completionField, completionDoneValues } = schema;
2716
- if (!completionField || !completionDoneValues) return false;
2717
- const raw = item[completionField];
2718
- return raw !== void 0 && raw !== null && completionDoneValues.includes(String(raw));
2800
+ return require_promptSafety.itemIsDone(schema, item);
2719
2801
  }
2720
2802
  /** Resolve the literal `every` that applies to `sourceItem`. Literal-arm
2721
2803
  * `spawn.every` passes through unchanged. Field-driven `spawn.every` reads
@@ -3965,4 +4047,4 @@ Object.defineProperty(exports, "writeItem", {
3965
4047
  }
3966
4048
  });
3967
4049
 
3968
- //# sourceMappingURL=server-Jaogu3Ky.cjs.map
4050
+ //# sourceMappingURL=server-CkysfLh4.cjs.map