@mulmoclaude/collection-plugin 0.5.2 → 0.5.6

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 (36) hide show
  1. package/dist/core/schema.d.ts +24 -2
  2. package/dist/core/schema.d.ts.map +1 -1
  3. package/dist/index.cjs +2 -1
  4. package/dist/index.js +2 -2
  5. package/dist/{schema-LrmrgW12.cjs → schema-5P5ZJPrY.cjs} +11 -1
  6. package/dist/schema-5P5ZJPrY.cjs.map +1 -0
  7. package/dist/{schema-DyfSfVzh.js → schema-BcnitlL8.js} +6 -2
  8. package/dist/schema-BcnitlL8.js.map +1 -0
  9. package/dist/server/discovery.d.ts +14 -2
  10. package/dist/server/discovery.d.ts.map +1 -1
  11. package/dist/server/host.d.ts +25 -0
  12. package/dist/server/host.d.ts.map +1 -1
  13. package/dist/server/index.d.ts +1 -1
  14. package/dist/server/index.d.ts.map +1 -1
  15. package/dist/server/io.d.ts +6 -0
  16. package/dist/server/io.d.ts.map +1 -1
  17. package/dist/server/spawn.d.ts +8 -1
  18. package/dist/server/spawn.d.ts.map +1 -1
  19. package/dist/server.cjs +117 -17
  20. package/dist/server.cjs.map +1 -1
  21. package/dist/server.js +115 -18
  22. package/dist/server.js.map +1 -1
  23. package/dist/style.css +3 -3
  24. package/dist/vue/components/CollectionCustomView.vue.d.ts +19 -1
  25. package/dist/vue/components/CollectionCustomView.vue.d.ts.map +1 -1
  26. package/dist/vue/components/CollectionRecordPanel.vue.d.ts +2 -2
  27. package/dist/vue/components/CollectionView.vue.d.ts.map +1 -1
  28. package/dist/vue/uiContext.d.ts +12 -0
  29. package/dist/vue/uiContext.d.ts.map +1 -1
  30. package/dist/vue.cjs +144 -4
  31. package/dist/vue.cjs.map +1 -1
  32. package/dist/vue.js +145 -5
  33. package/dist/vue.js.map +1 -1
  34. package/package.json +2 -2
  35. package/dist/schema-DyfSfVzh.js.map +0 -1
  36. package/dist/schema-LrmrgW12.cjs.map +0 -1
@@ -41,6 +41,27 @@ export interface CollectionEvery {
41
41
  * Ignored for `day`/`week` units. */
42
42
  dayOfMonth?: number | "last";
43
43
  }
44
+ /** Field-driven recurrence: the advance interval is selected PER RECORD by
45
+ * the value of an `enum` field (`fromField`), looked up in `map`. Lets one
46
+ * collection mix daily / weekly / monthly obligations in a single list — the
47
+ * host reads `record[fromField]`, finds the matching `CollectionEvery`, and
48
+ * advances by it. `fromField` must point at a top-level `enum` field whose
49
+ * `values` the `map` keys exactly cover (validated at discovery), and must
50
+ * itself be carried/`set` onto the successor so the chain keeps recurring. */
51
+ export interface CollectionEveryFieldDriven {
52
+ /** Top-level `enum` field whose value selects the interval. */
53
+ fromField: string;
54
+ /** Interval per enum value. Keys exactly cover `fromField`'s `values`;
55
+ * each value is a literal {@link CollectionEvery}. */
56
+ map: Record<string, CollectionEvery>;
57
+ }
58
+ /** The `every` of a `spawn`: either a single literal interval applied to
59
+ * every record, or a per-record interval selected by an `enum` field. The
60
+ * literal arm is what `advanceTriggerDate` consumes — the field-driven arm
61
+ * is resolved down to one of its `map` values before the date math runs. */
62
+ export type CollectionSpawnEvery = CollectionEvery | CollectionEveryFieldDriven;
63
+ /** Narrowing guard: true when `every` is the field-driven arm. */
64
+ export declare function isFieldDrivenEvery(every: CollectionSpawnEvery): every is CollectionEveryFieldDriven;
44
65
  /** Host-driven recurrence: when a record satisfies `when`, the host
45
66
  * creates the next record with a forward-advanced `triggerField` date.
46
67
  * The successor's id and contents are a pure function of (source
@@ -52,8 +73,9 @@ export interface CollectionSpawn {
52
73
  * "`completionField` value ∈ `completionDoneValues`" (i.e. spawn the
53
74
  * next instance when this one is done). */
54
75
  when?: CollectionWhen;
55
- /** How to advance `triggerField` from the source to the successor. */
56
- every: CollectionEvery;
76
+ /** How to advance `triggerField` from the source to the successor
77
+ * either a single literal interval or a per-record, field-driven map. */
78
+ every: CollectionSpawnEvery;
57
79
  /** Record fields copied verbatim onto the successor. Fields not listed
58
80
  * here, not in `set`, and not the trigger / primary keys start
59
81
  * blank. */
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_schema = require("./schema-LrmrgW12.cjs");
2
+ const require_schema = require("./schema-5P5ZJPrY.cjs");
3
3
  const require_promptSafety = require("./promptSafety-B0pPJkfQ.cjs");
4
4
  const require_deriveAll = require("./deriveAll-BJ0Lvm1Q.cjs");
5
5
  exports.ENUM_ALERT = require_promptSafety.ENUM_ALERT;
@@ -34,6 +34,7 @@ exports.evaluateDerived = require_deriveAll.evaluateDerived;
34
34
  exports.executePresentCollection = require_promptSafety.executePresentCollection;
35
35
  exports.fieldVisible = require_promptSafety.fieldVisible;
36
36
  exports.firstMissingRequiredField = require_promptSafety.firstMissingRequiredField;
37
+ exports.isFieldDrivenEvery = require_schema.isFieldDrivenEvery;
37
38
  exports.isSortableField = require_promptSafety.isSortableField;
38
39
  exports.itemIdOf = require_promptSafety.itemIdOf;
39
40
  exports.itemLabelOf = require_promptSafety.itemLabelOf;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { n as INGEST_KINDS, t as FEED_SCHEDULES } from "./schema-DyfSfVzh.js";
1
+ import { n as INGEST_KINDS, r as isFieldDrivenEvery, t as FEED_SCHEDULES } from "./schema-BcnitlL8.js";
2
2
  import { A as buildUpdatedRecord, B as ENUM_NEUTRAL, C as dateSortValue, D as numericSortValue, E as nextSortDirection, F as rowFromItem, G as TOOL_DEFINITION, H as enumColorClasses, I as actionVisible, K as TOOL_NAME, L as fieldVisible, M as draftToRecord, N as emptyRow, O as sortItems, P as firstMissingRequiredField, R as whenMatches, S as compareSortValues, T as isSortableField, U as enumValueIndex, V as ENUM_NUDGE, W as resolveEnumColor, _ as ymdKey, a as assignLanes, b as labelFieldFor, c as compareYmd, d as monthAnchorDate, f as parseIsoDate, g as spanCoversDay, h as recordSpan, i as MINUTES_PER_DAY, j as coerceInlineValue, k as stringSortValue, l as dateOf, m as parseTimeRange, n as shortHexId, o as bucketRecords, p as parseIsoDateTime, q as executePresentCollection, r as errorMessage, s as buildMonthGrid, t as defangForPrompt, u as daySlice, v as itemIdOf, w as enumSortValue, x as boolSortValue, y as itemLabelOf, z as ENUM_ALERT } from "./promptSafety-DIQ2yDca.js";
3
3
  import { n as resolveRowRefs, r as evaluateDerived, t as deriveAll } from "./deriveAll-BHcs1erT.js";
4
- export { ENUM_ALERT, ENUM_NEUTRAL, ENUM_NUDGE, FEED_SCHEDULES, INGEST_KINDS, MINUTES_PER_DAY, TOOL_DEFINITION, TOOL_NAME, actionVisible, assignLanes, boolSortValue, bucketRecords, buildMonthGrid, buildUpdatedRecord, coerceInlineValue, compareSortValues, compareYmd, dateOf, dateSortValue, daySlice, defangForPrompt, deriveAll, draftToRecord, emptyRow, enumColorClasses, enumSortValue, enumValueIndex, errorMessage, evaluateDerived, executePresentCollection, fieldVisible, firstMissingRequiredField, isSortableField, itemIdOf, itemLabelOf, labelFieldFor, monthAnchorDate, nextSortDirection, numericSortValue, parseIsoDate, parseIsoDateTime, parseTimeRange, recordSpan, resolveEnumColor, resolveRowRefs, rowFromItem, shortHexId, sortItems, spanCoversDay, stringSortValue, whenMatches, ymdKey };
4
+ export { ENUM_ALERT, ENUM_NEUTRAL, ENUM_NUDGE, FEED_SCHEDULES, INGEST_KINDS, MINUTES_PER_DAY, TOOL_DEFINITION, TOOL_NAME, actionVisible, assignLanes, boolSortValue, bucketRecords, buildMonthGrid, buildUpdatedRecord, coerceInlineValue, compareSortValues, compareYmd, dateOf, dateSortValue, daySlice, defangForPrompt, deriveAll, draftToRecord, emptyRow, enumColorClasses, enumSortValue, enumValueIndex, errorMessage, evaluateDerived, executePresentCollection, fieldVisible, firstMissingRequiredField, isFieldDrivenEvery, isSortableField, itemIdOf, itemLabelOf, labelFieldFor, monthAnchorDate, nextSortDirection, numericSortValue, parseIsoDate, parseIsoDateTime, parseTimeRange, recordSpan, resolveEnumColor, resolveRowRefs, rowFromItem, shortHexId, sortItems, spanCoversDay, stringSortValue, whenMatches, ymdKey };
@@ -15,6 +15,10 @@ var FEED_SCHEDULES = [
15
15
  "weekly",
16
16
  "on-demand"
17
17
  ];
18
+ /** Narrowing guard: true when `every` is the field-driven arm. */
19
+ function isFieldDrivenEvery(every) {
20
+ return "fromField" in every;
21
+ }
18
22
  //#endregion
19
23
  Object.defineProperty(exports, "FEED_SCHEDULES", {
20
24
  enumerable: true,
@@ -28,5 +32,11 @@ Object.defineProperty(exports, "INGEST_KINDS", {
28
32
  return INGEST_KINDS;
29
33
  }
30
34
  });
35
+ Object.defineProperty(exports, "isFieldDrivenEvery", {
36
+ enumerable: true,
37
+ get: function() {
38
+ return isFieldDrivenEvery;
39
+ }
40
+ });
31
41
 
32
- //# sourceMappingURL=schema-LrmrgW12.cjs.map
42
+ //# sourceMappingURL=schema-5P5ZJPrY.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-5P5ZJPrY.cjs","names":[],"sources":["../src/core/schema.ts"],"sourcesContent":["// Schema-driven collection types. A \"collection\" is a skill (under\n// .claude/skills/<slug>/) that also ships a sibling `schema.json`.\n// The host's <CollectionView> reads the schema + records and renders\n// a table/form; Claude reads SKILL.md and CRUDs the records as JSON\n// files.\n//\n// Field types for v0 — keep this list narrow and grow it only when a\n// real collection needs the new type. v0 supports flat records only;\n// nested tables / cross-collection refs / derived fields / actions are\n// deferred to follow-ups (see plans/done/feat-skill-driven-apps.md and\n// plans/done/feat-skill-driven-apps-worklog.md — historical names predate\n// the rename).\n\n/** Minimal \"this collection is a feed\" descriptor carried on the schema.\n * Deliberately narrow — the canonical collection contract stays\n * independent of the host's feeds subsystem. The host's richer retrieval\n * spec (`IngestSpec` in `server/workspace/feeds/ingestTypes.ts`)\n * `extends CollectionIngest`, so feed code reads the extra fields by\n * typing feed schemas with that subtype; collection rendering only needs\n * these three + the presence check. */\nexport interface CollectionIngest {\n kind: string;\n url: string;\n schedule: string;\n}\n\n/** Retriever kinds a Feed's `ingest.kind` may declare. The host's feeds engine\n * dispatches on these; they live here (with the schema contract) so the schema\n * validator can enforce them. The host re-exports these from\n * `server/workspace/feeds/ingestTypes.ts`. */\nexport const INGEST_KINDS = [\"rss\", \"atom\", \"http-json\"] as const;\nexport type IngestKind = (typeof INGEST_KINDS)[number];\n\n/** Refresh cadences a Feed's `ingest.schedule` may declare. */\nexport const FEED_SCHEDULES = [\"hourly\", \"daily\", \"weekly\", \"on-demand\"] as const;\nexport type FeedSchedule = (typeof FEED_SCHEDULES)[number];\n\nexport type CollectionFieldType =\n | \"string\"\n | \"text\"\n | \"email\"\n | \"number\"\n | \"date\"\n | \"datetime\"\n | \"boolean\"\n | \"markdown\"\n | \"ref\"\n | \"money\"\n | \"enum\"\n | \"table\"\n | \"derived\"\n | \"embed\"\n // Holds a workspace-relative image path (e.g. a `data/attachments/...`\n // upload); rendered as an <img> in the detail view (not the list table —\n // a per-row fetch is too expensive at scale). Stored and edited as a\n // plain string.\n | \"image\"\n // Holds a workspace-relative file path as a plain string (e.g. an\n // `artifacts/html/<name>.html` app). Rendered as a clickable link in\n // both the list table and the detail view: HTML / SVG artifacts open\n // their rendered form in a new tab; any other path opens in the File\n // Explorer. Stored and edited as a plain string, like `image`.\n | \"file\"\n // A checkbox that is a pure PROJECTION of an `enum` field — it stores\n // nothing of its own. Checked when the enum equals `onValue`; toggling\n // writes `onValue` / `offValue` back to that enum field. Lets a \"done\"\n // checkbox front a kanban `status` field with the enum as the single\n // source of truth (no separate stored boolean to keep in sync).\n | \"toggle\";\n\n// \"feed\" collections live in the non-skill `<workspace>/feeds/` registry\n// and carry an `ingest` block; they reuse the same storage + rendering\n// as skill-backed collections but are never loaded into the agent prompt.\nexport type CollectionSource = \"user\" | \"project\" | \"feed\";\n\n/** Recurrence unit for a `spawn.every` advance. */\nexport type CollectionRecurUnit = \"day\" | \"week\" | \"month\" | \"year\";\n\n/** How a `spawn` advances the source item's `triggerField` date to\n * produce the successor's. All arithmetic is done on the civil\n * (year, month, day) triple — never by adding milliseconds — so month\n * lengths and leap years are handled correctly. */\nexport interface CollectionEvery {\n unit: CollectionRecurUnit;\n /** Number of `unit`s to advance (≥ 1). `interval: 3` + `unit: \"month\"`\n * = quarterly; `interval: 1` + `unit: \"year\"` = annual. */\n interval: number;\n /** Day-of-month anchor for `month`/`year` units. The CANONICAL day —\n * read from the rule, never re-derived from the prior concrete date,\n * so \"31st of every month\" yields 31 → 28/29 → 31 → 30 … with no\n * drift (it is clamped per-month at compute time, not stored\n * clamped). `\"last\"` always means the last day of the target month.\n * Omitted ⇒ preserve the source date's day (safe for days ≤ 28).\n * Ignored for `day`/`week` units. */\n dayOfMonth?: number | \"last\";\n}\n\n/** Field-driven recurrence: the advance interval is selected PER RECORD by\n * the value of an `enum` field (`fromField`), looked up in `map`. Lets one\n * collection mix daily / weekly / monthly obligations in a single list — the\n * host reads `record[fromField]`, finds the matching `CollectionEvery`, and\n * advances by it. `fromField` must point at a top-level `enum` field whose\n * `values` the `map` keys exactly cover (validated at discovery), and must\n * itself be carried/`set` onto the successor so the chain keeps recurring. */\nexport interface CollectionEveryFieldDriven {\n /** Top-level `enum` field whose value selects the interval. */\n fromField: string;\n /** Interval per enum value. Keys exactly cover `fromField`'s `values`;\n * each value is a literal {@link CollectionEvery}. */\n map: Record<string, CollectionEvery>;\n}\n\n/** The `every` of a `spawn`: either a single literal interval applied to\n * every record, or a per-record interval selected by an `enum` field. The\n * literal arm is what `advanceTriggerDate` consumes — the field-driven arm\n * is resolved down to one of its `map` values before the date math runs. */\nexport type CollectionSpawnEvery = CollectionEvery | CollectionEveryFieldDriven;\n\n/** Narrowing guard: true when `every` is the field-driven arm. */\nexport function isFieldDrivenEvery(every: CollectionSpawnEvery): every is CollectionEveryFieldDriven {\n return \"fromField\" in every;\n}\n\n/** Host-driven recurrence: when a record satisfies `when`, the host\n * creates the next record with a forward-advanced `triggerField` date.\n * The successor's id and contents are a pure function of (source\n * record, this rule); creation is create-if-absent, so the mechanism\n * stays convergent — observing the predicate N times writes one\n * successor. Requires the schema to declare `triggerField`. */\nexport interface CollectionSpawn {\n /** Predicate that fires the spawn (a `CollectionWhen`). Defaults to\n * \"`completionField` value ∈ `completionDoneValues`\" (i.e. spawn the\n * next instance when this one is done). */\n when?: CollectionWhen;\n /** How to advance `triggerField` from the source to the successor —\n * either a single literal interval or a per-record, field-driven map. */\n every: CollectionSpawnEvery;\n /** Record fields copied verbatim onto the successor. Fields not listed\n * here, not in `set`, and not the trigger / primary keys start\n * blank. */\n carry?: string[];\n /** Fields forced to fixed values on the successor (typically resetting\n * the status field to its pending value). */\n set?: Record<string, unknown>;\n}\n\n/** The kind of work an action kicks off. v1 ships only `\"chat\"` —\n * start a new chat in a role with a templated seed prompt. The enum\n * reserves room for a future `\"mutate\"` (status transitions) without\n * another schema-shape change. */\nexport type CollectionActionKind = \"chat\";\n\n/** Optional visibility predicate: the target (an action button or a\n * field) renders only when the open record's `field` (stringified) is\n * one of `in`. Generic and domain-free — the host evaluates it against\n * the record with no knowledge of what the field means. Absent ⇒\n * always shown. */\nexport interface CollectionWhen {\n /** Top-level record field key whose value gates visibility. */\n field: string;\n /** Allowed values; the target shows when `String(record[field])` is\n * one of these. Non-empty. */\n in: string[];\n}\n\n/** @deprecated Name retained for back-compat; use {@link CollectionWhen}.\n * Both actions and fields share the same predicate shape. */\nexport type CollectionActionWhen = CollectionWhen;\n\n/** What a custom view's capability token is allowed to do against the\n * collection's data endpoint. `read` returns enriched records (getItems\n * semantics); `write` validates-and-stores rows (putItems semantics).\n * There is deliberately no `delete` — a view can never do more than the\n * agent's own `manageCollection` tool. */\nexport type CollectionViewCapability = \"read\" | \"write\";\n\n/** A custom (LLM-authored) HTML view for a collection. The host renders\n * `file` in a sandboxed iframe over the collection's records; the view\n * reaches its data only through a slug- and capability-scoped token (see\n * `server/api/auth/viewToken.ts`). Pure data — the host holds no\n * view-specific code; meaning lives in the HTML file + this registration. */\nexport interface CollectionCustomView {\n /** Stable id; the view-mode selector key (`custom:<id>`) and the\n * capability-token clamp key. Must be a valid slug. */\n id: string;\n /** Button label in the view-mode selector (author-authored, like field\n * labels — not run through i18n). */\n label: string;\n /** Optional Material-icon name for the selector button. */\n icon?: string;\n /** Skill-relative path to the HTML file under `views/` (e.g.\n * `views/year.html`). Path-safe, must end in `.html`. */\n file: string;\n /** What the view may do with the data endpoint. Defaults to `[\"read\"]`\n * (least privilege); declare `[\"read\",\"write\"]` only for views that\n * edit records. The mint endpoint clamps any requested caps to this. */\n capabilities?: CollectionViewCapability[];\n}\n\n/** A schema-declared, per-record action rendered as a button in the\n * read-only detail view. Pure UI/behaviour directive — never stored,\n * never validated against record data. All domain specifics (label,\n * role, template) live here in the schema / skill folder, so the host\n * stays generic. */\nexport interface CollectionAction {\n /** Stable id (used in the dispatch route + testids). */\n id: string;\n /** Button text (English, like field labels). */\n label: string;\n /** Material-icon name shown on the button. */\n icon?: string;\n /** What the action does. v1: `\"chat\"`. */\n kind: CollectionActionKind;\n /** `kind: \"chat\"`: the role id the new chat runs in. */\n role: string;\n /** `kind: \"chat\"`: skill-relative path to the template file whose\n * text becomes the seed prompt body (e.g. `templates/invoice.md`). */\n template: string;\n /** Optional visibility predicate; the button renders only when the\n * open record matches (see CollectionWhen). Absent ⇒ always\n * shown. */\n when?: CollectionWhen;\n}\n\nexport interface CollectionFieldSpec {\n type: CollectionFieldType;\n label: string;\n /** True for the field whose value is the record's filename (no\n * separate auto-id). Exactly one field per schema may set this. */\n primary?: boolean;\n required?: boolean;\n /** When `type === \"ref\"` or `type === \"embed\"`: the slug of the\n * target collection. For `ref` the record stores the target\n * item's primary-key slug and the host renders a clickable link\n * + dropdown picker. For `embed` the host pulls a *fixed* record\n * (see `id`) from the target and renders its fields read-only in\n * the detail view. Required for both; ignored on every other\n * type. */\n to?: string;\n /** When `type === \"embed\"`: the primary-key value of the fixed\n * record to pull from the `to` collection (e.g. `me` for the\n * singleton mc-profile). Nothing is stored on this record — the\n * embed is a display-only directive resolved at render time, so\n * it never appears in the list table or the edit form. Required\n * when type is `embed`; ignored on every other type. */\n id?: string;\n /** When `type === \"money\"` (or `type === \"derived\"` with\n * `display: \"money\"`): a literal ISO 4217 currency code passed to\n * `Intl.NumberFormat` for display — fixed for every record. The\n * stored value is always a plain decimal number; currency is\n * presentation only. Mutually substitutable with `currencyField`:\n * a money field must declare at least one of the two. */\n currency?: string;\n /** When `type === \"money\"` (or `type === \"derived\"` with\n * `display: \"money\"`): the name of a sibling record field whose\n * value holds the ISO 4217 code, letting currency vary per record\n * (e.g. an invoice's `currency` enum). The renderer reads\n * `record[currencyField]` and falls back to the literal `currency`\n * (then \"USD\") when the field is absent or empty. Resolved against\n * the top-level record even for money sub-fields inside a table. */\n currencyField?: string;\n /** When `type === \"enum\"`: the closed set of allowed string\n * values. The form renders a `<select>` populated from this\n * list; storage is a plain string. Required when type is\n * `enum`; ignored on every other type. */\n values?: readonly string[];\n /** When `type === \"table\"`: the sub-schema for each row (a flat\n * record of non-table / non-derived field specs). Required when\n * type is `table`. v0 disallows nested tables and derived\n * columns to keep the editor + evaluator simple. */\n of?: Record<string, CollectionFieldSpec>;\n /** When `type === \"derived\"`: a tiny expression evaluated against\n * the record. Supports `+ - * /`, parens, identifier refs to\n * top-level fields, `sum(tableField[].col)`, and\n * `sum(tableField[].col * tableField[].col)`. See\n * `src/utils/collections/derivedFormula.ts`. Required when type\n * is `derived`. */\n formula?: string;\n /** When `type === \"derived\"`: an inner field type the computed\n * value should be rendered as (e.g. `\"money\"` so $1,234.56 is\n * formatted). Defaults to `\"number\"`. */\n display?: CollectionFieldType;\n /** Optional visibility predicate: this field renders only when the\n * record matches (e.g. hide a `rating` field until `visited` is\n * `true` via `{ field: \"visited\", in: [\"true\"] }`). Applies to the\n * list cell (blank when hidden), the edit form (hidden live as the\n * gating field changes), and the detail view. Purely presentational\n * — a hidden field's stored value is never cleared. `when.field`\n * must name another top-level field. Absent ⇒ always shown. Only\n * honoured on top-level fields, not inside a `table`'s `of`. */\n when?: CollectionWhen;\n /** When `type === \"toggle\"`: the name of the top-level `enum` field this\n * checkbox projects. The toggle stores nothing itself — it reads and\n * writes this field. Required when type is `toggle`; ignored otherwise.\n * Must name a real `enum` field. */\n field?: string;\n /** When `type === \"toggle\"`: the enum value that means \"checked\". The\n * box is checked when the projected `field` equals this; checking writes\n * it. Required when type is `toggle`; must be one of the enum's `values`. */\n onValue?: string;\n /** When `type === \"toggle\"`: the enum value written when the box is\n * unchecked. Required when type is `toggle`; must be one of the enum's\n * `values`. */\n offValue?: string;\n}\n\nexport interface CollectionSchema {\n /** Human-facing collection name (sidebar, header). */\n title: string;\n /** Material-icon name shown next to the title. */\n icon: string;\n /** Workspace-relative folder holding one-JSON-per-record. Validated\n * to live under the workspace root at load time. */\n dataPath: string;\n /** Field name whose value doubles as the record's filename. */\n primaryKey: string;\n /** When set, the collection is a singleton: at most one record,\n * whose primary key is fixed to this value (e.g. `me` for the\n * business profile). The host pre-fills + locks the create form's\n * primary key and hides Add once the record exists. */\n singleton?: string;\n /** Ordered map: insertion order = column order in the table view. */\n fields: Record<string, CollectionFieldSpec>;\n /** Optional per-record actions rendered as buttons in the detail\n * view (e.g. \"Generate PDF\"). Order = button order. */\n actions?: CollectionAction[];\n /** Optional collection-level actions rendered as buttons in the\n * collection header (e.g. \"Extend the course\"). Unlike `actions`,\n * these carry no record context: the seed prompt injects a compact\n * progress summary of every record instead. The `when` predicate is\n * not evaluated (there is no record to gate on). Order = button order. */\n collectionActions?: CollectionAction[];\n /** Name of the field whose value marks an item as \"done\". When set,\n * a notification fires on item create (unless the item is born done)\n * and clears when the field's value transitions into\n * `completionDoneValues`. Must name a real field in `fields`. */\n completionField?: string;\n /** The set of values for `completionField` that count as \"done\"\n * (e.g. `[\"Done\"]` for a todo status field, `[\"paid\"]` for an\n * invoice). Non-empty. Compared as strings. */\n completionDoneValues?: readonly string[];\n /** Name of the field whose value is shown as the human-readable\n * label in a completion notification's title (e.g. a `name` field,\n * so the bell reads `Contacts: Jane Doe` instead of the opaque\n * primaryKey). Must name a real field in `fields`. When unset — or\n * when the record's value for it is empty — the title falls back to\n * the record's primaryKey value. Display-only; never stored. */\n displayField?: string;\n /** Name of a `date` field that gates this item's completion\n * notification: the bell is suppressed until the clock reaches that\n * date (compared at day-granularity in the server's local timezone),\n * instead of firing on create. Requires `completionField` /\n * `completionDoneValues` (the bell still clears via the done value).\n * Must name a real `date` field. Absent ⇒ fire on create, as before. */\n triggerField?: string;\n /** Lead time in whole days: fire the bell this many days BEFORE\n * `triggerField` (so `10` shows the reminder 10 days early). The lead\n * is applied at fire time, not stored, so it composes with `spawn` —\n * every recurred cycle fires the same number of days before its own\n * trigger. Non-negative integer; requires `triggerField`. Default 0\n * (fire on the trigger date). */\n triggerLeadDays?: number;\n /** Host-driven recurrence. When set, requires `triggerField`. See\n * {@link CollectionSpawn}. */\n spawn?: CollectionSpawn;\n /** Name of a `date` field that anchors the optional calendar view: a\n * month grid where each record lands on the day cell matching this\n * field's value. When unset, the calendar toggle still appears if the\n * schema has any `date` field (the first one, in declaration order, is\n * used by default and is switchable in-view). Set this to pin a specific\n * anchor. Must name a real `date` field. */\n calendarField?: string;\n /** Name of a second `date` field marking the END of a multi-day span on\n * the calendar: the record renders from `calendarField` through this\n * date inclusive. Requires `calendarField`. Must name a real `date`\n * field. Absent ⇒ single-day placement. */\n calendarEndField?: string;\n /** Name of a string field holding a free-form time or time-range\n * (e.g. \"14:00-17:00\", \"17:00-\", \"16:30\") that places records on the\n * calendar's day (time-allocation) view. Consulted only when the calendar\n * date fields are date-only. Requires `calendarField`. */\n calendarTimeField?: string;\n /** Name of an `enum` field that groups records into columns on the\n * optional Kanban board: each record lands in the column matching its\n * value, with empty/unknown values collected in an \"Uncategorized\"\n * column. When unset, the Kanban toggle still appears if the schema has\n * any `enum` field (the first one, in declaration order, is used by\n * default and is switchable in-view). Set this to pin a specific group\n * field. Must name a real `enum` field. */\n kanbanField?: string;\n /** Optional custom (LLM-authored) HTML views, each rendered in a\n * sandboxed iframe over the records. Absent ⇒ only the built-in\n * field-derived views (table / calendar / kanban / dashboard). See\n * {@link CollectionCustomView}. */\n views?: CollectionCustomView[];\n /** Optional predicate that gates the completion bell: when set, the bell\n * fires only for records whose `String(record[notifyWhen.field])` is one\n * of `notifyWhen.in` (e.g. notify only `high`/`urgent` priority todos).\n * Reuses the `when` predicate shape. Requires `completionField` — it\n * narrows that bell rather than introducing a second one. The bell still\n * clears on done / delete / when the predicate stops matching. Absent ⇒\n * notify for every open record (the prior behaviour). `notifyWhen.field`\n * must name a real top-level field. */\n notifyWhen?: CollectionWhen;\n /** Optional declarative retrieval config. When present, this collection\n * is a \"Feed\": the host periodically fetches `ingest.url`, maps the\n * response into records, and upserts them by `primaryKey`. Only feeds\n * discovered from the `<workspace>/feeds/` registry carry this; skill\n * collections omit it. The host's feeds subsystem narrows this to its\n * richer `IngestSpec` (which `extends CollectionIngest`). */\n ingest?: CollectionIngest;\n}\n\nexport interface CollectionSummary {\n slug: string;\n title: string;\n icon: string;\n source: CollectionSource;\n}\n\nexport interface CollectionDetail extends CollectionSummary {\n schema: CollectionSchema;\n}\n\nexport type CollectionItem = Record<string, unknown>;\n"],"mappings":";;;;;AA8BA,IAAa,eAAe;CAAC;CAAO;CAAQ;AAAW;;AAIvD,IAAa,iBAAiB;CAAC;CAAU;CAAS;CAAU;AAAW;;AAqFvE,SAAgB,mBAAmB,OAAkE;CACnG,OAAO,eAAe;AACxB"}
@@ -15,7 +15,11 @@ var FEED_SCHEDULES = [
15
15
  "weekly",
16
16
  "on-demand"
17
17
  ];
18
+ /** Narrowing guard: true when `every` is the field-driven arm. */
19
+ function isFieldDrivenEvery(every) {
20
+ return "fromField" in every;
21
+ }
18
22
  //#endregion
19
- export { INGEST_KINDS as n, FEED_SCHEDULES as t };
23
+ export { INGEST_KINDS as n, isFieldDrivenEvery as r, FEED_SCHEDULES as t };
20
24
 
21
- //# sourceMappingURL=schema-DyfSfVzh.js.map
25
+ //# sourceMappingURL=schema-BcnitlL8.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-BcnitlL8.js","names":[],"sources":["../src/core/schema.ts"],"sourcesContent":["// Schema-driven collection types. A \"collection\" is a skill (under\n// .claude/skills/<slug>/) that also ships a sibling `schema.json`.\n// The host's <CollectionView> reads the schema + records and renders\n// a table/form; Claude reads SKILL.md and CRUDs the records as JSON\n// files.\n//\n// Field types for v0 — keep this list narrow and grow it only when a\n// real collection needs the new type. v0 supports flat records only;\n// nested tables / cross-collection refs / derived fields / actions are\n// deferred to follow-ups (see plans/done/feat-skill-driven-apps.md and\n// plans/done/feat-skill-driven-apps-worklog.md — historical names predate\n// the rename).\n\n/** Minimal \"this collection is a feed\" descriptor carried on the schema.\n * Deliberately narrow — the canonical collection contract stays\n * independent of the host's feeds subsystem. The host's richer retrieval\n * spec (`IngestSpec` in `server/workspace/feeds/ingestTypes.ts`)\n * `extends CollectionIngest`, so feed code reads the extra fields by\n * typing feed schemas with that subtype; collection rendering only needs\n * these three + the presence check. */\nexport interface CollectionIngest {\n kind: string;\n url: string;\n schedule: string;\n}\n\n/** Retriever kinds a Feed's `ingest.kind` may declare. The host's feeds engine\n * dispatches on these; they live here (with the schema contract) so the schema\n * validator can enforce them. The host re-exports these from\n * `server/workspace/feeds/ingestTypes.ts`. */\nexport const INGEST_KINDS = [\"rss\", \"atom\", \"http-json\"] as const;\nexport type IngestKind = (typeof INGEST_KINDS)[number];\n\n/** Refresh cadences a Feed's `ingest.schedule` may declare. */\nexport const FEED_SCHEDULES = [\"hourly\", \"daily\", \"weekly\", \"on-demand\"] as const;\nexport type FeedSchedule = (typeof FEED_SCHEDULES)[number];\n\nexport type CollectionFieldType =\n | \"string\"\n | \"text\"\n | \"email\"\n | \"number\"\n | \"date\"\n | \"datetime\"\n | \"boolean\"\n | \"markdown\"\n | \"ref\"\n | \"money\"\n | \"enum\"\n | \"table\"\n | \"derived\"\n | \"embed\"\n // Holds a workspace-relative image path (e.g. a `data/attachments/...`\n // upload); rendered as an <img> in the detail view (not the list table —\n // a per-row fetch is too expensive at scale). Stored and edited as a\n // plain string.\n | \"image\"\n // Holds a workspace-relative file path as a plain string (e.g. an\n // `artifacts/html/<name>.html` app). Rendered as a clickable link in\n // both the list table and the detail view: HTML / SVG artifacts open\n // their rendered form in a new tab; any other path opens in the File\n // Explorer. Stored and edited as a plain string, like `image`.\n | \"file\"\n // A checkbox that is a pure PROJECTION of an `enum` field — it stores\n // nothing of its own. Checked when the enum equals `onValue`; toggling\n // writes `onValue` / `offValue` back to that enum field. Lets a \"done\"\n // checkbox front a kanban `status` field with the enum as the single\n // source of truth (no separate stored boolean to keep in sync).\n | \"toggle\";\n\n// \"feed\" collections live in the non-skill `<workspace>/feeds/` registry\n// and carry an `ingest` block; they reuse the same storage + rendering\n// as skill-backed collections but are never loaded into the agent prompt.\nexport type CollectionSource = \"user\" | \"project\" | \"feed\";\n\n/** Recurrence unit for a `spawn.every` advance. */\nexport type CollectionRecurUnit = \"day\" | \"week\" | \"month\" | \"year\";\n\n/** How a `spawn` advances the source item's `triggerField` date to\n * produce the successor's. All arithmetic is done on the civil\n * (year, month, day) triple — never by adding milliseconds — so month\n * lengths and leap years are handled correctly. */\nexport interface CollectionEvery {\n unit: CollectionRecurUnit;\n /** Number of `unit`s to advance (≥ 1). `interval: 3` + `unit: \"month\"`\n * = quarterly; `interval: 1` + `unit: \"year\"` = annual. */\n interval: number;\n /** Day-of-month anchor for `month`/`year` units. The CANONICAL day —\n * read from the rule, never re-derived from the prior concrete date,\n * so \"31st of every month\" yields 31 → 28/29 → 31 → 30 … with no\n * drift (it is clamped per-month at compute time, not stored\n * clamped). `\"last\"` always means the last day of the target month.\n * Omitted ⇒ preserve the source date's day (safe for days ≤ 28).\n * Ignored for `day`/`week` units. */\n dayOfMonth?: number | \"last\";\n}\n\n/** Field-driven recurrence: the advance interval is selected PER RECORD by\n * the value of an `enum` field (`fromField`), looked up in `map`. Lets one\n * collection mix daily / weekly / monthly obligations in a single list — the\n * host reads `record[fromField]`, finds the matching `CollectionEvery`, and\n * advances by it. `fromField` must point at a top-level `enum` field whose\n * `values` the `map` keys exactly cover (validated at discovery), and must\n * itself be carried/`set` onto the successor so the chain keeps recurring. */\nexport interface CollectionEveryFieldDriven {\n /** Top-level `enum` field whose value selects the interval. */\n fromField: string;\n /** Interval per enum value. Keys exactly cover `fromField`'s `values`;\n * each value is a literal {@link CollectionEvery}. */\n map: Record<string, CollectionEvery>;\n}\n\n/** The `every` of a `spawn`: either a single literal interval applied to\n * every record, or a per-record interval selected by an `enum` field. The\n * literal arm is what `advanceTriggerDate` consumes — the field-driven arm\n * is resolved down to one of its `map` values before the date math runs. */\nexport type CollectionSpawnEvery = CollectionEvery | CollectionEveryFieldDriven;\n\n/** Narrowing guard: true when `every` is the field-driven arm. */\nexport function isFieldDrivenEvery(every: CollectionSpawnEvery): every is CollectionEveryFieldDriven {\n return \"fromField\" in every;\n}\n\n/** Host-driven recurrence: when a record satisfies `when`, the host\n * creates the next record with a forward-advanced `triggerField` date.\n * The successor's id and contents are a pure function of (source\n * record, this rule); creation is create-if-absent, so the mechanism\n * stays convergent — observing the predicate N times writes one\n * successor. Requires the schema to declare `triggerField`. */\nexport interface CollectionSpawn {\n /** Predicate that fires the spawn (a `CollectionWhen`). Defaults to\n * \"`completionField` value ∈ `completionDoneValues`\" (i.e. spawn the\n * next instance when this one is done). */\n when?: CollectionWhen;\n /** How to advance `triggerField` from the source to the successor —\n * either a single literal interval or a per-record, field-driven map. */\n every: CollectionSpawnEvery;\n /** Record fields copied verbatim onto the successor. Fields not listed\n * here, not in `set`, and not the trigger / primary keys start\n * blank. */\n carry?: string[];\n /** Fields forced to fixed values on the successor (typically resetting\n * the status field to its pending value). */\n set?: Record<string, unknown>;\n}\n\n/** The kind of work an action kicks off. v1 ships only `\"chat\"` —\n * start a new chat in a role with a templated seed prompt. The enum\n * reserves room for a future `\"mutate\"` (status transitions) without\n * another schema-shape change. */\nexport type CollectionActionKind = \"chat\";\n\n/** Optional visibility predicate: the target (an action button or a\n * field) renders only when the open record's `field` (stringified) is\n * one of `in`. Generic and domain-free — the host evaluates it against\n * the record with no knowledge of what the field means. Absent ⇒\n * always shown. */\nexport interface CollectionWhen {\n /** Top-level record field key whose value gates visibility. */\n field: string;\n /** Allowed values; the target shows when `String(record[field])` is\n * one of these. Non-empty. */\n in: string[];\n}\n\n/** @deprecated Name retained for back-compat; use {@link CollectionWhen}.\n * Both actions and fields share the same predicate shape. */\nexport type CollectionActionWhen = CollectionWhen;\n\n/** What a custom view's capability token is allowed to do against the\n * collection's data endpoint. `read` returns enriched records (getItems\n * semantics); `write` validates-and-stores rows (putItems semantics).\n * There is deliberately no `delete` — a view can never do more than the\n * agent's own `manageCollection` tool. */\nexport type CollectionViewCapability = \"read\" | \"write\";\n\n/** A custom (LLM-authored) HTML view for a collection. The host renders\n * `file` in a sandboxed iframe over the collection's records; the view\n * reaches its data only through a slug- and capability-scoped token (see\n * `server/api/auth/viewToken.ts`). Pure data — the host holds no\n * view-specific code; meaning lives in the HTML file + this registration. */\nexport interface CollectionCustomView {\n /** Stable id; the view-mode selector key (`custom:<id>`) and the\n * capability-token clamp key. Must be a valid slug. */\n id: string;\n /** Button label in the view-mode selector (author-authored, like field\n * labels — not run through i18n). */\n label: string;\n /** Optional Material-icon name for the selector button. */\n icon?: string;\n /** Skill-relative path to the HTML file under `views/` (e.g.\n * `views/year.html`). Path-safe, must end in `.html`. */\n file: string;\n /** What the view may do with the data endpoint. Defaults to `[\"read\"]`\n * (least privilege); declare `[\"read\",\"write\"]` only for views that\n * edit records. The mint endpoint clamps any requested caps to this. */\n capabilities?: CollectionViewCapability[];\n}\n\n/** A schema-declared, per-record action rendered as a button in the\n * read-only detail view. Pure UI/behaviour directive — never stored,\n * never validated against record data. All domain specifics (label,\n * role, template) live here in the schema / skill folder, so the host\n * stays generic. */\nexport interface CollectionAction {\n /** Stable id (used in the dispatch route + testids). */\n id: string;\n /** Button text (English, like field labels). */\n label: string;\n /** Material-icon name shown on the button. */\n icon?: string;\n /** What the action does. v1: `\"chat\"`. */\n kind: CollectionActionKind;\n /** `kind: \"chat\"`: the role id the new chat runs in. */\n role: string;\n /** `kind: \"chat\"`: skill-relative path to the template file whose\n * text becomes the seed prompt body (e.g. `templates/invoice.md`). */\n template: string;\n /** Optional visibility predicate; the button renders only when the\n * open record matches (see CollectionWhen). Absent ⇒ always\n * shown. */\n when?: CollectionWhen;\n}\n\nexport interface CollectionFieldSpec {\n type: CollectionFieldType;\n label: string;\n /** True for the field whose value is the record's filename (no\n * separate auto-id). Exactly one field per schema may set this. */\n primary?: boolean;\n required?: boolean;\n /** When `type === \"ref\"` or `type === \"embed\"`: the slug of the\n * target collection. For `ref` the record stores the target\n * item's primary-key slug and the host renders a clickable link\n * + dropdown picker. For `embed` the host pulls a *fixed* record\n * (see `id`) from the target and renders its fields read-only in\n * the detail view. Required for both; ignored on every other\n * type. */\n to?: string;\n /** When `type === \"embed\"`: the primary-key value of the fixed\n * record to pull from the `to` collection (e.g. `me` for the\n * singleton mc-profile). Nothing is stored on this record — the\n * embed is a display-only directive resolved at render time, so\n * it never appears in the list table or the edit form. Required\n * when type is `embed`; ignored on every other type. */\n id?: string;\n /** When `type === \"money\"` (or `type === \"derived\"` with\n * `display: \"money\"`): a literal ISO 4217 currency code passed to\n * `Intl.NumberFormat` for display — fixed for every record. The\n * stored value is always a plain decimal number; currency is\n * presentation only. Mutually substitutable with `currencyField`:\n * a money field must declare at least one of the two. */\n currency?: string;\n /** When `type === \"money\"` (or `type === \"derived\"` with\n * `display: \"money\"`): the name of a sibling record field whose\n * value holds the ISO 4217 code, letting currency vary per record\n * (e.g. an invoice's `currency` enum). The renderer reads\n * `record[currencyField]` and falls back to the literal `currency`\n * (then \"USD\") when the field is absent or empty. Resolved against\n * the top-level record even for money sub-fields inside a table. */\n currencyField?: string;\n /** When `type === \"enum\"`: the closed set of allowed string\n * values. The form renders a `<select>` populated from this\n * list; storage is a plain string. Required when type is\n * `enum`; ignored on every other type. */\n values?: readonly string[];\n /** When `type === \"table\"`: the sub-schema for each row (a flat\n * record of non-table / non-derived field specs). Required when\n * type is `table`. v0 disallows nested tables and derived\n * columns to keep the editor + evaluator simple. */\n of?: Record<string, CollectionFieldSpec>;\n /** When `type === \"derived\"`: a tiny expression evaluated against\n * the record. Supports `+ - * /`, parens, identifier refs to\n * top-level fields, `sum(tableField[].col)`, and\n * `sum(tableField[].col * tableField[].col)`. See\n * `src/utils/collections/derivedFormula.ts`. Required when type\n * is `derived`. */\n formula?: string;\n /** When `type === \"derived\"`: an inner field type the computed\n * value should be rendered as (e.g. `\"money\"` so $1,234.56 is\n * formatted). Defaults to `\"number\"`. */\n display?: CollectionFieldType;\n /** Optional visibility predicate: this field renders only when the\n * record matches (e.g. hide a `rating` field until `visited` is\n * `true` via `{ field: \"visited\", in: [\"true\"] }`). Applies to the\n * list cell (blank when hidden), the edit form (hidden live as the\n * gating field changes), and the detail view. Purely presentational\n * — a hidden field's stored value is never cleared. `when.field`\n * must name another top-level field. Absent ⇒ always shown. Only\n * honoured on top-level fields, not inside a `table`'s `of`. */\n when?: CollectionWhen;\n /** When `type === \"toggle\"`: the name of the top-level `enum` field this\n * checkbox projects. The toggle stores nothing itself — it reads and\n * writes this field. Required when type is `toggle`; ignored otherwise.\n * Must name a real `enum` field. */\n field?: string;\n /** When `type === \"toggle\"`: the enum value that means \"checked\". The\n * box is checked when the projected `field` equals this; checking writes\n * it. Required when type is `toggle`; must be one of the enum's `values`. */\n onValue?: string;\n /** When `type === \"toggle\"`: the enum value written when the box is\n * unchecked. Required when type is `toggle`; must be one of the enum's\n * `values`. */\n offValue?: string;\n}\n\nexport interface CollectionSchema {\n /** Human-facing collection name (sidebar, header). */\n title: string;\n /** Material-icon name shown next to the title. */\n icon: string;\n /** Workspace-relative folder holding one-JSON-per-record. Validated\n * to live under the workspace root at load time. */\n dataPath: string;\n /** Field name whose value doubles as the record's filename. */\n primaryKey: string;\n /** When set, the collection is a singleton: at most one record,\n * whose primary key is fixed to this value (e.g. `me` for the\n * business profile). The host pre-fills + locks the create form's\n * primary key and hides Add once the record exists. */\n singleton?: string;\n /** Ordered map: insertion order = column order in the table view. */\n fields: Record<string, CollectionFieldSpec>;\n /** Optional per-record actions rendered as buttons in the detail\n * view (e.g. \"Generate PDF\"). Order = button order. */\n actions?: CollectionAction[];\n /** Optional collection-level actions rendered as buttons in the\n * collection header (e.g. \"Extend the course\"). Unlike `actions`,\n * these carry no record context: the seed prompt injects a compact\n * progress summary of every record instead. The `when` predicate is\n * not evaluated (there is no record to gate on). Order = button order. */\n collectionActions?: CollectionAction[];\n /** Name of the field whose value marks an item as \"done\". When set,\n * a notification fires on item create (unless the item is born done)\n * and clears when the field's value transitions into\n * `completionDoneValues`. Must name a real field in `fields`. */\n completionField?: string;\n /** The set of values for `completionField` that count as \"done\"\n * (e.g. `[\"Done\"]` for a todo status field, `[\"paid\"]` for an\n * invoice). Non-empty. Compared as strings. */\n completionDoneValues?: readonly string[];\n /** Name of the field whose value is shown as the human-readable\n * label in a completion notification's title (e.g. a `name` field,\n * so the bell reads `Contacts: Jane Doe` instead of the opaque\n * primaryKey). Must name a real field in `fields`. When unset — or\n * when the record's value for it is empty — the title falls back to\n * the record's primaryKey value. Display-only; never stored. */\n displayField?: string;\n /** Name of a `date` field that gates this item's completion\n * notification: the bell is suppressed until the clock reaches that\n * date (compared at day-granularity in the server's local timezone),\n * instead of firing on create. Requires `completionField` /\n * `completionDoneValues` (the bell still clears via the done value).\n * Must name a real `date` field. Absent ⇒ fire on create, as before. */\n triggerField?: string;\n /** Lead time in whole days: fire the bell this many days BEFORE\n * `triggerField` (so `10` shows the reminder 10 days early). The lead\n * is applied at fire time, not stored, so it composes with `spawn` —\n * every recurred cycle fires the same number of days before its own\n * trigger. Non-negative integer; requires `triggerField`. Default 0\n * (fire on the trigger date). */\n triggerLeadDays?: number;\n /** Host-driven recurrence. When set, requires `triggerField`. See\n * {@link CollectionSpawn}. */\n spawn?: CollectionSpawn;\n /** Name of a `date` field that anchors the optional calendar view: a\n * month grid where each record lands on the day cell matching this\n * field's value. When unset, the calendar toggle still appears if the\n * schema has any `date` field (the first one, in declaration order, is\n * used by default and is switchable in-view). Set this to pin a specific\n * anchor. Must name a real `date` field. */\n calendarField?: string;\n /** Name of a second `date` field marking the END of a multi-day span on\n * the calendar: the record renders from `calendarField` through this\n * date inclusive. Requires `calendarField`. Must name a real `date`\n * field. Absent ⇒ single-day placement. */\n calendarEndField?: string;\n /** Name of a string field holding a free-form time or time-range\n * (e.g. \"14:00-17:00\", \"17:00-\", \"16:30\") that places records on the\n * calendar's day (time-allocation) view. Consulted only when the calendar\n * date fields are date-only. Requires `calendarField`. */\n calendarTimeField?: string;\n /** Name of an `enum` field that groups records into columns on the\n * optional Kanban board: each record lands in the column matching its\n * value, with empty/unknown values collected in an \"Uncategorized\"\n * column. When unset, the Kanban toggle still appears if the schema has\n * any `enum` field (the first one, in declaration order, is used by\n * default and is switchable in-view). Set this to pin a specific group\n * field. Must name a real `enum` field. */\n kanbanField?: string;\n /** Optional custom (LLM-authored) HTML views, each rendered in a\n * sandboxed iframe over the records. Absent ⇒ only the built-in\n * field-derived views (table / calendar / kanban / dashboard). See\n * {@link CollectionCustomView}. */\n views?: CollectionCustomView[];\n /** Optional predicate that gates the completion bell: when set, the bell\n * fires only for records whose `String(record[notifyWhen.field])` is one\n * of `notifyWhen.in` (e.g. notify only `high`/`urgent` priority todos).\n * Reuses the `when` predicate shape. Requires `completionField` — it\n * narrows that bell rather than introducing a second one. The bell still\n * clears on done / delete / when the predicate stops matching. Absent ⇒\n * notify for every open record (the prior behaviour). `notifyWhen.field`\n * must name a real top-level field. */\n notifyWhen?: CollectionWhen;\n /** Optional declarative retrieval config. When present, this collection\n * is a \"Feed\": the host periodically fetches `ingest.url`, maps the\n * response into records, and upserts them by `primaryKey`. Only feeds\n * discovered from the `<workspace>/feeds/` registry carry this; skill\n * collections omit it. The host's feeds subsystem narrows this to its\n * richer `IngestSpec` (which `extends CollectionIngest`). */\n ingest?: CollectionIngest;\n}\n\nexport interface CollectionSummary {\n slug: string;\n title: string;\n icon: string;\n source: CollectionSource;\n}\n\nexport interface CollectionDetail extends CollectionSummary {\n schema: CollectionSchema;\n}\n\nexport type CollectionItem = Record<string, unknown>;\n"],"mappings":";;;;;AA8BA,IAAa,eAAe;CAAC;CAAO;CAAQ;AAAW;;AAIvD,IAAa,iBAAiB;CAAC;CAAU;CAAS;CAAU;AAAW;;AAqFvE,SAAgB,mBAAmB,OAAkE;CACnG,OAAO,eAAe;AACxB"}
@@ -109,7 +109,7 @@ export declare const CollectionSchemaZ: z.ZodObject<{
109
109
  field: z.ZodString;
110
110
  in: z.ZodArray<z.ZodString>;
111
111
  }, z.core.$strip>>;
112
- every: z.ZodObject<{
112
+ every: z.ZodUnion<readonly [z.ZodObject<{
113
113
  unit: z.ZodEnum<{
114
114
  day: "day";
115
115
  week: "week";
@@ -118,7 +118,19 @@ export declare const CollectionSchemaZ: z.ZodObject<{
118
118
  }>;
119
119
  interval: z.ZodNumber;
120
120
  dayOfMonth: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodLiteral<"last">]>>;
121
- }, z.core.$strip>;
121
+ }, z.core.$strict>, z.ZodObject<{
122
+ fromField: z.ZodString;
123
+ map: z.ZodRecord<z.ZodString, z.ZodObject<{
124
+ unit: z.ZodEnum<{
125
+ day: "day";
126
+ week: "week";
127
+ month: "month";
128
+ year: "year";
129
+ }>;
130
+ interval: z.ZodNumber;
131
+ dayOfMonth: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodLiteral<"last">]>>;
132
+ }, z.core.$strict>>;
133
+ }, z.core.$strict>]>;
122
134
  carry: z.ZodOptional<z.ZodArray<z.ZodString>>;
123
135
  set: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
124
136
  }, z.core.$strip>>;
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/server/discovery.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAwT9G,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6P1B,CAAC;AAmBL;qEACqE;AACrE,MAAM,MAAM,gBAAgB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7F;;;;;;;;;;;;;;6EAc6E;AAC7E,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE;IAAE,MAAM,EAAE,gBAAgB,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAAG,gBAAgB,CAQxI;AA+ED,MAAM,WAAW,gBAAgB;IAC/B;;;;+DAI2D;IAC3D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;4CAGwC;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;+BAM+B;AAC/B,wBAAsB,mBAAmB,CAAC,IAAI,GAAE,gBAAqB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAgBlG;AAED;4DAC4D;AAC5D,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,gBAAqB,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAchH;AAED,wBAAgB,SAAS,CAAC,UAAU,EAAE,gBAAgB,GAAG,iBAAiB,CAEzE;AAED,wBAAgB,QAAQ,CAAC,UAAU,EAAE,gBAAgB,GAAG,gBAAgB,CAEvE"}
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/server/discovery.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,KAAK,EAAE,gBAAgB,EAA8B,gBAAgB,EAAE,gBAAgB,EAAwB,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AA+YhK,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmR1B,CAAC;AAmBL;qEACqE;AACrE,MAAM,MAAM,gBAAgB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7F;;;;;;;;;;;;;;6EAc6E;AAC7E,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE;IAAE,MAAM,EAAE,gBAAgB,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAAG,gBAAgB,CAQxI;AA+ED,MAAM,WAAW,gBAAgB;IAC/B;;;;+DAI2D;IAC3D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;4CAGwC;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;+BAM+B;AAC/B,wBAAsB,mBAAmB,CAAC,IAAI,GAAE,gBAAqB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAgBlG;AAED;4DAC4D;AAC5D,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,gBAAqB,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAchH;AAED,wBAAgB,SAAS,CAAC,UAAU,EAAE,gBAAgB,GAAG,iBAAiB,CAEzE;AAED,wBAAgB,QAAQ,CAAC,UAAU,EAAE,gBAAgB,GAAG,gBAAgB,CAEvE"}
@@ -30,11 +30,35 @@ export interface CollectionHost {
30
30
  /** True for a preset-skill slug (host-owned naming convention). */
31
31
  isPresetSlug: (slug: string) => boolean;
32
32
  }
33
+ /** A collection's records changed on disk. Carries the `slug` so the host can
34
+ * publish on a per-collection channel; `ids` lists the affected record ids
35
+ * when known (a consumer may ignore them and refetch the whole collection),
36
+ * and `op` is advisory. Deliberately carries NO record bodies — this is a
37
+ * "refetch" ping, not a data feed, so it stays cheap and leaks nothing when a
38
+ * host relays it into an opaque-origin custom-view iframe. */
39
+ export interface CollectionChangePayload {
40
+ slug: string;
41
+ ids?: string[];
42
+ op?: "upsert" | "delete";
43
+ }
44
+ type CollectionChangePublisher = (payload: CollectionChangePayload) => void;
33
45
  /** Wire the engine to a host. Call once at server startup, before any
34
46
  * collection storage operation. Re-binding to a *different* host throws —
35
47
  * silently redirecting later filesystem operations to another workspace
36
48
  * would be a bug, not a feature. Re-calling with the same host is a no-op. */
37
49
  export declare function configureCollectionHost(host: CollectionHost): void;
50
+ /** Wire a publisher that broadcasts record-change events; the host bridges it
51
+ * to its pubsub. Kept SEPARATE from `configureCollectionHost` because the
52
+ * host's pubsub instance isn't ready at host-binding time (the binding is set
53
+ * at the top of server startup, the pubsub later). Optional: left unset, every
54
+ * write is silent — the default for tests and for a host that doesn't want
55
+ * live view updates. Pass `null` to detach (test teardown). */
56
+ export declare function setCollectionChangePublisher(publish: CollectionChangePublisher | null): void;
57
+ /** Broadcast a record-change event if a publisher is wired (no-op otherwise).
58
+ * Called from the write path (`writeItem`/`deleteItem`). The wired publisher is
59
+ * expected to be fire-and-forget (it wraps its own pubsub call in try/catch),
60
+ * so this stays a thin pass-through and never throws into the write. */
61
+ export declare function publishCollectionChange(payload: CollectionChangePayload): void;
38
62
  /** The configured workspace root. Throws if the host never configured one. */
39
63
  export declare function getWorkspaceRoot(): string;
40
64
  export declare function userSkillsDir(): string;
@@ -50,4 +74,5 @@ export declare function isPresetSlug(slug: string): boolean;
50
74
  * `getWorkspaceRoot()`, which fails loudly because the engine cannot operate
51
75
  * without a workspace root. */
52
76
  export declare const log: CollectionLogger;
77
+ export {};
53
78
  //# sourceMappingURL=host.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/server/host.ts"],"names":[],"mappings":"AAUA;mDACmD;AACnD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACjF,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAChF,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAChF,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CAClF;AAED,MAAM,WAAW,cAAc;IAC7B;;6BAEyB;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,GAAG,EAAE,gBAAgB,CAAC;IACtB;6EACyE;IACzE,KAAK,EAAE;QACL,+EAA+E;QAC/E,aAAa,EAAE,MAAM,CAAC;QACtB,mFAAmF;QACnF,gBAAgB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,CAAC;QACpD,0EAA0E;QAC1E,SAAS,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,CAAC;QAC7C,oFAAoF;QACpF,gBAAgB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,CAAC;QACpD,+EAA+E;QAC/E,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,mEAAmE;IACnE,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACzC;AAID;;;+EAG+E;AAC/E,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAKlE;AASD,8EAA8E;AAC9E,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAKD,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AACD,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE9D;AACD,wBAAgB,SAAS,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAEvD;AACD,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE9D;AACD,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AACD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;;;gCAKgC;AAChC,eAAO,MAAM,GAAG,EAAE,gBAKjB,CAAC"}
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/server/host.ts"],"names":[],"mappings":"AAUA;mDACmD;AACnD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACjF,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAChF,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAChF,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CAClF;AAED,MAAM,WAAW,cAAc;IAC7B;;6BAEyB;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,GAAG,EAAE,gBAAgB,CAAC;IACtB;6EACyE;IACzE,KAAK,EAAE;QACL,+EAA+E;QAC/E,aAAa,EAAE,MAAM,CAAC;QACtB,mFAAmF;QACnF,gBAAgB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,CAAC;QACpD,0EAA0E;QAC1E,SAAS,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,CAAC;QAC7C,oFAAoF;QACpF,gBAAgB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,CAAC;QACpD,+EAA+E;QAC/E,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,mEAAmE;IACnE,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACzC;AAED;;;;;+DAK+D;AAC/D,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,EAAE,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC1B;AAED,KAAK,yBAAyB,GAAG,CAAC,OAAO,EAAE,uBAAuB,KAAK,IAAI,CAAC;AAK5E;;;+EAG+E;AAC/E,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAKlE;AAED;;;;;gEAKgE;AAChE,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,yBAAyB,GAAG,IAAI,GAAG,IAAI,CAE5F;AAED;;;yEAGyE;AACzE,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,uBAAuB,GAAG,IAAI,CAE9E;AASD,8EAA8E;AAC9E,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAKD,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AACD,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE9D;AACD,wBAAgB,SAAS,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAEvD;AACD,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE9D;AACD,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AACD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;;;gCAKgC;AAChC,eAAO,MAAM,GAAG,EAAE,gBAKjB,CAAC"}
@@ -1,4 +1,4 @@
1
- export { configureCollectionHost, getWorkspaceRoot, log, type CollectionHost, type CollectionLogger } from "./host";
1
+ export { configureCollectionHost, getWorkspaceRoot, log, setCollectionChangePublisher, publishCollectionChange, type CollectionHost, type CollectionLogger, type CollectionChangePayload, } from "./host";
2
2
  export type { LoadedCollection } from "./discoveredCollection";
3
3
  export * from "./paths";
4
4
  export * from "./templatePath";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,GAAG,EAAE,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AACpH,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,MAAM,CAAC;AACrB,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,GAAG,EACH,4BAA4B,EAC5B,uBAAuB,EACvB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,GAC7B,MAAM,QAAQ,CAAC;AAChB,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,MAAM,CAAC;AACrB,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
@@ -7,6 +7,12 @@ export interface IoOptions {
7
7
  * without touching `~/mulmoclaude/`. Same pattern as
8
8
  * `server/workspace/skills/catalog.ts#CatalogOptions`. */
9
9
  workspaceRoot?: string;
10
+ /** Collection slug this write/delete belongs to. When provided, a
11
+ * successful write/delete publishes a record-change event (see
12
+ * `publishCollectionChange`) so live views refetch. `writeItem` has no
13
+ * slug of its own (it's keyed by `dataDir`), so callers thread it through;
14
+ * omitting it just means no event is published (internal / test writes). */
15
+ slug?: string;
10
16
  }
11
17
  /** Read every record under `dataDir`. Returns [] if the dir doesn't
12
18
  * exist yet (legitimate first-use state). Malformed JSON files and
@@ -1 +1 @@
1
- {"version":3,"file":"io.d.ts","sourceRoot":"","sources":["../../src/server/io.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"io.d.ts","sourceRoot":"","sources":["../../src/server/io.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { type IoOptions } from "./io";
2
- import type { CollectionEvery, CollectionItem, CollectionSchema } from "../core/schema";
2
+ import type { CollectionEvery, CollectionItem, CollectionSchema, CollectionSpawnEvery } from "../core/schema";
3
3
  /** A timezone-free calendar date. `m` is 1-12. */
4
4
  export interface CivilDate {
5
5
  y: number;
@@ -32,6 +32,13 @@ export declare function isTriggerDue(triggerRaw: unknown, now: Date, leadDays?:
32
32
  * Slug-safe (alphanumeric + hyphen) and a pure function of the inputs,
33
33
  * which is what makes create-if-absent idempotent. */
34
34
  export declare function successorId(sourceId: string, next: CivilDate): string;
35
+ /** Resolve the literal `every` that applies to `sourceItem`. Literal-arm
36
+ * `spawn.every` passes through unchanged. Field-driven `spawn.every` reads
37
+ * `sourceItem[fromField]` and looks it up in `map`; an empty field or a
38
+ * value with no map entry yields null (caller skips + logs — see plan §5).
39
+ * Discovery rejects a map that doesn't cover the enum's values, so null
40
+ * here means a record that predates a map/enum edit. */
41
+ export declare function resolveEvery(every: CollectionSpawnEvery, sourceItem: CollectionItem): CollectionEvery | null;
35
42
  export interface ComputedSuccessor {
36
43
  id: string;
37
44
  record: CollectionItem;
@@ -1 +1 @@
1
- {"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../src/server/spawn.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,MAAM,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAkB,MAAM,gBAAgB,CAAC;AAExG,kDAAkD;AAClD,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAYD;;kDAEkD;AAClD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;kDACkD;AAClD,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAUzD;AAED,kDAAkD;AAClD,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAEnD;AAeD;;0DAE0D;AAC1D,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,GAAG,SAAS,CAYvF;AAED;;;oEAGoE;AACpE,wBAAgB,YAAY,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,SAAI,GAAG,OAAO,GAAG,IAAI,CAMzF;AAID;;;;;;uDAMuD;AACvD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAGrE;AAiBD,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,cAAc,CAAC;CACxB;AAED;;4CAE4C;AAC5C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAejI;AAED;;;;mEAImE;AACnE,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,cAAc,EAC1B,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,SAAc,GACrB,OAAO,CAAC,IAAI,CAAC,CAiCf"}
1
+ {"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../src/server/spawn.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,MAAM,CAAC;AAEjD,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,oBAAoB,EAAkB,MAAM,gBAAgB,CAAC;AAE9H,kDAAkD;AAClD,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAYD;;kDAEkD;AAClD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;kDACkD;AAClD,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAUzD;AAED,kDAAkD;AAClD,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAEnD;AAeD;;0DAE0D;AAC1D,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,GAAG,SAAS,CAYvF;AAED;;;oEAGoE;AACpE,wBAAgB,YAAY,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,SAAI,GAAG,OAAO,GAAG,IAAI,CAMzF;AAID;;;;;;uDAMuD;AACvD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAGrE;AAiBD;;;;;yDAKyD;AACzD,wBAAgB,YAAY,CAAC,KAAK,EAAE,oBAAoB,EAAE,UAAU,EAAE,cAAc,GAAG,eAAe,GAAG,IAAI,CAK5G;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,cAAc,CAAC;CACxB;AAED;;4CAE4C;AAC5C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAiBjI;AAoBD;;;;mEAImE;AACnE,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,cAAc,EAC1B,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,SAAc,GACrB,OAAO,CAAC,IAAI,CAAC,CAiCf"}