@mulmoclaude/core 0.23.0 → 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 (53) hide show
  1. package/assets/helps/collection-skills.md +39 -7
  2. package/assets/helps/custom-view.md +13 -9
  3. package/assets/skills-preset/mc-zenn/SKILL.md +31 -0
  4. package/dist/collection/core/completion.d.ts +18 -0
  5. package/dist/collection/core/deriveAll.d.ts +14 -9
  6. package/dist/collection/core/schema.d.ts +9 -4
  7. package/dist/collection/core/schemaZ.d.ts +97 -43
  8. package/dist/collection/index.cjs +2 -1
  9. package/dist/collection/index.cjs.map +1 -1
  10. package/dist/collection/index.d.ts +1 -0
  11. package/dist/collection/index.js +2 -2
  12. package/dist/collection/index.js.map +1 -1
  13. package/dist/collection/registry/server/index.cjs +1 -1
  14. package/dist/collection/registry/server/index.js +1 -1
  15. package/dist/collection/server/csvQuery.d.ts +13 -5
  16. package/dist/collection/server/csvStore.d.ts +2 -0
  17. package/dist/collection/server/index.cjs +4 -2
  18. package/dist/collection/server/index.d.ts +2 -1
  19. package/dist/collection/server/index.js +3 -3
  20. package/dist/collection/server/jsonlQuery.d.ts +4 -0
  21. package/dist/collection-watchers/index.cjs +5 -14
  22. package/dist/collection-watchers/index.cjs.map +1 -1
  23. package/dist/collection-watchers/index.js +2 -11
  24. package/dist/collection-watchers/index.js.map +1 -1
  25. package/dist/collection-watchers/reconciler.d.ts +2 -4
  26. package/dist/feeds/index.cjs +2 -2
  27. package/dist/feeds/index.js +2 -2
  28. package/dist/feeds/server/index.cjs +3 -3
  29. package/dist/feeds/server/index.js +3 -3
  30. package/dist/google/auth.d.ts +10 -1
  31. package/dist/google/authFlow.d.ts +1 -0
  32. package/dist/google/index.cjs +79 -38
  33. package/dist/google/index.cjs.map +1 -1
  34. package/dist/google/index.d.ts +1 -1
  35. package/dist/google/index.js +78 -39
  36. package/dist/google/index.js.map +1 -1
  37. package/dist/{ingestTypes-B-dXxUF9.js → ingestTypes-CFEgTItj.js} +2 -2
  38. package/dist/{ingestTypes-B-dXxUF9.js.map → ingestTypes-CFEgTItj.js.map} +1 -1
  39. package/dist/{ingestTypes-Cev9q77C.cjs → ingestTypes-Stc7iQyA.cjs} +2 -2
  40. package/dist/{ingestTypes-Cev9q77C.cjs.map → ingestTypes-Stc7iQyA.cjs.map} +1 -1
  41. package/dist/{promptSafety-rDWA9_JS.js → promptSafety-BLUcImzd.js} +54 -26
  42. package/dist/promptSafety-BLUcImzd.js.map +1 -0
  43. package/dist/{promptSafety-DRd15gQ6.cjs → promptSafety-DI_1Rvhk.cjs} +59 -25
  44. package/dist/promptSafety-DI_1Rvhk.cjs.map +1 -0
  45. package/dist/{server--FgDORd3.js → server-BpEo0FOd.js} +233 -57
  46. package/dist/server-BpEo0FOd.js.map +1 -0
  47. package/dist/{server-Q7ld-FlZ.cjs → server-CkysfLh4.cjs} +244 -56
  48. package/dist/server-CkysfLh4.cjs.map +1 -0
  49. package/package.json +1 -1
  50. package/dist/promptSafety-DRd15gQ6.cjs.map +0 -1
  51. package/dist/promptSafety-rDWA9_JS.js.map +0 -1
  52. package/dist/server--FgDORd3.js.map +0 -1
  53. package/dist/server-Q7ld-FlZ.cjs.map +0 -1
@@ -132,8 +132,8 @@ skipped, never crashes the host):
132
132
  | `singleton` | Optional. When set, at most one record exists, pinned to this exact id (e.g. `me`). Host pre-fills + locks the create form and hides Add once it exists. |
133
133
  | `fields` | Ordered map of field-name → field spec. **Insertion order = column order** in the table. Required. |
134
134
  | `actions` | Optional array of per-record buttons (see below). |
135
- | `completionField` | Optional. Name of the field whose value marks an item as "done" — when set, item-create fires a bell notification that clears once the field reaches one of `completionDoneValues`. Must name a real field in `fields`. Paired with `completionDoneValues` (both set, or both omitted). |
136
- | `completionDoneValues` | Optional. Non-empty array of values that count as "done" for `completionField` (e.g. `["Done"]`, `["paid", "void"]`). Compared as strings. |
135
+ | `completionField` | Optional. Name of the field whose value marks an item as "done" — when set, item-create fires a bell notification that clears once the item reads as done. Must name a real field in `fields`. Two forms: paired with `completionDoneValues` (done ⇔ the field's value is in that array), or naming a **`flag` field** (done ⇔ the flag's `where` matches — `completionDoneValues` must then be omitted). |
136
+ | `completionDoneValues` | Optional. Non-empty array of values that count as "done" for `completionField` (e.g. `["Done"]`, `["paid", "void"]`). Compared as strings. Omit when `completionField` names a `flag` field. |
137
137
  | `notifyWhen` | Optional. A `when` predicate (`{ "field": "...", "in": [...] }`) that **gates** the completion bell: fire it only for records matching the predicate (e.g. `{ "field": "priority", "in": ["high", "urgent"] }`). Requires `completionField`; `field` must name a real field. Absent ⇒ notify for every open record. |
138
138
  | `displayField` | Optional. Name of a field whose value is shown as the human-readable label in the completion notification's title (e.g. `Contacts: Jane Doe` instead of the opaque primaryKey). Must name a real field in `fields`. Falls back to the primaryKey value when unset or when the record's value is empty. |
139
139
  | `triggerField` | Optional. Name of a `date` field that **delays** the completion bell until that date arrives (instead of firing on create). Requires `completionField` / `completionDoneValues` (the bell still clears via the done value). Must name a real `date` field. See "Time-gated bells" below. |
@@ -149,7 +149,7 @@ skipped, never crashes the host):
149
149
 
150
150
  `string` · `text` (multi-line) · `email` · `number` · `date` (`YYYY-MM-DD`) ·
151
151
  `datetime` (`YYYY-MM-DDTHH:MM`) · `boolean` · `markdown` · `money` · `enum` ·
152
- `ref` · `embed` · `backlinks` · `rollup` · `table` · `derived` · `image` · `file` · `toggle`
152
+ `ref` · `embed` · `backlinks` · `rollup` · `table` · `derived` · `image` · `file` · `toggle` · `flag`
153
153
 
154
154
  Every field spec needs a `type` and a `label`. Extra keys by type:
155
155
 
@@ -249,6 +249,20 @@ Every field spec needs a `type` and a `label`. Extra keys by type:
249
249
  "done" checkbox. Without it, `status` only shows as a dropdown and a kanban
250
250
  column, with no checkbox to tick. `offValue` is the status to return to on
251
251
  uncheck (the default open column, e.g. `"Todo"`).
252
+ - **`flag`** — `where: [<conditions>]`. A **computed boolean**: true when the
253
+ record matches every condition (AND). **Never stored** (like `derived`); the
254
+ host recomputes it on every read, so you NEVER write flag values into the
255
+ JSON. Each condition is `{ "field": "<field>", "op": "<op>", "value": "..." }`
256
+ with ops `eq` / `ne` / `in` (array value) / `contains` / `gt` / `gte` / `lt` /
257
+ `lte`, or `{ ..., "valueFrom": { "field": "<sibling>" } }` to compare two
258
+ fields of the same record (`spent > budget`). Condition fields must name
259
+ declared fields; cross-record `valueFrom.record` is not allowed. A flag may
260
+ read `derived` / `rollup` values, and other flags via their stringified
261
+ boolean (`{ "field": "isDone", "op": "eq", "value": "true" }`). Use it for
262
+ generic state summaries — done-ness, pass/fail, qualification:
263
+ `{ "type": "flag", "label": "Passed", "where": [{ "field": "score", "op": "gte", "value": "60" }] }`.
264
+ A flag can also drive completion tracking (stored-field conditions only) —
265
+ see `completionField` above and the "Completion tracking" section below.
252
266
 
253
267
  ### Conditional field visibility (`when`)
254
268
 
@@ -474,6 +488,16 @@ with any field type whose stringified value is comparable (`enum`, `string`,
474
488
  ["paid", "void"]` on an invoice, or `completionField: "shipped"` +
475
489
  `completionDoneValues: ["true"]` on an order.
476
490
 
491
+ **Flag-form alternative**: `completionField` may instead name a **`flag`
492
+ field** — then done ⇔ the flag's `where` matches, and `completionDoneValues`
493
+ must be **omitted** (declaring it fails validation). Use it when done-ness is
494
+ richer than one field's membership (e.g. `"isDone": { "type": "flag", "where":
495
+ [{ "field": "score", "op": "gte", "value": "60" }] }` + `"completionField":
496
+ "isDone"`). Two extra rules apply only to a completion flag: its `where` may
497
+ reference **stored fields only** (no derived/rollup/toggle/flag/embed/backlinks
498
+ — completion is checked against the raw record), and combining it with `spawn`
499
+ requires an explicit `spawn.when`.
500
+
477
501
  Set `displayField` to make the bell title readable: with `displayField:
478
502
  "title"` the notification reads `Todos: Buy milk` instead of `Todos: t-0042`.
479
503
  It must name a real field; an empty value on a given record falls back to the
@@ -854,6 +878,13 @@ records through **`manageCollection`**, not raw file I/O:
854
878
  / `fields` on large collections to keep the result small — e.g.
855
879
  `fields: ["id"]` to check for an id collision before an add.
856
880
  - **Delete** — remove the record file (`manageCollection` has no delete).
881
+ - **Aggregate — `queryItems`.** Counts, sums, averages, group-bys on ANY
882
+ collection via a structured query (`groupBy` / `aggregates` / `where` /
883
+ `orderBy` / `limit` — full shape in the "External data (CSV) collections"
884
+ section below). On file-backed collections it aggregates the ENRICHED
885
+ records, so computed fields (`derived` / `rollup` / `toggle`) are
886
+ queryable columns — "sum of invoice totals" works even when `total` is a
887
+ formula. Prefer it over doing arithmetic on `getItems` output.
857
888
  - **Cross-collection questions — `getOntology`.** Returns every collection in
858
889
  the workspace with its `primaryKey`, effective `displayField`, record count,
859
890
  and its `ref` / `embed` / `backlinks` / `rollup` relations (field → related slug, including refs
@@ -961,10 +992,11 @@ Semantics to remember (and to tell the user):
961
992
  logged). Fine for browsing — but NEVER compute an aggregate from
962
993
  `getItems` output on a large file (a capped scan gives a silently wrong
963
994
  number). Use `queryItems` instead.
964
- - **Aggregation — `manageCollection` `queryItems`** (dataSource collections
965
- only): a structured query over the WHOLE file (uncapped scan, DuckDB
966
- underneath). Answer counts / sums / averages / group-bys with it —
967
- don't shell out to python/pandas for questions it covers. Shape:
995
+ - **Aggregation — `manageCollection` `queryItems`**: a structured query over
996
+ the WHOLE file (uncapped scan, DuckDB underneath). Answer counts / sums /
997
+ averages / group-bys with it — don't shell out to python/pandas for
998
+ questions it covers. (It works on EVERY collection see the Records
999
+ section; this bullet is about the dataSource specifics.) Shape:
968
1000
 
969
1001
  ```json
970
1002
  {
@@ -101,12 +101,14 @@ toggles, embeds) — the same numbers the user sees elsewhere.
101
101
  / shows one record at a time. Combinable with `fields`.
102
102
  - The primary key is always returned regardless of `fields`.
103
103
 
104
- ### Aggregation queries (dataSource/CSV collections; `read` capability)
104
+ ### Aggregation queries (`read` capability)
105
105
 
106
- On a collection backed by an external CSV (`dataSource` in its schema), a
107
- view can run structured aggregations over the WHOLE file the honest way
108
- to chart big data (the record read above is row-capped at 5,000; an
109
- aggregate computed from it would be silently wrong):
106
+ A view can run structured aggregations over the collection on a
107
+ `dataSource` (CSV) collection this scans the WHOLE file (the record read
108
+ above is row-capped at 5,000 there, so an aggregate computed from it would
109
+ be silently wrong); on a file-backed collection it aggregates the ENRICHED
110
+ records, so computed fields (`derived` / `rollup` / `toggle`) are queryable
111
+ columns:
110
112
 
111
113
  ```js
112
114
  const res = await fetch(dataUrl + "/query", {
@@ -130,10 +132,12 @@ const { rows } = await res.json(); // [{ Category, total, n }, ...] — chart th
130
132
  `groupBy`/`aggregates`; `orderBy` sorts by a groupBy column or an
131
133
  aggregate alias; result rows clamp at 1,000 by default.
132
134
  - Structured JSON only — there is **no SQL surface**, by design.
133
- - A file-backed (non-dataSource) collection answers 400 ("file-backed") —
134
- compute from the record read instead there.
135
- - Combine with `onChange` (below) to re-run the query when the CSV is
136
- replaced that's a live dashboard.
135
+ - Combine with `onChange` (below) to stay live: in the callback, re-run
136
+ **this POST query** (wrap it in your own `refresh()` and register that)
137
+ NOT the `?fields=` record read from the section above, which would
138
+ silently repaint an aggregation view with non-aggregated data. A
139
+ replaced CSV or edited records then redraw the chart — that's a live
140
+ dashboard.
137
141
 
138
142
  ### Writing records (only with the `write` capability)
139
143
 
@@ -43,9 +43,11 @@ unless the user already told you:
43
43
 
44
44
  - **Clone an existing Zenn repo** (they already write Zenn on GitHub). Get the
45
45
  repo URL, then:
46
+
46
47
  ```bash
47
48
  git clone <url> github/zenn
48
49
  ```
50
+
49
51
  `npx zenn` fetches zenn-cli on demand, so a missing local dependency is fine.
50
52
 
51
53
  - **Create a fresh project** (standard zenn-cli flow):
@@ -90,6 +92,7 @@ fill it in. **A published slug becomes the article URL and can't change** — pi
90
92
  it deliberately.
91
93
 
92
94
  **Step 3 — write the frontmatter** (Zenn house style):
95
+
93
96
  ```yaml
94
97
  ---
95
98
  title: "<a clear title, in the user's language>"
@@ -99,6 +102,7 @@ topics: ["MulmoClaude", "<related>"]
99
102
  published: true
100
103
  ---
101
104
  ```
105
+
102
106
  - **Always include `MulmoClaude` in `topics`.** At most 5 topics, no spaces
103
107
  inside a single topic.
104
108
  - `type` defaults to `tech`; `published` defaults to `true` (use `false` when
@@ -109,6 +113,33 @@ implementation (fenced ` ```lang ` blocks, runnable commands) → result → a s
109
113
  wrap-up. Informative but casual; describe the work, not yourself. Put images in
110
114
  `github/zenn/images/` and reference them as `![alt](/images/<file>)`.
111
115
 
116
+ Write it the way a person would, not the way a model defaults to. Each rule
117
+ below comes from real reader feedback — ignore them and the draft reads as
118
+ machine output:
119
+
120
+ - **Sound human, not like a generated listicle.** Prefer flowing prose over
121
+ walls of bullets, use bold sparingly, and let paragraphs connect into an
122
+ argument. If every section is just a heading plus a list, vary the rhythm.
123
+ - **No uncommon loanwords or jargon.** Use only terms a typical reader already
124
+ knows. Niche English acronyms, trendy katakana, and insider slang either get
125
+ dropped or replaced with plain words. A term the field itself hasn't settled
126
+ on ("code smell" and the like) is a red flag — say the plain thing instead
127
+ ("code that works now but bites you later").
128
+ - **Define every term and acronym on first use**, in plain language, and put the
129
+ foundational ones up front — define "DRY" before the article leans on it. A
130
+ reader should never hit a word they can't parse.
131
+ - **Carry a source's essence, don't just cite it.** When an idea comes from a
132
+ book or article, explain the idea itself in your own words; "see <book>"
133
+ teaches nothing. Search for the actual content when you're unsure what it says,
134
+ then write the substance.
135
+ - **Make the article self-contained.** Anything project-specific — a repo's
136
+ internals, a config choice, a domain constraint — needs enough general
137
+ background that a reader with zero context can follow. Running longer is fine
138
+ when the extra length buys understanding.
139
+ - **Match the stated audience.** "Explain to intermediate developers" means
140
+ patient explanations, concrete examples, real code from the work, and links —
141
+ not a terse summary.
142
+
112
143
  **Step 5 — save + preview.** Write `github/zenn/articles/<slug>.md`. Tell the
113
144
  user the path and how to preview: `cd github/zenn && npx zenn preview`
114
145
  (http://localhost:8000). Surface the title, slug, and topics.
@@ -0,0 +1,18 @@
1
+ import { Where } from './where';
2
+ /** The slice of a parsed schema the done predicate reads — minimal
3
+ * structural shape (like `DerivableSchema`) so the client and server
4
+ * `CollectionSchema` types both satisfy it as-is. */
5
+ export interface CompletionSchemaView {
6
+ /** Optional so legacy-pair callers (and their test fixtures) that
7
+ * never consult field specs keep working; only the flag form needs
8
+ * to look the completion field up. */
9
+ fields?: Record<string, {
10
+ type: string;
11
+ where?: Where;
12
+ }>;
13
+ completionField?: string;
14
+ completionDoneValues?: readonly string[];
15
+ }
16
+ /** True iff the schema declares completion tracking AND `item` is done
17
+ * under whichever completion form the schema uses (see module doc). */
18
+ export declare function itemIsDone(schema: CompletionSchemaView, item: Record<string, unknown>): boolean;
@@ -1,4 +1,5 @@
1
1
  import { FormulaContext } from './derivedFormula';
2
+ import { Where } from './where';
2
3
  /** Minimal field shape the derive loop needs — accepts both the client
3
4
  * FieldSpec and the server CollectionFieldSpec. */
4
5
  export interface DerivableFieldSpec {
@@ -7,6 +8,8 @@ export interface DerivableFieldSpec {
7
8
  to?: string;
8
9
  /** When type === "derived": formula evaluated against the record. */
9
10
  formula?: string;
11
+ /** When type === "flag": predicate matched against the record. */
12
+ where?: Where;
10
13
  }
11
14
  /** Minimal schema shape: just the ordered field map. */
12
15
  export interface DerivableSchema {
@@ -21,17 +24,19 @@ export type DeriveRefRecords = Record<string, Record<string, DerivableRecord>>;
21
24
  * null when dangling / not loaded), keyed by the LOCAL field name —
22
25
  * the shape `evaluateDerived` reads for `<field>.<col>` derefs. */
23
26
  export declare function resolveRowRefs(schema: DerivableSchema, record: DerivableRecord, refRecords: DeriveRefRecords): NonNullable<FormulaContext["refs"]>;
24
- /** Evaluate every `derived` field against `base`, saturating so a
25
- * derived field can read another derived field computed in an earlier
26
- * pass (`subtotal → tax → total` converges in ≤ field-count passes).
27
- * Cycles can't loop forever passes are bounded by the number of
28
- * derived fields and the loop breaks as soon as a pass changes
29
- * nothing. Failed formulas stay ABSENT (the UI renders them as
30
- * em-dash). Returns a copy; `base` is never mutated.
27
+ /** Evaluate every `derived` and `flag` field against `base`, saturating
28
+ * so a computed field can read another one computed in an earlier pass
29
+ * (`subtotal → tax → total` converges in ≤ field-count passes; a flag
30
+ * may read a derived value, or another flag via its stringified
31
+ * boolean). Cycles can't loop forever passes are bounded by the
32
+ * number of computed fields and the loop breaks as soon as a pass
33
+ * changes nothing. Failed formulas stay ABSENT (the UI renders them as
34
+ * em-dash); flags are total (always true/false). Returns a copy;
35
+ * `base` is never mutated.
31
36
  *
32
- * Derived keys already present in `base` are stripped before
37
+ * Computed keys already present in `base` are stripped before
33
38
  * evaluation: computed output is host-truth, never persisted-input
34
- * fallback. A record JSON can carry a stale (or forged) derived value
39
+ * fallback. A record JSON can carry a stale (or forged) computed value
35
40
  * — raw Write/Edit, legacy data — and without the strip, a failing
36
41
  * formula would silently surface that value as if the host computed
37
42
  * it. */
@@ -52,10 +52,15 @@ export type CollectionFieldSpec = z.infer<typeof FieldSpecZ>;
52
52
  * `derived` / display-only types (see `SubFieldSpecZ`). */
53
53
  export type CollectionSubFieldSpec = z.infer<typeof SubFieldSpecZ>;
54
54
  export type CollectionFieldType = CollectionFieldSpec["type"];
55
- /** derived/embed/backlinks/rollup/toggle are host-computed or projected
56
- * never written to the record JSON, so required / value checks and
57
- * edit-draft slots must not apply to them. THE single source for
58
- * "computed" — lives here (zod-free at runtime) so browser code
55
+ /** The computed-boolean variant a `where` predicate bound to a field
56
+ * name; see `FlagFieldZ`. */
57
+ export type CollectionFlagField = Extract<CollectionFieldSpec, {
58
+ type: "flag";
59
+ }>;
60
+ /** derived/embed/backlinks/rollup/toggle/flag are host-computed or
61
+ * projected — never written to the record JSON, so required / value
62
+ * checks and edit-draft slots must not apply to them. THE single source
63
+ * for "computed" — lives here (zod-free at runtime) so browser code
59
64
  * (`./draft`) and the zod record compiler (`./recordZ`, which re-exports
60
65
  * it) share one set instead of drifting copies. */
61
66
  export declare const COMPUTED_TYPES: ReadonlySet<CollectionFieldType>;
@@ -12,6 +12,46 @@ export declare const WhenZ: z.ZodObject<{
12
12
  field: z.ZodString;
13
13
  in: z.ZodArray<z.ZodString>;
14
14
  }, z.core.$strip>;
15
+ export declare const ValueRefZ: z.ZodObject<{
16
+ record: z.ZodOptional<z.ZodString>;
17
+ field: z.ZodString;
18
+ }, z.core.$strip>;
19
+ export declare const WhereCondZ: z.ZodObject<{
20
+ field: z.ZodString;
21
+ op: z.ZodEnum<{
22
+ in: "in";
23
+ eq: "eq";
24
+ ne: "ne";
25
+ gt: "gt";
26
+ gte: "gte";
27
+ lt: "lt";
28
+ lte: "lte";
29
+ contains: "contains";
30
+ }>;
31
+ value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
32
+ valueFrom: z.ZodOptional<z.ZodObject<{
33
+ record: z.ZodOptional<z.ZodString>;
34
+ field: z.ZodString;
35
+ }, z.core.$strip>>;
36
+ }, z.core.$strip>;
37
+ export declare const WhereZ: z.ZodArray<z.ZodObject<{
38
+ field: z.ZodString;
39
+ op: z.ZodEnum<{
40
+ in: "in";
41
+ eq: "eq";
42
+ ne: "ne";
43
+ gt: "gt";
44
+ gte: "gte";
45
+ lt: "lt";
46
+ lte: "lte";
47
+ contains: "contains";
48
+ }>;
49
+ value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
50
+ valueFrom: z.ZodOptional<z.ZodObject<{
51
+ record: z.ZodOptional<z.ZodString>;
52
+ field: z.ZodString;
53
+ }, z.core.$strip>>;
54
+ }, z.core.$strip>>;
15
55
  export declare const SubFieldSpecZ: z.ZodDiscriminatedUnion<[z.ZodObject<{
16
56
  label: z.ZodString;
17
57
  required: z.ZodOptional<z.ZodBoolean>;
@@ -210,6 +250,33 @@ export declare const FieldSpecZ: z.ZodDiscriminatedUnion<[z.ZodObject<{
210
250
  in: z.ZodArray<z.ZodString>;
211
251
  }, z.core.$strip>>;
212
252
  type: z.ZodLiteral<"toggle">;
253
+ }, z.core.$strip>, z.ZodObject<{
254
+ where: z.ZodArray<z.ZodObject<{
255
+ field: z.ZodString;
256
+ op: z.ZodEnum<{
257
+ in: "in";
258
+ eq: "eq";
259
+ ne: "ne";
260
+ gt: "gt";
261
+ gte: "gte";
262
+ lt: "lt";
263
+ lte: "lte";
264
+ contains: "contains";
265
+ }>;
266
+ value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
267
+ valueFrom: z.ZodOptional<z.ZodObject<{
268
+ record: z.ZodOptional<z.ZodString>;
269
+ field: z.ZodString;
270
+ }, z.core.$strip>>;
271
+ }, z.core.$strip>>;
272
+ label: z.ZodString;
273
+ primary: z.ZodOptional<z.ZodBoolean>;
274
+ required: z.ZodOptional<z.ZodBoolean>;
275
+ when: z.ZodOptional<z.ZodObject<{
276
+ field: z.ZodString;
277
+ in: z.ZodArray<z.ZodString>;
278
+ }, z.core.$strip>>;
279
+ type: z.ZodLiteral<"flag">;
213
280
  }, z.core.$strip>], "type">;
214
281
  /** A schema-declared record action, rendered as a button in the read-only
215
282
  * detail view. Domain-free: the host validates the shape; the meaning
@@ -469,46 +536,6 @@ export declare const IngestZ: z.ZodDiscriminatedUnion<[z.ZodObject<{
469
536
  role: z.ZodString;
470
537
  template: z.ZodString;
471
538
  }, z.core.$strip>], "kind">;
472
- export declare const ValueRefZ: z.ZodObject<{
473
- record: z.ZodOptional<z.ZodString>;
474
- field: z.ZodString;
475
- }, z.core.$strip>;
476
- export declare const WhereCondZ: z.ZodObject<{
477
- field: z.ZodString;
478
- op: z.ZodEnum<{
479
- in: "in";
480
- eq: "eq";
481
- ne: "ne";
482
- gt: "gt";
483
- gte: "gte";
484
- lt: "lt";
485
- lte: "lte";
486
- contains: "contains";
487
- }>;
488
- value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
489
- valueFrom: z.ZodOptional<z.ZodObject<{
490
- record: z.ZodOptional<z.ZodString>;
491
- field: z.ZodString;
492
- }, z.core.$strip>>;
493
- }, z.core.$strip>;
494
- export declare const WhereZ: z.ZodArray<z.ZodObject<{
495
- field: z.ZodString;
496
- op: z.ZodEnum<{
497
- in: "in";
498
- eq: "eq";
499
- ne: "ne";
500
- gt: "gt";
501
- gte: "gte";
502
- lt: "lt";
503
- lte: "lte";
504
- contains: "contains";
505
- }>;
506
- value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
507
- valueFrom: z.ZodOptional<z.ZodObject<{
508
- record: z.ZodOptional<z.ZodString>;
509
- field: z.ZodString;
510
- }, z.core.$strip>>;
511
- }, z.core.$strip>>;
512
539
  export declare const DynamicIconSourceZ: z.ZodObject<{
513
540
  collection: z.ZodString;
514
541
  from: z.ZodOptional<z.ZodEnum<{
@@ -616,12 +643,12 @@ export declare const DynamicIconSpecZ: z.ZodObject<{
616
643
  * workspace-relative and containment-checked exactly like `dataPath`. The
617
644
  * row-id column is the schema's existing `primaryKey` — there is
618
645
  * deliberately no second key concept here.
619
- * See plans/feat-collection-csv-duckdb-source.md. */
646
+ * See plans/done/feat-collection-csv-duckdb-source.md. */
620
647
  export declare const DataSourceZ: z.ZodObject<{
621
648
  type: z.ZodLiteral<"csv">;
622
649
  path: z.ZodString;
623
650
  }, z.core.$strip>;
624
- export declare const CollectionSchemaZ: z.ZodObject<{
651
+ export declare const CollectionSchemaZ: z.ZodPreprocess<z.ZodObject<{
625
652
  title: z.ZodString;
626
653
  icon: z.ZodString;
627
654
  dataPath: z.ZodOptional<z.ZodString>;
@@ -799,6 +826,33 @@ export declare const CollectionSchemaZ: z.ZodObject<{
799
826
  in: z.ZodArray<z.ZodString>;
800
827
  }, z.core.$strip>>;
801
828
  type: z.ZodLiteral<"toggle">;
829
+ }, z.core.$strip>, z.ZodObject<{
830
+ where: z.ZodArray<z.ZodObject<{
831
+ field: z.ZodString;
832
+ op: z.ZodEnum<{
833
+ in: "in";
834
+ eq: "eq";
835
+ ne: "ne";
836
+ gt: "gt";
837
+ gte: "gte";
838
+ lt: "lt";
839
+ lte: "lte";
840
+ contains: "contains";
841
+ }>;
842
+ value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
843
+ valueFrom: z.ZodOptional<z.ZodObject<{
844
+ record: z.ZodOptional<z.ZodString>;
845
+ field: z.ZodString;
846
+ }, z.core.$strip>>;
847
+ }, z.core.$strip>>;
848
+ label: z.ZodString;
849
+ primary: z.ZodOptional<z.ZodBoolean>;
850
+ required: z.ZodOptional<z.ZodBoolean>;
851
+ when: z.ZodOptional<z.ZodObject<{
852
+ field: z.ZodString;
853
+ in: z.ZodArray<z.ZodString>;
854
+ }, z.core.$strip>>;
855
+ type: z.ZodLiteral<"flag">;
802
856
  }, z.core.$strip>], "type">>;
803
857
  actions: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
804
858
  role: z.ZodString;
@@ -1053,4 +1107,4 @@ export declare const CollectionSchemaZ: z.ZodObject<{
1053
1107
  }, z.core.$strip>>;
1054
1108
  fallback: z.ZodOptional<z.ZodString>;
1055
1109
  }, z.core.$strip>>;
1056
- }, z.core.$strip>;
1110
+ }, z.core.$strip>>;
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_promptSafety = require("../promptSafety-DRd15gQ6.cjs");
2
+ const require_promptSafety = require("../promptSafety-DI_1Rvhk.cjs");
3
3
  const require_errorMessage = require("../errorMessage--LvXe_Jx.cjs");
4
4
  //#region src/collection/core/presentCollection.ts
5
5
  var TOOL_NAME = "presentCollection";
@@ -483,6 +483,7 @@ exports.isSafeRecordId = require_promptSafety.isSafeRecordId;
483
483
  exports.isSafeSlug = require_promptSafety.isSafeSlug;
484
484
  exports.isSortableField = isSortableField;
485
485
  exports.itemIdOf = itemIdOf;
486
+ exports.itemIsDone = require_promptSafety.itemIsDone;
486
487
  exports.itemLabelOf = itemLabelOf;
487
488
  exports.labelFieldFor = labelFieldFor;
488
489
  exports.matchesWhere = require_promptSafety.matchesWhere;