@mulmoclaude/core 3.7.0 → 3.10.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 (74) hide show
  1. package/dist/collection/core/itemId.d.ts +28 -0
  2. package/dist/collection/firestore.cjs +9 -1
  3. package/dist/collection/firestore.cjs.map +1 -1
  4. package/dist/collection/firestore.js +10 -2
  5. package/dist/collection/firestore.js.map +1 -1
  6. package/dist/collection/index.cjs +55 -66
  7. package/dist/collection/index.cjs.map +1 -1
  8. package/dist/collection/index.d.ts +1 -1
  9. package/dist/collection/index.js +3 -15
  10. package/dist/collection/index.js.map +1 -1
  11. package/dist/collection/registry/server/index.cjs +19 -19
  12. package/dist/collection/registry/server/index.cjs.map +1 -1
  13. package/dist/collection/registry/server/index.js +2 -2
  14. package/dist/collection/server/firestoreDocs.d.ts +18 -0
  15. package/dist/collection/server/host.d.ts +29 -0
  16. package/dist/collection/server/index.cjs +70 -62
  17. package/dist/collection/server/index.d.ts +2 -3
  18. package/dist/collection/server/index.js +4 -4
  19. package/dist/collection/server/io.d.ts +5 -3
  20. package/dist/collection/server/manageTool.d.ts +0 -4
  21. package/dist/collection/server/publishProject.d.ts +171 -2
  22. package/dist/collection-watchers/index.cjs +82 -38
  23. package/dist/collection-watchers/index.cjs.map +1 -1
  24. package/dist/collection-watchers/index.js +67 -23
  25. package/dist/collection-watchers/index.js.map +1 -1
  26. package/dist/{store-_61sO8K8.js → discovery-B9zdNkgW.js} +2525 -2354
  27. package/dist/discovery-B9zdNkgW.js.map +1 -0
  28. package/dist/{store-5_P_NsGa.cjs → discovery-BsXiDZBR.cjs} +2545 -2362
  29. package/dist/discovery-BsXiDZBR.cjs.map +1 -0
  30. package/dist/feeds/index.cjs +4 -4
  31. package/dist/feeds/index.js +2 -2
  32. package/dist/feeds/server/index.cjs +14 -14
  33. package/dist/feeds/server/index.cjs.map +1 -1
  34. package/dist/feeds/server/index.js +4 -4
  35. package/dist/firestore/listen.d.ts +4 -0
  36. package/dist/google/index.cjs +16 -16
  37. package/dist/google/index.cjs.map +1 -1
  38. package/dist/google/index.js +2 -2
  39. package/dist/{ingestTypes-CEi-Ot7F.js → ingestTypes-B312BwXg.js} +2 -2
  40. package/dist/{ingestTypes-CEi-Ot7F.js.map → ingestTypes-B312BwXg.js.map} +1 -1
  41. package/dist/{ingestTypes-iaiq33Ph.cjs → ingestTypes-B4XfrUoq.cjs} +3 -3
  42. package/dist/{ingestTypes-iaiq33Ph.cjs.map → ingestTypes-B4XfrUoq.cjs.map} +1 -1
  43. package/dist/{calendarGrid-CQ8MVSRb.js → itemId-DfTm08jm.js} +34 -2
  44. package/dist/itemId-DfTm08jm.js.map +1 -0
  45. package/dist/{calendarGrid-DGILaVxI.cjs → itemId-Dzrr3vs5.cjs} +45 -1
  46. package/dist/itemId-Dzrr3vs5.cjs.map +1 -0
  47. package/dist/listen-D5av7GzB.js +22 -0
  48. package/dist/listen-D5av7GzB.js.map +1 -0
  49. package/dist/listen-UZA68Upt.cjs +45 -0
  50. package/dist/listen-UZA68Upt.cjs.map +1 -0
  51. package/dist/{promptSafety-CpiME8pj.js → promptSafety-CSdyp7RF.js} +2 -2
  52. package/dist/{promptSafety-CpiME8pj.js.map → promptSafety-CSdyp7RF.js.map} +1 -1
  53. package/dist/{promptSafety-NNGViiCr.cjs → promptSafety-CWqYq-NS.cjs} +8 -8
  54. package/dist/{promptSafety-NNGViiCr.cjs.map → promptSafety-CWqYq-NS.cjs.map} +1 -1
  55. package/dist/remote-host/server/hostRunner.d.ts +2 -4
  56. package/dist/remote-host/server/index.cjs +4 -19
  57. package/dist/remote-host/server/index.cjs.map +1 -1
  58. package/dist/remote-host/server/index.js +1 -16
  59. package/dist/remote-host/server/index.js.map +1 -1
  60. package/dist/{server-B48Jyxcj.js → server-BNe8XMtu.js} +388 -568
  61. package/dist/server-BNe8XMtu.js.map +1 -0
  62. package/dist/{server-CWZyg8fn.cjs → server-CgkkWWBd.cjs} +590 -734
  63. package/dist/server-CgkkWWBd.cjs.map +1 -0
  64. package/dist/whisper/index.cjs +1 -1
  65. package/dist/whisper/index.js +1 -1
  66. package/package.json +1 -1
  67. package/dist/calendarGrid-CQ8MVSRb.js.map +0 -1
  68. package/dist/calendarGrid-DGILaVxI.cjs.map +0 -1
  69. package/dist/collection/core/shortHexId.d.ts +0 -8
  70. package/dist/collection/server/publish.d.ts +0 -56
  71. package/dist/server-B48Jyxcj.js.map +0 -1
  72. package/dist/server-CWZyg8fn.cjs.map +0 -1
  73. package/dist/store-5_P_NsGa.cjs.map +0 -1
  74. package/dist/store-_61sO8K8.js.map +0 -1
@@ -0,0 +1,28 @@
1
+ /**
2
+ * A generated record id: a v4 UUID with its hyphens stripped — 32 lowercase hex
3
+ * characters, 122 bits.
4
+ *
5
+ * The ONE generator behind both blank-id create paths — the server's
6
+ * `generateItemId()` (../server/io) delegates here, so the UI's pre-filled id
7
+ * and the id a blank-id POST mints are the same thing rather than two
8
+ * implementations that have to agree.
9
+ *
10
+ * It replaced an 8-hex-char id, whose 32 bits collided at a 1.2% rate across
11
+ * 10k records — and a collision surfaced as `item '<id>' already exists`, which
12
+ * named a duplicate that did not exist (#2851).
13
+ *
14
+ * **The hyphens have to go.** A record id in a `googleCalendar` collection is
15
+ * sent to Google as the caller-chosen event id, and Google takes base32hex only
16
+ * (`isClientSettableEventId`, ../../google/pushPlan) — a hyphenated UUID is
17
+ * refused, so every UI-created record would push as "the record id cannot be
18
+ * used as a Google event id". Hex is a subset of base32hex, so the stripped
19
+ * form satisfies both that and `SAFE_RECORD_ID_PATTERN` (the id is also the
20
+ * `<id>.json` filename stem).
21
+ */
22
+ export declare function newItemId(): string;
23
+ /** @deprecated Use {@link newItemId}. Kept as a compatibility export because
24
+ * `@mulmoclaude/core/collection` is public API (same reason as
25
+ * `CollectionActionWhen` in ./schema). It is the NEW generator, not the old
26
+ * 8-hex one: that width is the bug #2851 reported, and leaving a copy of it
27
+ * reachable under an old name would keep shipping it. */
28
+ export declare const shortHexId: typeof newItemId;
@@ -42,7 +42,15 @@ function createFirestoreDocs(database) {
42
42
  if (!(await transaction.get(ref)).exists()) return false;
43
43
  transaction.delete(ref);
44
44
  return true;
45
- })
45
+ }),
46
+ watch: (collectionPath, onChanged, onError) => {
47
+ let seen = false;
48
+ return (0, firebase_firestore.onSnapshot)((0, firebase_firestore.collection)(database, collectionPath), (snapshot) => {
49
+ const initial = !seen;
50
+ seen = true;
51
+ onChanged(snapshot.docChanges().map((change) => change.doc.id), { initial });
52
+ }, onError);
53
+ }
46
54
  };
47
55
  }
48
56
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"firestore.cjs","names":[],"sources":["../../src/collection/server/firestoreDocs.ts"],"sourcesContent":["// The seam between the firestore store and the Firestore SDK.\n//\n// The modular SDK is function-based (`getDocs(query(collection(db, …)))`), so a\n// store that imported those functions directly could not be tested without a\n// real backend — a fake `db` would still be handed to the real functions.\n// Narrowing to this interface makes the backend swappable: core ships\n// `createFirestoreDocs` over the real SDK, and the tests inject an in-memory\n// fake that satisfies the same shape. That is what lets this repository's tests\n// run with no API key and no network.\n//\n// Deliberately minimal and id-keyed: no query builder, no field ordering, no\n// cursors. Everything the store needs is \"the documents of one collection path,\n// ordered by document id\" — see the store header for why field ordering is\n// avoided entirely.\n//\n// The collection path is an ARGUMENT, not something this module composes. It\n// owns the SDK calls; `firestoreStore` owns where the documents live.\n\nimport {\n collection as firestoreCollection,\n doc,\n getDoc,\n getDocs,\n orderBy,\n query as firestoreQuery,\n runTransaction,\n setDoc,\n type Firestore,\n} from \"firebase/firestore\";\n\n/** One stored record document. `data` is the document's own fields — the\n * record itself, not a wrapper around it; see `set` below. The store\n * validates its shape, because a document written by hand could be\n * anything. */\nexport interface FirestoreDoc {\n id: string;\n data: unknown;\n}\n\nexport interface FirestoreDocs {\n /** Every document under `collectionPath`, ordered by document id. */\n list: (collectionPath: string) => Promise<FirestoreDoc[]>;\n /** One document's fields, or null when it doesn't exist. */\n get: (collectionPath: string, docId: string) => Promise<unknown | null>;\n /** Create or replace. */\n set: (collectionPath: string, docId: string, data: Record<string, unknown>) => Promise<void>;\n /** Create only. Returns false when the id already exists — atomic, so two\n * concurrent creates can't both observe \"missing\". */\n create: (collectionPath: string, docId: string, data: Record<string, unknown>) => Promise<boolean>;\n /** Delete. Returns false when the id didn't exist, so a caller can tell a\n * real delete from a typo'd id. */\n delete: (collectionPath: string, docId: string) => Promise<boolean>;\n}\n\n/** The real implementation over the modular SDK.\n *\n * THE RECORD IS THE DOCUMENT. Its fields are written at the top level, not\n * nested under a `data` key. This is not a matter of taste: the deployed\n * security rules read `request.resource.data.<field>` and\n * `resource.data[submit.emailField]` — a wrapper would put every field one\n * level down, so the required-field checks, the status state machine and the\n * \"your own row\" predicate would all read absent values and fail closed. A\n * shared record's shape is part of the authorization contract.\n *\n * `orderBy(\"__name__\")` orders by DOCUMENT ID. Ordering by a record field\n * would silently EXCLUDE documents missing that field (the trap\n * `remote-host/server/hostRunner.ts:158-169` documents), turning a read into a\n * partial one; the document id is always present and gives the stable order\n * the store contract requires. */\nexport function createFirestoreDocs(database: Firestore): FirestoreDocs {\n return {\n list: async (collectionPath) => {\n const snapshot = await getDocs(firestoreQuery(firestoreCollection(database, collectionPath), orderBy(\"__name__\")));\n return snapshot.docs.map((entry) => ({ id: entry.id, data: entry.data() }));\n },\n get: async (collectionPath, docId) => {\n const snapshot = await getDoc(doc(database, collectionPath, docId));\n return snapshot.exists() ? snapshot.data() : null;\n },\n set: async (collectionPath, docId, data) => {\n await setDoc(doc(database, collectionPath, docId), data);\n },\n create: (collectionPath, docId, data) =>\n runTransaction(database, async (transaction) => {\n const ref = doc(database, collectionPath, docId);\n const existing = await transaction.get(ref);\n if (existing.exists()) return false;\n transaction.set(ref, data);\n return true;\n }),\n // Firestore's deleteDoc succeeds on a missing document, so an existence\n // check is what makes \"deleted\" distinguishable from \"there was nothing\".\n // It runs INSIDE the transaction (like `create`): a plain get-then-delete\n // would report `true` for a document a concurrent client had already\n // removed, i.e. claim a delete this call never performed.\n delete: (collectionPath, docId) =>\n runTransaction(database, async (transaction) => {\n const ref = doc(database, collectionPath, docId);\n const existing = await transaction.get(ref);\n if (!existing.exists()) return false;\n transaction.delete(ref);\n return true;\n }),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAqEA,SAAgB,oBAAoB,UAAoC;CACtE,OAAO;EACL,MAAM,OAAO,mBAAmB;GAE9B,QAAO,OAAA,GADgB,mBAAA,QAAA,EAAA,GAAQ,mBAAA,MAAA,EAAA,GAAe,mBAAA,WAAA,CAAoB,UAAU,cAAc,IAAA,GAAG,mBAAA,QAAA,CAAQ,UAAU,CAAC,CAAC,EAAA,CACjG,KAAK,KAAK,WAAW;IAAE,IAAI,MAAM;IAAI,MAAM,MAAM,KAAK;GAAE,EAAE;EAC5E;EACA,KAAK,OAAO,gBAAgB,UAAU;GACpC,MAAM,WAAW,OAAA,GAAM,mBAAA,OAAA,EAAA,GAAO,mBAAA,IAAA,CAAI,UAAU,gBAAgB,KAAK,CAAC;GAClE,OAAO,SAAS,OAAO,IAAI,SAAS,KAAK,IAAI;EAC/C;EACA,KAAK,OAAO,gBAAgB,OAAO,SAAS;GAC1C,OAAA,GAAM,mBAAA,OAAA,EAAA,GAAO,mBAAA,IAAA,CAAI,UAAU,gBAAgB,KAAK,GAAG,IAAI;EACzD;EACA,SAAS,gBAAgB,OAAO,UAAA,GAC9B,mBAAA,eAAA,CAAe,UAAU,OAAO,gBAAgB;GAC9C,MAAM,OAAA,GAAM,mBAAA,IAAA,CAAI,UAAU,gBAAgB,KAAK;GAE/C,KAAI,MADmB,YAAY,IAAI,GAAG,EAAA,CAC7B,OAAO,GAAG,OAAO;GAC9B,YAAY,IAAI,KAAK,IAAI;GACzB,OAAO;EACT,CAAC;EAMH,SAAS,gBAAgB,WAAA,GACvB,mBAAA,eAAA,CAAe,UAAU,OAAO,gBAAgB;GAC9C,MAAM,OAAA,GAAM,mBAAA,IAAA,CAAI,UAAU,gBAAgB,KAAK;GAE/C,IAAI,EAAC,MADkB,YAAY,IAAI,GAAG,EAAA,CAC5B,OAAO,GAAG,OAAO;GAC/B,YAAY,OAAO,GAAG;GACtB,OAAO;EACT,CAAC;CACL;AACF"}
1
+ {"version":3,"file":"firestore.cjs","names":[],"sources":["../../src/collection/server/firestoreDocs.ts"],"sourcesContent":["// The seam between the firestore store and the Firestore SDK.\n//\n// The modular SDK is function-based (`getDocs(query(collection(db, …)))`), so a\n// store that imported those functions directly could not be tested without a\n// real backend — a fake `db` would still be handed to the real functions.\n// Narrowing to this interface makes the backend swappable: core ships\n// `createFirestoreDocs` over the real SDK, and the tests inject an in-memory\n// fake that satisfies the same shape. That is what lets this repository's tests\n// run with no API key and no network.\n//\n// Deliberately minimal and id-keyed: no query builder, no field ordering, no\n// cursors. Everything the store needs is \"the documents of one collection path,\n// ordered by document id\" — see the store header for why field ordering is\n// avoided entirely.\n//\n// The collection path is an ARGUMENT, not something this module composes. It\n// owns the SDK calls; `firestoreStore` owns where the documents live.\n\nimport {\n collection as firestoreCollection,\n doc,\n getDoc,\n getDocs,\n orderBy,\n query as firestoreQuery,\n onSnapshot,\n runTransaction,\n setDoc,\n type Firestore,\n} from \"firebase/firestore\";\n\n/** One stored record document. `data` is the document's own fields — the\n * record itself, not a wrapper around it; see `set` below. The store\n * validates its shape, because a document written by hand could be\n * anything. */\nexport interface FirestoreDoc {\n id: string;\n data: unknown;\n}\n\nexport interface FirestoreDocs {\n /** Every document under `collectionPath`, ordered by document id. */\n list: (collectionPath: string) => Promise<FirestoreDoc[]>;\n /** One document's fields, or null when it doesn't exist. */\n get: (collectionPath: string, docId: string) => Promise<unknown | null>;\n /** Create or replace. */\n set: (collectionPath: string, docId: string, data: Record<string, unknown>) => Promise<void>;\n /** Create only. Returns false when the id already exists — atomic, so two\n * concurrent creates can't both observe \"missing\". */\n create: (collectionPath: string, docId: string, data: Record<string, unknown>) => Promise<boolean>;\n /** Delete. Returns false when the id didn't exist, so a caller can tell a\n * real delete from a typo'd id. */\n delete: (collectionPath: string, docId: string) => Promise<boolean>;\n /** Listen to `collectionPath`. Every snapshot reports the ids that changed\n * in it, and whether it is the FIRST one.\n *\n * `initial` is not a nicety. `onSnapshot` delivers the current contents\n * immediately, as one snapshot in which every existing document reads as\n * `added` — so a listener that treats snapshots uniformly announces the\n * whole collection as changed the moment it arms, on every mount. The flag\n * is passed up rather than swallowed here so the decision (and its test)\n * lives with the store's policy, next to the rest of it.\n *\n * `onError` fires at most once per subscription: a Firestore listen error\n * TERMINATES the listener and never recovers on its own. Re-subscribing is\n * the caller's job (`firestore/listen.ts` holds the policy).\n *\n * Returns the detach function synchronously — `onSnapshot` is not async. */\n watch: (collectionPath: string, onChanged: (ids: string[], meta: { initial: boolean }) => void, onError: (error: unknown) => void) => () => void;\n}\n\n/** The real implementation over the modular SDK.\n *\n * THE RECORD IS THE DOCUMENT. Its fields are written at the top level, not\n * nested under a `data` key. This is not a matter of taste: the deployed\n * security rules read `request.resource.data.<field>` and\n * `resource.data[submit.emailField]` — a wrapper would put every field one\n * level down, so the required-field checks, the status state machine and the\n * \"your own row\" predicate would all read absent values and fail closed. A\n * shared record's shape is part of the authorization contract.\n *\n * `orderBy(\"__name__\")` orders by DOCUMENT ID. Ordering by a record field\n * would silently EXCLUDE documents missing that field (the trap\n * `remote-host/server/hostRunner.ts:158-169` documents), turning a read into a\n * partial one; the document id is always present and gives the stable order\n * the store contract requires. */\nexport function createFirestoreDocs(database: Firestore): FirestoreDocs {\n return {\n list: async (collectionPath) => {\n const snapshot = await getDocs(firestoreQuery(firestoreCollection(database, collectionPath), orderBy(\"__name__\")));\n return snapshot.docs.map((entry) => ({ id: entry.id, data: entry.data() }));\n },\n get: async (collectionPath, docId) => {\n const snapshot = await getDoc(doc(database, collectionPath, docId));\n return snapshot.exists() ? snapshot.data() : null;\n },\n set: async (collectionPath, docId, data) => {\n await setDoc(doc(database, collectionPath, docId), data);\n },\n create: (collectionPath, docId, data) =>\n runTransaction(database, async (transaction) => {\n const ref = doc(database, collectionPath, docId);\n const existing = await transaction.get(ref);\n if (existing.exists()) return false;\n transaction.set(ref, data);\n return true;\n }),\n // Firestore's deleteDoc succeeds on a missing document, so an existence\n // check is what makes \"deleted\" distinguishable from \"there was nothing\".\n // It runs INSIDE the transaction (like `create`): a plain get-then-delete\n // would report `true` for a document a concurrent client had already\n // removed, i.e. claim a delete this call never performed.\n delete: (collectionPath, docId) =>\n runTransaction(database, async (transaction) => {\n const ref = doc(database, collectionPath, docId);\n const existing = await transaction.get(ref);\n if (!existing.exists()) return false;\n transaction.delete(ref);\n return true;\n }),\n // `docChanges()` rather than the whole snapshot: it names the documents\n // that moved, which is what lets the store report per-record changes\n // instead of \"something in this collection changed\". Added, modified and\n // removed are all reported the same way — the store's listener takes an\n // id, and re-reads; what KIND of change it was is not something a\n // reconcile pass needs to be told.\n //\n // `includeMetadataChanges` is deliberately left off: local writes and\n // has-pending-writes flips would otherwise wake every listener for\n // changes this process just made.\n watch: (collectionPath, onChanged, onError) => {\n let seen = false;\n return onSnapshot(\n firestoreCollection(database, collectionPath),\n (snapshot) => {\n const initial = !seen;\n seen = true;\n onChanged(\n snapshot.docChanges().map((change) => change.doc.id),\n { initial },\n );\n },\n onError,\n );\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAsFA,SAAgB,oBAAoB,UAAoC;CACtE,OAAO;EACL,MAAM,OAAO,mBAAmB;GAE9B,QAAO,OAAA,GADgB,mBAAA,QAAA,EAAA,GAAQ,mBAAA,MAAA,EAAA,GAAe,mBAAA,WAAA,CAAoB,UAAU,cAAc,IAAA,GAAG,mBAAA,QAAA,CAAQ,UAAU,CAAC,CAAC,EAAA,CACjG,KAAK,KAAK,WAAW;IAAE,IAAI,MAAM;IAAI,MAAM,MAAM,KAAK;GAAE,EAAE;EAC5E;EACA,KAAK,OAAO,gBAAgB,UAAU;GACpC,MAAM,WAAW,OAAA,GAAM,mBAAA,OAAA,EAAA,GAAO,mBAAA,IAAA,CAAI,UAAU,gBAAgB,KAAK,CAAC;GAClE,OAAO,SAAS,OAAO,IAAI,SAAS,KAAK,IAAI;EAC/C;EACA,KAAK,OAAO,gBAAgB,OAAO,SAAS;GAC1C,OAAA,GAAM,mBAAA,OAAA,EAAA,GAAO,mBAAA,IAAA,CAAI,UAAU,gBAAgB,KAAK,GAAG,IAAI;EACzD;EACA,SAAS,gBAAgB,OAAO,UAAA,GAC9B,mBAAA,eAAA,CAAe,UAAU,OAAO,gBAAgB;GAC9C,MAAM,OAAA,GAAM,mBAAA,IAAA,CAAI,UAAU,gBAAgB,KAAK;GAE/C,KAAI,MADmB,YAAY,IAAI,GAAG,EAAA,CAC7B,OAAO,GAAG,OAAO;GAC9B,YAAY,IAAI,KAAK,IAAI;GACzB,OAAO;EACT,CAAC;EAMH,SAAS,gBAAgB,WAAA,GACvB,mBAAA,eAAA,CAAe,UAAU,OAAO,gBAAgB;GAC9C,MAAM,OAAA,GAAM,mBAAA,IAAA,CAAI,UAAU,gBAAgB,KAAK;GAE/C,IAAI,EAAC,MADkB,YAAY,IAAI,GAAG,EAAA,CAC5B,OAAO,GAAG,OAAO;GAC/B,YAAY,OAAO,GAAG;GACtB,OAAO;EACT,CAAC;EAWH,QAAQ,gBAAgB,WAAW,YAAY;GAC7C,IAAI,OAAO;GACX,QAAA,GAAO,mBAAA,WAAA,EAAA,GACL,mBAAA,WAAA,CAAoB,UAAU,cAAc,IAC3C,aAAa;IACZ,MAAM,UAAU,CAAC;IACjB,OAAO;IACP,UACE,SAAS,WAAW,CAAC,CAAC,KAAK,WAAW,OAAO,IAAI,EAAE,GACnD,EAAE,QAAQ,CACZ;GACF,GACA,OACF;EACF;CACF;AACF"}
@@ -1,4 +1,4 @@
1
- import { collection, doc, getDoc, getDocs, orderBy, query, runTransaction, setDoc } from "firebase/firestore";
1
+ import { collection, doc, getDoc, getDocs, onSnapshot, orderBy, query, runTransaction, setDoc } from "firebase/firestore";
2
2
  //#region src/collection/server/firestoreDocs.ts
3
3
  /** The real implementation over the modular SDK.
4
4
  *
@@ -41,7 +41,15 @@ function createFirestoreDocs(database) {
41
41
  if (!(await transaction.get(ref)).exists()) return false;
42
42
  transaction.delete(ref);
43
43
  return true;
44
- })
44
+ }),
45
+ watch: (collectionPath, onChanged, onError) => {
46
+ let seen = false;
47
+ return onSnapshot(collection(database, collectionPath), (snapshot) => {
48
+ const initial = !seen;
49
+ seen = true;
50
+ onChanged(snapshot.docChanges().map((change) => change.doc.id), { initial });
51
+ }, onError);
52
+ }
45
53
  };
46
54
  }
47
55
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"firestore.js","names":[],"sources":["../../src/collection/server/firestoreDocs.ts"],"sourcesContent":["// The seam between the firestore store and the Firestore SDK.\n//\n// The modular SDK is function-based (`getDocs(query(collection(db, …)))`), so a\n// store that imported those functions directly could not be tested without a\n// real backend — a fake `db` would still be handed to the real functions.\n// Narrowing to this interface makes the backend swappable: core ships\n// `createFirestoreDocs` over the real SDK, and the tests inject an in-memory\n// fake that satisfies the same shape. That is what lets this repository's tests\n// run with no API key and no network.\n//\n// Deliberately minimal and id-keyed: no query builder, no field ordering, no\n// cursors. Everything the store needs is \"the documents of one collection path,\n// ordered by document id\" — see the store header for why field ordering is\n// avoided entirely.\n//\n// The collection path is an ARGUMENT, not something this module composes. It\n// owns the SDK calls; `firestoreStore` owns where the documents live.\n\nimport {\n collection as firestoreCollection,\n doc,\n getDoc,\n getDocs,\n orderBy,\n query as firestoreQuery,\n runTransaction,\n setDoc,\n type Firestore,\n} from \"firebase/firestore\";\n\n/** One stored record document. `data` is the document's own fields — the\n * record itself, not a wrapper around it; see `set` below. The store\n * validates its shape, because a document written by hand could be\n * anything. */\nexport interface FirestoreDoc {\n id: string;\n data: unknown;\n}\n\nexport interface FirestoreDocs {\n /** Every document under `collectionPath`, ordered by document id. */\n list: (collectionPath: string) => Promise<FirestoreDoc[]>;\n /** One document's fields, or null when it doesn't exist. */\n get: (collectionPath: string, docId: string) => Promise<unknown | null>;\n /** Create or replace. */\n set: (collectionPath: string, docId: string, data: Record<string, unknown>) => Promise<void>;\n /** Create only. Returns false when the id already exists — atomic, so two\n * concurrent creates can't both observe \"missing\". */\n create: (collectionPath: string, docId: string, data: Record<string, unknown>) => Promise<boolean>;\n /** Delete. Returns false when the id didn't exist, so a caller can tell a\n * real delete from a typo'd id. */\n delete: (collectionPath: string, docId: string) => Promise<boolean>;\n}\n\n/** The real implementation over the modular SDK.\n *\n * THE RECORD IS THE DOCUMENT. Its fields are written at the top level, not\n * nested under a `data` key. This is not a matter of taste: the deployed\n * security rules read `request.resource.data.<field>` and\n * `resource.data[submit.emailField]` — a wrapper would put every field one\n * level down, so the required-field checks, the status state machine and the\n * \"your own row\" predicate would all read absent values and fail closed. A\n * shared record's shape is part of the authorization contract.\n *\n * `orderBy(\"__name__\")` orders by DOCUMENT ID. Ordering by a record field\n * would silently EXCLUDE documents missing that field (the trap\n * `remote-host/server/hostRunner.ts:158-169` documents), turning a read into a\n * partial one; the document id is always present and gives the stable order\n * the store contract requires. */\nexport function createFirestoreDocs(database: Firestore): FirestoreDocs {\n return {\n list: async (collectionPath) => {\n const snapshot = await getDocs(firestoreQuery(firestoreCollection(database, collectionPath), orderBy(\"__name__\")));\n return snapshot.docs.map((entry) => ({ id: entry.id, data: entry.data() }));\n },\n get: async (collectionPath, docId) => {\n const snapshot = await getDoc(doc(database, collectionPath, docId));\n return snapshot.exists() ? snapshot.data() : null;\n },\n set: async (collectionPath, docId, data) => {\n await setDoc(doc(database, collectionPath, docId), data);\n },\n create: (collectionPath, docId, data) =>\n runTransaction(database, async (transaction) => {\n const ref = doc(database, collectionPath, docId);\n const existing = await transaction.get(ref);\n if (existing.exists()) return false;\n transaction.set(ref, data);\n return true;\n }),\n // Firestore's deleteDoc succeeds on a missing document, so an existence\n // check is what makes \"deleted\" distinguishable from \"there was nothing\".\n // It runs INSIDE the transaction (like `create`): a plain get-then-delete\n // would report `true` for a document a concurrent client had already\n // removed, i.e. claim a delete this call never performed.\n delete: (collectionPath, docId) =>\n runTransaction(database, async (transaction) => {\n const ref = doc(database, collectionPath, docId);\n const existing = await transaction.get(ref);\n if (!existing.exists()) return false;\n transaction.delete(ref);\n return true;\n }),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAqEA,SAAgB,oBAAoB,UAAoC;CACtE,OAAO;EACL,MAAM,OAAO,mBAAmB;GAE9B,QAAO,MADgB,QAAQ,MAAe,WAAoB,UAAU,cAAc,GAAG,QAAQ,UAAU,CAAC,CAAC,EAAA,CACjG,KAAK,KAAK,WAAW;IAAE,IAAI,MAAM;IAAI,MAAM,MAAM,KAAK;GAAE,EAAE;EAC5E;EACA,KAAK,OAAO,gBAAgB,UAAU;GACpC,MAAM,WAAW,MAAM,OAAO,IAAI,UAAU,gBAAgB,KAAK,CAAC;GAClE,OAAO,SAAS,OAAO,IAAI,SAAS,KAAK,IAAI;EAC/C;EACA,KAAK,OAAO,gBAAgB,OAAO,SAAS;GAC1C,MAAM,OAAO,IAAI,UAAU,gBAAgB,KAAK,GAAG,IAAI;EACzD;EACA,SAAS,gBAAgB,OAAO,SAC9B,eAAe,UAAU,OAAO,gBAAgB;GAC9C,MAAM,MAAM,IAAI,UAAU,gBAAgB,KAAK;GAE/C,KAAI,MADmB,YAAY,IAAI,GAAG,EAAA,CAC7B,OAAO,GAAG,OAAO;GAC9B,YAAY,IAAI,KAAK,IAAI;GACzB,OAAO;EACT,CAAC;EAMH,SAAS,gBAAgB,UACvB,eAAe,UAAU,OAAO,gBAAgB;GAC9C,MAAM,MAAM,IAAI,UAAU,gBAAgB,KAAK;GAE/C,IAAI,EAAC,MADkB,YAAY,IAAI,GAAG,EAAA,CAC5B,OAAO,GAAG,OAAO;GAC/B,YAAY,OAAO,GAAG;GACtB,OAAO;EACT,CAAC;CACL;AACF"}
1
+ {"version":3,"file":"firestore.js","names":[],"sources":["../../src/collection/server/firestoreDocs.ts"],"sourcesContent":["// The seam between the firestore store and the Firestore SDK.\n//\n// The modular SDK is function-based (`getDocs(query(collection(db, …)))`), so a\n// store that imported those functions directly could not be tested without a\n// real backend — a fake `db` would still be handed to the real functions.\n// Narrowing to this interface makes the backend swappable: core ships\n// `createFirestoreDocs` over the real SDK, and the tests inject an in-memory\n// fake that satisfies the same shape. That is what lets this repository's tests\n// run with no API key and no network.\n//\n// Deliberately minimal and id-keyed: no query builder, no field ordering, no\n// cursors. Everything the store needs is \"the documents of one collection path,\n// ordered by document id\" — see the store header for why field ordering is\n// avoided entirely.\n//\n// The collection path is an ARGUMENT, not something this module composes. It\n// owns the SDK calls; `firestoreStore` owns where the documents live.\n\nimport {\n collection as firestoreCollection,\n doc,\n getDoc,\n getDocs,\n orderBy,\n query as firestoreQuery,\n onSnapshot,\n runTransaction,\n setDoc,\n type Firestore,\n} from \"firebase/firestore\";\n\n/** One stored record document. `data` is the document's own fields — the\n * record itself, not a wrapper around it; see `set` below. The store\n * validates its shape, because a document written by hand could be\n * anything. */\nexport interface FirestoreDoc {\n id: string;\n data: unknown;\n}\n\nexport interface FirestoreDocs {\n /** Every document under `collectionPath`, ordered by document id. */\n list: (collectionPath: string) => Promise<FirestoreDoc[]>;\n /** One document's fields, or null when it doesn't exist. */\n get: (collectionPath: string, docId: string) => Promise<unknown | null>;\n /** Create or replace. */\n set: (collectionPath: string, docId: string, data: Record<string, unknown>) => Promise<void>;\n /** Create only. Returns false when the id already exists — atomic, so two\n * concurrent creates can't both observe \"missing\". */\n create: (collectionPath: string, docId: string, data: Record<string, unknown>) => Promise<boolean>;\n /** Delete. Returns false when the id didn't exist, so a caller can tell a\n * real delete from a typo'd id. */\n delete: (collectionPath: string, docId: string) => Promise<boolean>;\n /** Listen to `collectionPath`. Every snapshot reports the ids that changed\n * in it, and whether it is the FIRST one.\n *\n * `initial` is not a nicety. `onSnapshot` delivers the current contents\n * immediately, as one snapshot in which every existing document reads as\n * `added` — so a listener that treats snapshots uniformly announces the\n * whole collection as changed the moment it arms, on every mount. The flag\n * is passed up rather than swallowed here so the decision (and its test)\n * lives with the store's policy, next to the rest of it.\n *\n * `onError` fires at most once per subscription: a Firestore listen error\n * TERMINATES the listener and never recovers on its own. Re-subscribing is\n * the caller's job (`firestore/listen.ts` holds the policy).\n *\n * Returns the detach function synchronously — `onSnapshot` is not async. */\n watch: (collectionPath: string, onChanged: (ids: string[], meta: { initial: boolean }) => void, onError: (error: unknown) => void) => () => void;\n}\n\n/** The real implementation over the modular SDK.\n *\n * THE RECORD IS THE DOCUMENT. Its fields are written at the top level, not\n * nested under a `data` key. This is not a matter of taste: the deployed\n * security rules read `request.resource.data.<field>` and\n * `resource.data[submit.emailField]` — a wrapper would put every field one\n * level down, so the required-field checks, the status state machine and the\n * \"your own row\" predicate would all read absent values and fail closed. A\n * shared record's shape is part of the authorization contract.\n *\n * `orderBy(\"__name__\")` orders by DOCUMENT ID. Ordering by a record field\n * would silently EXCLUDE documents missing that field (the trap\n * `remote-host/server/hostRunner.ts:158-169` documents), turning a read into a\n * partial one; the document id is always present and gives the stable order\n * the store contract requires. */\nexport function createFirestoreDocs(database: Firestore): FirestoreDocs {\n return {\n list: async (collectionPath) => {\n const snapshot = await getDocs(firestoreQuery(firestoreCollection(database, collectionPath), orderBy(\"__name__\")));\n return snapshot.docs.map((entry) => ({ id: entry.id, data: entry.data() }));\n },\n get: async (collectionPath, docId) => {\n const snapshot = await getDoc(doc(database, collectionPath, docId));\n return snapshot.exists() ? snapshot.data() : null;\n },\n set: async (collectionPath, docId, data) => {\n await setDoc(doc(database, collectionPath, docId), data);\n },\n create: (collectionPath, docId, data) =>\n runTransaction(database, async (transaction) => {\n const ref = doc(database, collectionPath, docId);\n const existing = await transaction.get(ref);\n if (existing.exists()) return false;\n transaction.set(ref, data);\n return true;\n }),\n // Firestore's deleteDoc succeeds on a missing document, so an existence\n // check is what makes \"deleted\" distinguishable from \"there was nothing\".\n // It runs INSIDE the transaction (like `create`): a plain get-then-delete\n // would report `true` for a document a concurrent client had already\n // removed, i.e. claim a delete this call never performed.\n delete: (collectionPath, docId) =>\n runTransaction(database, async (transaction) => {\n const ref = doc(database, collectionPath, docId);\n const existing = await transaction.get(ref);\n if (!existing.exists()) return false;\n transaction.delete(ref);\n return true;\n }),\n // `docChanges()` rather than the whole snapshot: it names the documents\n // that moved, which is what lets the store report per-record changes\n // instead of \"something in this collection changed\". Added, modified and\n // removed are all reported the same way — the store's listener takes an\n // id, and re-reads; what KIND of change it was is not something a\n // reconcile pass needs to be told.\n //\n // `includeMetadataChanges` is deliberately left off: local writes and\n // has-pending-writes flips would otherwise wake every listener for\n // changes this process just made.\n watch: (collectionPath, onChanged, onError) => {\n let seen = false;\n return onSnapshot(\n firestoreCollection(database, collectionPath),\n (snapshot) => {\n const initial = !seen;\n seen = true;\n onChanged(\n snapshot.docChanges().map((change) => change.doc.id),\n { initial },\n );\n },\n onError,\n );\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAsFA,SAAgB,oBAAoB,UAAoC;CACtE,OAAO;EACL,MAAM,OAAO,mBAAmB;GAE9B,QAAO,MADgB,QAAQ,MAAe,WAAoB,UAAU,cAAc,GAAG,QAAQ,UAAU,CAAC,CAAC,EAAA,CACjG,KAAK,KAAK,WAAW;IAAE,IAAI,MAAM;IAAI,MAAM,MAAM,KAAK;GAAE,EAAE;EAC5E;EACA,KAAK,OAAO,gBAAgB,UAAU;GACpC,MAAM,WAAW,MAAM,OAAO,IAAI,UAAU,gBAAgB,KAAK,CAAC;GAClE,OAAO,SAAS,OAAO,IAAI,SAAS,KAAK,IAAI;EAC/C;EACA,KAAK,OAAO,gBAAgB,OAAO,SAAS;GAC1C,MAAM,OAAO,IAAI,UAAU,gBAAgB,KAAK,GAAG,IAAI;EACzD;EACA,SAAS,gBAAgB,OAAO,SAC9B,eAAe,UAAU,OAAO,gBAAgB;GAC9C,MAAM,MAAM,IAAI,UAAU,gBAAgB,KAAK;GAE/C,KAAI,MADmB,YAAY,IAAI,GAAG,EAAA,CAC7B,OAAO,GAAG,OAAO;GAC9B,YAAY,IAAI,KAAK,IAAI;GACzB,OAAO;EACT,CAAC;EAMH,SAAS,gBAAgB,UACvB,eAAe,UAAU,OAAO,gBAAgB;GAC9C,MAAM,MAAM,IAAI,UAAU,gBAAgB,KAAK;GAE/C,IAAI,EAAC,MADkB,YAAY,IAAI,GAAG,EAAA,CAC5B,OAAO,GAAG,OAAO;GAC/B,YAAY,OAAO,GAAG;GACtB,OAAO;EACT,CAAC;EAWH,QAAQ,gBAAgB,WAAW,YAAY;GAC7C,IAAI,OAAO;GACX,OAAO,WACL,WAAoB,UAAU,cAAc,IAC3C,aAAa;IACZ,MAAM,UAAU,CAAC;IACjB,OAAO;IACP,UACE,SAAS,WAAW,CAAC,CAAC,KAAK,WAAW,OAAO,IAAI,EAAE,GACnD,EAAE,QAAQ,CACZ;GACF,GACA,OACF;EACF;CACF;AACF"}
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_dist = require("../dist-CsgSfWwR.cjs");
3
- const require_calendarGrid = require("../calendarGrid-DGILaVxI.cjs");
3
+ const require_itemId = require("../itemId-Dzrr3vs5.cjs");
4
4
  const require_project = require("../project-C1ep9pvo.cjs");
5
- const require_promptSafety = require("../promptSafety-NNGViiCr.cjs");
5
+ const require_promptSafety = require("../promptSafety-CWqYq-NS.cjs");
6
6
  //#region src/collection/core/presentCollection.ts
7
7
  var TOOL_NAME = "presentCollection";
8
8
  /** Stamp a host's opaque project scope onto a card payload. The ONLY way a
@@ -174,7 +174,7 @@ function enumColorClasses(index) {
174
174
  /** Index of `value` within an enum field's declared `values`, or -1 when the
175
175
  * value is empty / unknown (→ neutral). */
176
176
  function enumValueIndex(values, value) {
177
- const text = require_calendarGrid.fieldTextOrNull(value);
177
+ const text = require_itemId.fieldTextOrNull(value);
178
178
  if (text === null || text === "") return -1;
179
179
  return values?.indexOf(text) ?? -1;
180
180
  }
@@ -192,7 +192,7 @@ function notifyValuesFor(schema, fieldKey) {
192
192
  function resolveEnumColor(schema, fieldKey, value) {
193
193
  const notifyValues = notifyValuesFor(schema, fieldKey);
194
194
  if (notifyValues) {
195
- const str = require_calendarGrid.fieldText(value);
195
+ const str = require_itemId.fieldText(value);
196
196
  const rank = notifyValues.indexOf(str);
197
197
  if (rank < 0) return ENUM_NEUTRAL;
198
198
  return rank === 0 ? ENUM_ALERT : ENUM_NUDGE;
@@ -218,7 +218,7 @@ function buildTableRowDraft(subFields, readSub) {
218
218
  bool[subKey] = raw === true;
219
219
  boolOriginallyPresent[subKey] = typeof raw === "boolean";
220
220
  boolTouched[subKey] = false;
221
- } else text[subKey] = require_calendarGrid.fieldText(raw);
221
+ } else text[subKey] = require_itemId.fieldText(raw);
222
222
  }
223
223
  return {
224
224
  text,
@@ -273,7 +273,7 @@ function rowDraftToRecord(rowDraft, subFields) {
273
273
  function draftToRecord(state, schema) {
274
274
  const record = {};
275
275
  for (const [key, field] of Object.entries(schema.fields)) {
276
- if (require_calendarGrid.COMPUTED_TYPES.has(field.type)) continue;
276
+ if (require_itemId.COMPUTED_TYPES.has(field.type)) continue;
277
277
  if (field.type === "boolean") {
278
278
  if (shouldEmitBoolean(state, key, field)) record[key] = ownFlag(state.bool, key);
279
279
  continue;
@@ -326,7 +326,7 @@ function firstMissingTableSubField(field, rows) {
326
326
  * value, and the computed/projected kinds (COMPUTED_TYPES — the shared
327
327
  * set, so a future computed type can't drift past this check) have no
328
328
  * draft input at all. */
329
- var NEVER_MISSING_TYPES = /* @__PURE__ */ new Set(["boolean", ...require_calendarGrid.COMPUTED_TYPES]);
329
+ var NEVER_MISSING_TYPES = /* @__PURE__ */ new Set(["boolean", ...require_itemId.COMPUTED_TYPES]);
330
330
  function validateOneField(key, field, draft, record) {
331
331
  if (!require_promptSafety.fieldVisible(field, record)) return null;
332
332
  if (field.type === "table" && field.of) {
@@ -387,7 +387,7 @@ function numericSortValue(raw) {
387
387
  } : EMPTY;
388
388
  }
389
389
  function stringSortValue(raw) {
390
- const str = require_calendarGrid.fieldTextOrNull(raw);
390
+ const str = require_itemId.fieldTextOrNull(raw);
391
391
  if (str === null) return EMPTY;
392
392
  return str.trim() === "" ? EMPTY : {
393
393
  empty: false,
@@ -395,7 +395,7 @@ function stringSortValue(raw) {
395
395
  };
396
396
  }
397
397
  function dateSortValue(raw) {
398
- const text = require_calendarGrid.fieldTextOrNull(raw);
398
+ const text = require_itemId.fieldTextOrNull(raw);
399
399
  if (text === null || text === "") return EMPTY;
400
400
  const epoch = Date.parse(text);
401
401
  return Number.isNaN(epoch) ? stringSortValue(raw) : {
@@ -406,7 +406,7 @@ function dateSortValue(raw) {
406
406
  /** Enum sorts by the value's index in the declared `values` list. A value
407
407
  * outside the list (or unset) is treated as empty → last. */
408
408
  function enumSortValue(values, raw) {
409
- const text = require_calendarGrid.fieldTextOrNull(raw);
409
+ const text = require_itemId.fieldTextOrNull(raw);
410
410
  if (text === null || text === "") return EMPTY;
411
411
  const idx = values ? values.indexOf(text) : -1;
412
412
  return idx < 0 ? EMPTY : {
@@ -491,7 +491,7 @@ function sortValueOf(field, key, item, deps) {
491
491
  function itemMatchesQuery(item, query) {
492
492
  if (query === "") return true;
493
493
  return Object.values(item).some((value) => {
494
- const text = require_calendarGrid.fieldTextOrNull(value);
494
+ const text = require_itemId.fieldTextOrNull(value);
495
495
  return text !== null && text.toLowerCase().includes(query);
496
496
  });
497
497
  }
@@ -508,7 +508,7 @@ function cellKey(rowId, fieldKey) {
508
508
  * empty-enum snapshot always agree. A real primary key is a scalar, so this
509
509
  * matches its plain string form. */
510
510
  function rowIdOf(primaryKey, item) {
511
- return primaryKey ? require_calendarGrid.fieldText(item[primaryKey]) : "";
511
+ return primaryKey ? require_itemId.fieldText(item[primaryKey]) : "";
512
512
  }
513
513
  /** The set of enum cells that were empty in the freshly-fetched records — the
514
514
  * only cells whose inline dropdown offers an empty option. */
@@ -517,7 +517,7 @@ function snapshotEmptyEnums(schema, records) {
517
517
  const enumKeys = Object.entries(schema.fields).filter(([, field]) => field.type === "enum").map(([fieldKey]) => fieldKey);
518
518
  if (enumKeys.length === 0) return empty;
519
519
  for (const record of records) {
520
- const recordId = require_calendarGrid.fieldText(record[schema.primaryKey]);
520
+ const recordId = require_itemId.fieldText(record[schema.primaryKey]);
521
521
  for (const fieldKey of enumKeys) if (record[fieldKey] == null || record[fieldKey] === "") empty.add(cellKey(recordId, fieldKey));
522
522
  }
523
523
  return empty;
@@ -541,7 +541,7 @@ function labelFieldFor(schema) {
541
541
  }
542
542
  /** A record's primary-key value as a string. */
543
543
  function itemIdOf(item, schema) {
544
- return require_calendarGrid.fieldText(item[schema.primaryKey]);
544
+ return require_itemId.fieldText(item[schema.primaryKey]);
545
545
  }
546
546
  /** A record's display label: the resolved `labelField` value, else the
547
547
  * primary key. Pass the result of `labelFieldFor(schema)` as `labelField`
@@ -557,18 +557,6 @@ function itemLabelOf(item, schema, labelField) {
557
557
  return itemIdOf(item, schema);
558
558
  }
559
559
  //#endregion
560
- //#region src/collection/core/shortHexId.ts
561
- /**
562
- * 8-char hex id — short, slug-safe, and editable. Produces the same id *shape*
563
- * as the server's `generateItemId()` (8 hex chars) so a UI-created collection
564
- * record looks like one the server would have generated for a form submitted
565
- * with a blank primary key. The source of randomness differs (UUID-derived here
566
- * vs `randomBytes` on the server); only the shape is intentionally shared.
567
- */
568
- function shortHexId() {
569
- return crypto.randomUUID().replace(/-/g, "").slice(0, 8);
570
- }
571
- //#endregion
572
560
  //#region src/collection/core/ontologyGraph.ts
573
561
  var isForwardKind = (kind) => kind === "ref" || kind === "embed";
574
562
  /** Fold a reverse relation (`backlinks`/`rollup` declared on `owner`)
@@ -639,25 +627,25 @@ var buildOntologyGraph = (entries) => {
639
627
  };
640
628
  };
641
629
  //#endregion
642
- exports.AGENT_INGEST_KIND = require_calendarGrid.AGENT_INGEST_KIND;
643
- exports.COMPUTED_TYPES = require_calendarGrid.COMPUTED_TYPES;
630
+ exports.AGENT_INGEST_KIND = require_itemId.AGENT_INGEST_KIND;
631
+ exports.COMPUTED_TYPES = require_itemId.COMPUTED_TYPES;
644
632
  exports.ENUM_ALERT = ENUM_ALERT;
645
633
  exports.ENUM_NEUTRAL = ENUM_NEUTRAL;
646
634
  exports.ENUM_NUDGE = ENUM_NUDGE;
647
- exports.FEED_SCHEDULES = require_calendarGrid.FEED_SCHEDULES;
648
- exports.INGEST_KINDS = require_calendarGrid.INGEST_KINDS;
649
- exports.MINUTES_PER_DAY = require_calendarGrid.MINUTES_PER_DAY;
650
- exports.SAFE_RECORD_ID_PATTERN = require_calendarGrid.SAFE_RECORD_ID_PATTERN;
651
- exports.SAFE_SLUG_PATTERN = require_calendarGrid.SAFE_SLUG_PATTERN;
635
+ exports.FEED_SCHEDULES = require_itemId.FEED_SCHEDULES;
636
+ exports.INGEST_KINDS = require_itemId.INGEST_KINDS;
637
+ exports.MINUTES_PER_DAY = require_itemId.MINUTES_PER_DAY;
638
+ exports.SAFE_RECORD_ID_PATTERN = require_itemId.SAFE_RECORD_ID_PATTERN;
639
+ exports.SAFE_SLUG_PATTERN = require_itemId.SAFE_SLUG_PATTERN;
652
640
  exports.TOOL_DEFINITION = TOOL_DEFINITION;
653
641
  exports.TOOL_NAME = TOOL_NAME;
654
642
  exports.actionVisible = require_promptSafety.actionVisible;
655
643
  exports.agentActionRunKey = require_promptSafety.agentActionRunKey;
656
- exports.assignLanes = require_calendarGrid.assignLanes;
644
+ exports.assignLanes = require_itemId.assignLanes;
657
645
  exports.backlinkRows = require_promptSafety.backlinkRows;
658
646
  exports.boolSortValue = boolSortValue;
659
- exports.bucketRecords = require_calendarGrid.bucketRecords;
660
- exports.buildMonthGrid = require_calendarGrid.buildMonthGrid;
647
+ exports.bucketRecords = require_itemId.bucketRecords;
648
+ exports.buildMonthGrid = require_itemId.buildMonthGrid;
661
649
  exports.buildOntologyGraph = buildOntologyGraph;
662
650
  exports.buildUpdatedRecord = buildUpdatedRecord;
663
651
  exports.cellKey = cellKey;
@@ -665,19 +653,19 @@ exports.chipMatches = require_promptSafety.chipMatches;
665
653
  exports.coerceInlineValue = coerceInlineValue;
666
654
  exports.coerceNumeric = require_promptSafety.coerceNumeric;
667
655
  exports.collectionCardKey = collectionCardKey;
668
- exports.collectionKeyId = require_calendarGrid.collectionKeyId;
669
- exports.collectionKeyName = require_calendarGrid.collectionKeyName;
656
+ exports.collectionKeyId = require_itemId.collectionKeyId;
657
+ exports.collectionKeyName = require_itemId.collectionKeyName;
670
658
  exports.compareSortValues = compareSortValues;
671
- exports.compareYmd = require_calendarGrid.compareYmd;
659
+ exports.compareYmd = require_itemId.compareYmd;
672
660
  exports.completionCoveredByFieldChip = require_promptSafety.completionCoveredByFieldChip;
673
- exports.dateOf = require_calendarGrid.dateOf;
661
+ exports.dateOf = require_itemId.dateOf;
674
662
  exports.dateSortValue = dateSortValue;
675
- exports.daySlice = require_calendarGrid.daySlice;
663
+ exports.daySlice = require_itemId.daySlice;
676
664
  exports.defangForPrompt = require_promptSafety.defangForPrompt;
677
665
  exports.deriveAll = require_promptSafety.deriveAll;
678
666
  exports.derivedSortValue = derivedSortValue;
679
667
  exports.draftToRecord = draftToRecord;
680
- exports.embedTargetId = require_calendarGrid.embedTargetId;
668
+ exports.embedTargetId = require_itemId.embedTargetId;
681
669
  exports.emptyRow = emptyRow;
682
670
  exports.enumColorClasses = enumColorClasses;
683
671
  exports.enumSortValue = enumSortValue;
@@ -685,40 +673,41 @@ exports.enumValueIndex = enumValueIndex;
685
673
  exports.errorMessage = require_dist.errorMessage;
686
674
  exports.evaluateDerived = require_promptSafety.evaluateDerived;
687
675
  exports.executePresentCollection = executePresentCollection;
688
- exports.fieldText = require_calendarGrid.fieldText;
689
- exports.fieldTextOrNull = require_calendarGrid.fieldTextOrNull;
676
+ exports.fieldText = require_itemId.fieldText;
677
+ exports.fieldTextOrNull = require_itemId.fieldTextOrNull;
690
678
  exports.fieldVisible = require_promptSafety.fieldVisible;
691
679
  exports.firstDateField = require_promptSafety.firstDateField;
692
680
  exports.firstMissingRequiredField = firstMissingRequiredField;
693
681
  exports.flagFieldValue = require_promptSafety.flagFieldValue;
694
- exports.generateUniqueId = require_calendarGrid.generateUniqueId;
695
- exports.isFieldDrivenEvery = require_calendarGrid.isFieldDrivenEvery;
696
- exports.isLocalCollectionKey = require_calendarGrid.isLocalCollectionKey;
697
- exports.isReadOnlySchema = require_calendarGrid.isReadOnlySchema;
698
- exports.isSafeRecordId = require_calendarGrid.isSafeRecordId;
699
- exports.isSafeSlug = require_calendarGrid.isSafeSlug;
700
- exports.isSharedCollectionKey = require_calendarGrid.isSharedCollectionKey;
682
+ exports.generateUniqueId = require_itemId.generateUniqueId;
683
+ exports.isFieldDrivenEvery = require_itemId.isFieldDrivenEvery;
684
+ exports.isLocalCollectionKey = require_itemId.isLocalCollectionKey;
685
+ exports.isReadOnlySchema = require_itemId.isReadOnlySchema;
686
+ exports.isSafeRecordId = require_itemId.isSafeRecordId;
687
+ exports.isSafeSlug = require_itemId.isSafeSlug;
688
+ exports.isSharedCollectionKey = require_itemId.isSharedCollectionKey;
701
689
  exports.isSortableField = isSortableField;
702
- exports.isValidCollectionName = require_calendarGrid.isValidCollectionName;
690
+ exports.isValidCollectionName = require_itemId.isValidCollectionName;
703
691
  exports.itemIdOf = itemIdOf;
704
692
  exports.itemIsDone = require_promptSafety.itemIsDone;
705
693
  exports.itemLabelOf = itemLabelOf;
706
694
  exports.itemMatchesQuery = itemMatchesQuery;
707
695
  exports.labelFieldFor = labelFieldFor;
708
- exports.localCollectionKeyOf = require_calendarGrid.localCollectionKeyOf;
696
+ exports.localCollectionKeyOf = require_itemId.localCollectionKeyOf;
709
697
  exports.matchesWhere = require_promptSafety.matchesWhere;
710
698
  exports.mergeIntoExisting = require_project.mergeIntoExisting;
711
- exports.monthAnchorDate = require_calendarGrid.monthAnchorDate;
699
+ exports.monthAnchorDate = require_itemId.monthAnchorDate;
700
+ exports.newItemId = require_itemId.newItemId;
712
701
  exports.nextSortDirection = nextSortDirection;
713
- exports.nextUniqueItemId = require_calendarGrid.nextUniqueItemId;
702
+ exports.nextUniqueItemId = require_itemId.nextUniqueItemId;
714
703
  exports.numericSortValue = numericSortValue;
715
- exports.parseCollectionKeyId = require_calendarGrid.parseCollectionKeyId;
716
- exports.parseIsoDate = require_calendarGrid.parseIsoDate;
717
- exports.parseIsoDateTime = require_calendarGrid.parseIsoDateTime;
718
- exports.parseTimeRange = require_calendarGrid.parseTimeRange;
704
+ exports.parseCollectionKeyId = require_itemId.parseCollectionKeyId;
705
+ exports.parseIsoDate = require_itemId.parseIsoDate;
706
+ exports.parseIsoDateTime = require_itemId.parseIsoDateTime;
707
+ exports.parseTimeRange = require_itemId.parseTimeRange;
719
708
  exports.projectBacklinkRow = require_promptSafety.projectBacklinkRow;
720
709
  exports.projectRecordFields = require_project.projectRecordFields;
721
- exports.recordSpan = require_calendarGrid.recordSpan;
710
+ exports.recordSpan = require_itemId.recordSpan;
722
711
  exports.resolveEnumColor = resolveEnumColor;
723
712
  exports.resolveIcon = require_promptSafety.resolveIcon;
724
713
  exports.resolveRowRefs = require_promptSafety.resolveRowRefs;
@@ -726,17 +715,17 @@ exports.rollupValue = require_promptSafety.rollupValue;
726
715
  exports.rowFromItem = rowFromItem;
727
716
  exports.rowIdOf = rowIdOf;
728
717
  exports.sameCollectionCard = sameCollectionCard;
729
- exports.sameCollectionKey = require_calendarGrid.sameCollectionKey;
718
+ exports.sameCollectionKey = require_itemId.sameCollectionKey;
730
719
  exports.scalarSortValue = scalarSortValue;
731
720
  exports.selectDynamicRecord = require_promptSafety.selectDynamicRecord;
732
- exports.sharedCollectionKey = require_calendarGrid.sharedCollectionKey;
733
- exports.shortHexId = shortHexId;
721
+ exports.sharedCollectionKey = require_itemId.sharedCollectionKey;
722
+ exports.shortHexId = require_itemId.shortHexId;
734
723
  exports.skillCommandSeed = skillCommandSeed;
735
724
  exports.snapshotEmptyEnums = snapshotEmptyEnums;
736
725
  exports.sortItems = sortItems;
737
726
  exports.sortValueOf = sortValueOf;
738
- exports.spanCoversDay = require_calendarGrid.spanCoversDay;
739
- exports.storageKindFor = require_calendarGrid.storageKindFor;
727
+ exports.spanCoversDay = require_itemId.spanCoversDay;
728
+ exports.storageKindFor = require_itemId.storageKindFor;
740
729
  exports.stringSortValue = stringSortValue;
741
730
  exports.toPresentCollectionData = toPresentCollectionData;
742
731
  exports.toggleChecked = require_promptSafety.toggleChecked;
@@ -746,6 +735,6 @@ exports.uniqueRefTargets = require_promptSafety.uniqueRefTargets;
746
735
  exports.viaMatches = require_promptSafety.viaMatches;
747
736
  exports.whenMatches = require_promptSafety.whenMatches;
748
737
  exports.withCardScope = withCardScope;
749
- exports.ymdKey = require_calendarGrid.ymdKey;
738
+ exports.ymdKey = require_itemId.ymdKey;
750
739
 
751
740
  //# sourceMappingURL=index.cjs.map