@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,4 +1,4 @@
1
- import { B as isFieldDrivenEvery, C as backlinkRows, D as actionVisible, E as rollupValue, F as AGENT_INGEST_KIND, I as COMPUTED_TYPES, L as FEED_SCHEDULES, M as SAFE_SLUG_PATTERN, N as isSafeRecordId, P as isSafeSlug, R as INGEST_KINDS, T as projectBacklinkRow, V as isReadOnlySchema, b as resolveIcon, d as parseIsoDateTime, g as deriveAll, j as SAFE_RECORD_ID_PATTERN, t as defangForPrompt, u as parseIsoDate, w as coerceNumeric, x as selectDynamicRecord, y as firstDateField, z as embedTargetId } from "./promptSafety-rDWA9_JS.js";
1
+ import { B as embedTargetId, D as rollupValue, E as projectBacklinkRow, F as isSafeSlug, H as isReadOnlySchema, I as AGENT_INGEST_KIND, L as COMPUTED_TYPES, M as SAFE_RECORD_ID_PATTERN, N as SAFE_SLUG_PATTERN, O as actionVisible, P as isSafeRecordId, R as FEED_SCHEDULES, S as itemIsDone, T as coerceNumeric, V as isFieldDrivenEvery, b as resolveIcon, d as parseIsoDateTime, g as deriveAll, t as defangForPrompt, u as parseIsoDate, w as backlinkRows, x as selectDynamicRecord, y as firstDateField, z as INGEST_KINDS } from "./promptSafety-BLUcImzd.js";
2
2
  import { isSafeActionTemplatePath, isSafeCustomViewI18nPath, isSafeCustomViewPath } from "./collection/paths.js";
3
3
  import { dataSkillDir, mirrorSkillWrite } from "./skill-bridge/index.js";
4
4
  import path from "node:path";
@@ -1502,6 +1502,32 @@ var WhenZ = z.object({
1502
1502
  field: z.string().trim().min(1),
1503
1503
  in: z.array(z.string().trim().min(1)).min(1)
1504
1504
  });
1505
+ var ValueRefZ = z.object({
1506
+ record: z.string().trim().min(1).optional(),
1507
+ field: z.string().trim().min(1)
1508
+ });
1509
+ var WhereCondZ = z.object({
1510
+ field: z.string().trim().min(1),
1511
+ op: z.enum([
1512
+ "eq",
1513
+ "ne",
1514
+ "in",
1515
+ "gt",
1516
+ "gte",
1517
+ "lt",
1518
+ "lte",
1519
+ "contains"
1520
+ ]),
1521
+ value: z.union([z.string(), z.array(z.string())]).optional(),
1522
+ valueFrom: ValueRefZ.optional()
1523
+ }).refine((cond) => cond.value !== void 0 !== (cond.valueFrom !== void 0), {
1524
+ 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",
1525
+ path: ["value"]
1526
+ }).refine((cond) => cond.value === void 0 || cond.op === "in" === Array.isArray(cond.value), {
1527
+ message: "`in` requires an array `value` (the allowed set); every other op requires a single string `value`",
1528
+ path: ["value"]
1529
+ });
1530
+ var WhereZ = z.array(WhereCondZ);
1505
1531
  var fieldBase = {
1506
1532
  label: z.string().min(1),
1507
1533
  primary: z.boolean().optional(),
@@ -1712,6 +1738,30 @@ var ToggleFieldZ = z.object({
1712
1738
  onValue: z.string().trim().min(1),
1713
1739
  offValue: z.string().trim().min(1)
1714
1740
  });
1741
+ /** A computed boolean: the record matched against a `where` predicate
1742
+ * (the same AND-of-conditions shape `dynamicIcon` uses; evaluated by
1743
+ * `./where`'s `matchesWhere`). Generic state summaries — isDone,
1744
+ * isPassed, isQualified — become declared fields, so every
1745
+ * field-driven mechanism (table cells, detail view, completion via
1746
+ * `completionField`) picks them up without special cases. Never
1747
+ * stored; computed by `deriveAll` on both server and client in the
1748
+ * same saturation loop as `derived`, so a flag may read derived /
1749
+ * rollup values — and other flags (`matchesWhere` stringifies, so
1750
+ * `eq "true"` composes). Deliberately a STRUCTURED field, not formula
1751
+ * syntax — the derived evaluator's no-string-literals boundary stays
1752
+ * untouched (same reasoning as `rollup`). Cross-record
1753
+ * `valueFrom.record` is rejected here: per-record evaluation has no
1754
+ * `recordsById`, so it could only ever silently never-match.
1755
+ * `where` condition fields are validated to exist by a schema-level
1756
+ * refine below (a field can't see its siblings). */
1757
+ var FlagFieldZ = z.object({
1758
+ type: z.literal("flag"),
1759
+ ...fieldBase,
1760
+ where: WhereZ.min(1)
1761
+ }).refine((spec) => spec.where.every((cond) => cond.valueFrom?.record === void 0), {
1762
+ 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)",
1763
+ path: ["where"]
1764
+ });
1715
1765
  var FieldSpecZ = z.discriminatedUnion("type", [
1716
1766
  ScalarFieldZ,
1717
1767
  RefFieldZ,
@@ -1722,7 +1772,8 @@ var FieldSpecZ = z.discriminatedUnion("type", [
1722
1772
  EmbedFieldZ,
1723
1773
  BacklinksFieldZ,
1724
1774
  RollupFieldZ,
1725
- ToggleFieldZ
1775
+ ToggleFieldZ,
1776
+ FlagFieldZ
1726
1777
  ]);
1727
1778
  var actionBase = {
1728
1779
  id: z.string().trim().min(1),
@@ -1871,32 +1922,6 @@ var AgentIngestZ = z.object({
1871
1922
  * discovered from `<workspace>/feeds/` are REQUIRED to carry it (gated by
1872
1923
  * `acceptParsedSchema`). */
1873
1924
  var IngestZ = z.discriminatedUnion("kind", [DeclarativeIngestZ, AgentIngestZ]);
1874
- var ValueRefZ = z.object({
1875
- record: z.string().trim().min(1).optional(),
1876
- field: z.string().trim().min(1)
1877
- });
1878
- var WhereCondZ = z.object({
1879
- field: z.string().trim().min(1),
1880
- op: z.enum([
1881
- "eq",
1882
- "ne",
1883
- "in",
1884
- "gt",
1885
- "gte",
1886
- "lt",
1887
- "lte",
1888
- "contains"
1889
- ]),
1890
- value: z.union([z.string(), z.array(z.string())]).optional(),
1891
- valueFrom: ValueRefZ.optional()
1892
- }).refine((cond) => cond.value !== void 0 !== (cond.valueFrom !== void 0), {
1893
- 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",
1894
- path: ["value"]
1895
- }).refine((cond) => cond.value === void 0 || cond.op === "in" === Array.isArray(cond.value), {
1896
- message: "`in` requires an array `value` (the allowed set); every other op requires a single string `value`",
1897
- path: ["value"]
1898
- });
1899
- var WhereZ = z.array(WhereCondZ);
1900
1925
  var DynamicIconSourceZ = z.object({
1901
1926
  collection: z.string().trim().min(1),
1902
1927
  from: z.enum([
@@ -1991,12 +2016,12 @@ function fieldDrivenFromFieldCarried(schema) {
1991
2016
  * workspace-relative and containment-checked exactly like `dataPath`. The
1992
2017
  * row-id column is the schema's existing `primaryKey` — there is
1993
2018
  * deliberately no second key concept here.
1994
- * See plans/feat-collection-csv-duckdb-source.md. */
2019
+ * See plans/done/feat-collection-csv-duckdb-source.md. */
1995
2020
  var DataSourceZ = z.object({
1996
2021
  type: z.literal("csv"),
1997
2022
  path: z.string().min(1)
1998
2023
  });
1999
- var CollectionSchemaZ = z.object({
2024
+ var BareCollectionSchemaZ = z.object({
2000
2025
  title: z.string().min(1),
2001
2026
  icon: z.string().min(1),
2002
2027
  dataPath: z.string().min(1).optional(),
@@ -2056,8 +2081,11 @@ var CollectionSchemaZ = z.object({
2056
2081
  }).refine((schema) => collectCurrencyFieldRefs(schema.fields).every((name) => CODE_FIELD_TYPES.has(schema.fields[name]?.type ?? "")), {
2057
2082
  message: "a money field's `currencyField` must name a top-level `string`, `text`, or `enum` field that holds the currency code",
2058
2083
  path: ["fields"]
2059
- }).refine((schema) => schema.completionField === void 0 === (schema.completionDoneValues === void 0), {
2060
- message: "schema `completionField` and `completionDoneValues` must be declared together (both set, or both omitted)",
2084
+ }).refine((schema) => {
2085
+ if (schema.completionField !== void 0 && schema.fields[schema.completionField]?.type === "flag") return schema.completionDoneValues === void 0;
2086
+ return schema.completionField === void 0 === (schema.completionDoneValues === void 0);
2087
+ }, {
2088
+ 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)",
2061
2089
  path: ["completionField"]
2062
2090
  }).refine((schema) => schema.completionField === void 0 || schema.fields[schema.completionField] !== void 0, {
2063
2091
  message: "schema `completionField` must name a top-level field declared in `fields`",
@@ -2068,6 +2096,22 @@ var CollectionSchemaZ = z.object({
2068
2096
  }).refine((schema) => Object.values(schema.fields).every((field) => field.when === void 0 || schema.fields[field.when.field] !== void 0), {
2069
2097
  message: "a field's `when.field` must name a top-level field declared in `fields`",
2070
2098
  path: ["fields"]
2099
+ }).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))), {
2100
+ message: "a flag field's `where` conditions must name top-level fields declared in `fields` (both `field` and a same-record `valueFrom.field`)",
2101
+ path: ["fields"]
2102
+ }).refine((schema) => {
2103
+ const spec = schema.completionField === void 0 ? void 0 : schema.fields[schema.completionField];
2104
+ if (spec?.type !== "flag") return true;
2105
+ return spec.where.every((cond) => [cond.field, ...cond.valueFrom ? [cond.valueFrom.field] : []].every((name) => {
2106
+ const target = schema.fields[name];
2107
+ return target !== void 0 && !COMPUTED_TYPES.has(target.type);
2108
+ }));
2109
+ }, {
2110
+ 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",
2111
+ path: ["completionField"]
2112
+ }).refine((schema) => schema.spawn === void 0 || schema.spawn.when !== void 0 || schema.fields[schema.completionField ?? ""]?.type !== "flag", {
2113
+ 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`)",
2114
+ path: ["spawn"]
2071
2115
  }).refine((schema) => Object.values(schema.fields).every((field) => {
2072
2116
  if (field.type !== "embed" || field.idField === void 0) return true;
2073
2117
  const target = schema.fields[field.idField];
@@ -2142,6 +2186,46 @@ var CollectionSchemaZ = z.object({
2142
2186
  message: "schema `views` must have unique `id`s",
2143
2187
  path: ["views"]
2144
2188
  });
2189
+ var PROTOTYPE_KEYS = [
2190
+ "__proto__",
2191
+ "constructor",
2192
+ "prototype"
2193
+ ];
2194
+ /** The first own prototype-sensitive key of `value`, or null. */
2195
+ function ownPrototypeKey(value) {
2196
+ if (value === null || typeof value !== "object") return null;
2197
+ for (const key of PROTOTYPE_KEYS) if (Object.hasOwn(value, key)) return key;
2198
+ return null;
2199
+ }
2200
+ /** Dotted path of the first prototype-sensitive field name in the raw
2201
+ * schema input — top-level `fields`, each table field's `of`, and each
2202
+ * action's `params` (the three records that DEFINE names) — or null. */
2203
+ function prototypeFieldKeyPath(input) {
2204
+ if (input === null || typeof input !== "object") return null;
2205
+ const schema = input;
2206
+ const bad = ownPrototypeKey(schema.fields);
2207
+ if (bad !== null) return `fields.${bad}`;
2208
+ for (const [key, spec] of Object.entries(schema.fields ?? {})) {
2209
+ const badSub = ownPrototypeKey(spec?.of);
2210
+ if (badSub !== null) return `fields.${key}.of.${badSub}`;
2211
+ }
2212
+ for (const [listName, list] of [["actions", schema.actions], ["collectionActions", schema.collectionActions]]) for (const action of Array.isArray(list) ? list : []) {
2213
+ const badParam = ownPrototypeKey(action?.params);
2214
+ if (badParam !== null) return `${listName}.params.${badParam}`;
2215
+ }
2216
+ return null;
2217
+ }
2218
+ var CollectionSchemaZ = z.preprocess((input, ctx) => {
2219
+ const bad = prototypeFieldKeyPath(input);
2220
+ if (bad !== null) {
2221
+ ctx.addIssue({
2222
+ code: "custom",
2223
+ message: `'${bad}': field names must not be prototype-sensitive keys (\`__proto__\`, \`constructor\`, \`prototype\`)`
2224
+ });
2225
+ return z.NEVER;
2226
+ }
2227
+ return input;
2228
+ }, BareCollectionSchemaZ);
2145
2229
  //#endregion
2146
2230
  //#region src/collection/server/discovery.ts
2147
2231
  function applyFeedSchemaDefaults(parsed, slug) {
@@ -2702,17 +2786,15 @@ function successorId(sourceId, next) {
2702
2786
  }
2703
2787
  /** True iff `item` satisfies the spawn predicate. With an explicit
2704
2788
  * `when`, matches `String(item[when.field]) ∈ when.in`. Without one,
2705
- * defaults to the completion-done condition. Self-contained (no import
2706
- * from notifications.ts) to keep the module graph acyclic. */
2789
+ * defaults to the completion-done condition the shared, flag-aware
2790
+ * `itemIsDone` (core/completion; downhill import, so the module graph
2791
+ * stays acyclic). */
2707
2792
  function matchesWhen(when, schema, item) {
2708
2793
  if (when) {
2709
2794
  const raw = item[when.field];
2710
2795
  return raw !== void 0 && raw !== null && when.in.includes(String(raw));
2711
2796
  }
2712
- const { completionField, completionDoneValues } = schema;
2713
- if (!completionField || !completionDoneValues) return false;
2714
- const raw = item[completionField];
2715
- return raw !== void 0 && raw !== null && completionDoneValues.includes(String(raw));
2797
+ return itemIsDone(schema, item);
2716
2798
  }
2717
2799
  /** Resolve the literal `every` that applies to `sourceItem`. Literal-arm
2718
2800
  * `spawn.every` passes through unchanged. Field-driven `spawn.every` reads
@@ -3507,4 +3589,4 @@ function makeManageCollectionTool(deps = {}) {
3507
3589
  //#endregion
3508
3590
  export { isRegularFile as $, validateCollectionRecords as A, decodeCsvRecordId as B, discoverCollections as C, CollectionSchemaZ as D, toSummary as E, collectionWritable as F, compileJsonlQuery as G, encodeCsvRecordId as H, readOnlyRefusal as I, MAX_QUERY_ROWS as J, CollectionQueryZ as K, storeFor as L, compileRecordZ as M, recordFieldProblem as N, applyMutateAction as O, runQueryOverRows as P, generateItemId as Q, MAX_CSV_ROWS as R, acceptParsedSchema as S, setCollectionChangePublisher as St, toDetail as T, normalizeCsvValue as U, dedupeByRecordId as V, compileCsvQuery as W, buildCollectionActionSeedPrompt as X, buildActionSeedPrompt as Y, deleteItem as Z, errorMessage as _, collectionsRegistriesConfigPath as _t, deleteCollection as a, readSkillTemplate as at, buildWorkspaceOntology as b, log as bt, computeSuccessor as c, writeFileAtomic as ct, isTriggerDue as d, isContainedInWorkspace as dt, listItems as et, maybeSpawnSuccessor as f, itemFilePath as ft, ONE_SECOND_MS as g, safeSlugName as gt, successorId as h, safeRecordId as ht, deleteCustomView as i, readItem as it, validateRecordObject as j, firstMutateParamProblem as k, daysInMonth as l, SCHEMA_FILE$1 as lt, resolveEvery as m, resolveTemplatePath as mt, MAX_UNSELECTIVE_ITEMS as n, readCustomViewHtml as nt, deleteCollectionRefusalMessage as o, resolveCreateItemId as ot, parseCivil as p, resolveDataDir as pt, DEFAULT_QUERY_ROWS as q, makeManageCollectionTool as r, readCustomViewI18n as rt, advanceTriggerDate as s, writeItem as st, MAX_SCHEMA_ISSUES as t, promptPathsFor as tt, formatCivil as u, isContainedInRoot as ut, computeCollectionIcon as v, configureCollectionHost as vt, loadCollection as w, schemaRelations as x, publishCollectionChange as xt, enrichItems as y, getWorkspaceRoot as yt, csvRowToItem as z };
3509
3591
 
3510
- //# sourceMappingURL=server-D2ibbixF.js.map
3592
+ //# sourceMappingURL=server-BpEo0FOd.js.map