@mulmoclaude/core 1.11.0 → 1.13.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 (70) hide show
  1. package/assets/helps/error-recovery.md +98 -0
  2. package/dist/collection/core/project.d.ts +11 -0
  3. package/dist/collection/index.cjs +3 -2
  4. package/dist/collection/index.js +3 -3
  5. package/dist/collection/registry/server/index.cjs +3 -3
  6. package/dist/collection/registry/server/index.js +3 -3
  7. package/dist/collection/server/index.cjs +2 -2
  8. package/dist/collection/server/index.js +2 -2
  9. package/dist/collection-watchers/index.cjs +3 -3
  10. package/dist/collection-watchers/index.js +3 -3
  11. package/dist/{discovery-B4CZvrXR.js → discovery-D-ZJ6a6z.js} +39 -18
  12. package/dist/discovery-D-ZJ6a6z.js.map +1 -0
  13. package/dist/{discovery-NRy3tyUA.cjs → discovery-DAoMnBYM.cjs} +39 -18
  14. package/dist/discovery-DAoMnBYM.cjs.map +1 -0
  15. package/dist/{dist-pWpC-b04.cjs → dist-21pMsI1a.cjs} +45 -1
  16. package/dist/{dist-pWpC-b04.cjs.map → dist-21pMsI1a.cjs.map} +1 -1
  17. package/dist/{dist-Cwk0e12G.js → dist-DP1FTGnO.js} +16 -2
  18. package/dist/{dist-Cwk0e12G.js.map → dist-DP1FTGnO.js.map} +1 -1
  19. package/dist/feeds/server/engine.d.ts +27 -0
  20. package/dist/feeds/server/index.cjs +72 -7
  21. package/dist/feeds/server/index.cjs.map +1 -1
  22. package/dist/feeds/server/index.d.ts +1 -1
  23. package/dist/feeds/server/index.js +71 -8
  24. package/dist/feeds/server/index.js.map +1 -1
  25. package/dist/google/calendarStateLock.d.ts +23 -0
  26. package/dist/google/calendarSyncDue.d.ts +10 -0
  27. package/dist/google/calendarSyncStore.d.ts +20 -1
  28. package/dist/google/collectionProjection.d.ts +0 -8
  29. package/dist/google/collectionSync.d.ts +104 -15
  30. package/dist/google/index.cjs +512 -89
  31. package/dist/google/index.cjs.map +1 -1
  32. package/dist/google/index.d.ts +6 -3
  33. package/dist/google/index.js +501 -91
  34. package/dist/google/index.js.map +1 -1
  35. package/dist/notifier/index.cjs +1 -1
  36. package/dist/notifier/index.js +1 -1
  37. package/dist/notifier/store.d.ts +4 -4
  38. package/dist/{notifier-tMsAXyXp.cjs → notifier-C3IhYxqh.cjs} +39 -25
  39. package/dist/notifier-C3IhYxqh.cjs.map +1 -0
  40. package/dist/{notifier-BdA5qzhe.js → notifier-CMFlw74b.js} +39 -25
  41. package/dist/notifier-CMFlw74b.js.map +1 -0
  42. package/dist/project-B9NSyr6L.js +28 -0
  43. package/dist/project-B9NSyr6L.js.map +1 -0
  44. package/dist/project-CCtT_fQr.cjs +39 -0
  45. package/dist/project-CCtT_fQr.cjs.map +1 -0
  46. package/dist/remote-host/server/index.cjs +1 -1
  47. package/dist/remote-host/server/index.js +1 -1
  48. package/dist/remote-view/index.cjs +1 -1
  49. package/dist/remote-view/index.js +1 -1
  50. package/dist/scheduler/index.cjs +1 -1
  51. package/dist/scheduler/index.js +1 -1
  52. package/dist/{server-7U-3DE2e.cjs → server-B_b0bLSW.cjs} +3 -3
  53. package/dist/{server-7U-3DE2e.cjs.map → server-B_b0bLSW.cjs.map} +1 -1
  54. package/dist/{server-DdyIvFhz.js → server-Ci_A3chZ.js} +3 -3
  55. package/dist/{server-DdyIvFhz.js.map → server-Ci_A3chZ.js.map} +1 -1
  56. package/dist/utils/index.cjs +1 -1
  57. package/dist/utils/index.js +1 -1
  58. package/dist/whisper/index.cjs +1 -1
  59. package/dist/whisper/index.js +1 -1
  60. package/dist/wiki/index.cjs +1 -1
  61. package/dist/wiki/index.js +1 -1
  62. package/package.json +1 -1
  63. package/dist/discovery-B4CZvrXR.js.map +0 -1
  64. package/dist/discovery-NRy3tyUA.cjs.map +0 -1
  65. package/dist/notifier-BdA5qzhe.js.map +0 -1
  66. package/dist/notifier-tMsAXyXp.cjs.map +0 -1
  67. package/dist/project-BWI5w_BT.cjs +0 -17
  68. package/dist/project-BWI5w_BT.cjs.map +0 -1
  69. package/dist/project-bU98ycsy.js +0 -12
  70. package/dist/project-bU98ycsy.js.map +0 -1
@@ -461,6 +461,104 @@ Repair pass reports schema violations by record id, but has no
461
461
  "malformed file" classification), and the completion/spawn watcher
462
462
  reconciles the WHOLE collection per db change (no per-record events).
463
463
 
464
+ ## A record the user edited came back with the source's value
465
+
466
+ ### Symptoms
467
+
468
+ Nothing fails — the user reports it. Any of:
469
+
470
+ - A Google Calendar collection record they edited shows Google's value
471
+ again after a sync.
472
+ - A feed record lost the column they had added beside it, or the whole
473
+ record disappeared once the item aged past `ingest.maxItems`.
474
+ - The edit is simply gone, and no conflict was ever reported.
475
+
476
+ ### Cause
477
+
478
+ Records are written WHOLE (`writeItem`), so anything that mirrors a
479
+ remote source into a collection has to lay its values OVER the stored
480
+ record rather than replace it — and has to refuse when the record holds
481
+ an edit the source has not seen. Four separate places got that wrong:
482
+
483
+ - `#2683` — a calendar collection without `autoPush` was never in the
484
+ pull's protected set at all.
485
+ - `#2684` — the protected set was a snapshot taken when the push
486
+ finished, so an edit made while the window was in flight (minutes of
487
+ it, on a full re-walk) was invisible to it.
488
+ - `#2688` — a cancellation in Google deleted the record without asking
489
+ whether it held an unsent edit.
490
+ - `#2696` — the feeds ingest replaced the record whole, and the
491
+ `maxItems` prune deleted annotated records once they aged out.
492
+
493
+ ### Fix
494
+
495
+ All four are fixed as of `@mulmoclaude/core` 1.13.0. **Check the host's
496
+ version first** — if it is older, that is the whole answer.
497
+
498
+ If it happens on 1.13.0 or later, it is a new bug, not one of these:
499
+ capture which collection, whether it declares `googleCalendar` or
500
+ `ingest`, and what the record looked like before and after. Do NOT
501
+ suggest re-editing and hoping — the point of these fixes is that the
502
+ loss is no longer silent.
503
+
504
+ ## A calendar conflict is reported on every Push and will not clear
505
+
506
+ ### Symptoms
507
+
508
+ Push reports a conflict for a record that already matches Google. It
509
+ comes back on every attempt; nothing the user does in the record clears
510
+ it.
511
+
512
+ ### Cause
513
+
514
+ The conflict check compares Google against the BASELINE in
515
+ `<workspace>/data/calendar/.push-state.json`, not against the record.
516
+ A baseline older than both sides reports a conflict forever.
517
+
518
+ Before `#2679` that happened whenever two hosts pointed at the same
519
+ workspace: both read the same snapshot and the later write dropped the
520
+ earlier one's entry. The state files are now serialised across
521
+ processes with a lock file.
522
+
523
+ **It can still happen when the workspace lives in a sync folder**
524
+ (Dropbox, iCloud, Google Drive). Exclusive file creation gives no
525
+ exclusion there — the file is replicated after the fact, so both hosts
526
+ believe they hold the lock. No mechanism in the app can fix that.
527
+
528
+ ### Fix
529
+
530
+ Move the workspace onto a real filesystem. A network mount is fine
531
+ (`O_EXCL` is atomic on NFSv3+); a consumer sync folder is not.
532
+
533
+ Nothing is lost while it persists: the push REFUSES rather than
534
+ overwrites, which is exactly what the conflict report means. If the
535
+ workspace is already on a real filesystem and a conflict still will not
536
+ clear, that is a new bug — report it with the calendar id and the
537
+ record.
538
+
539
+ ## `proceeding without the calendar state lock` in the logs
540
+
541
+ ### Symptoms
542
+
543
+ A `google` warning naming a `.lock` path, during a calendar sync.
544
+
545
+ ### Cause
546
+
547
+ The lock guards one read-modify-write of a calendar state file, and it
548
+ fails OPEN: a host that cannot take it does its work anyway, because
549
+ the lock removes a race rather than being a precondition for syncing
550
+ correctly.
551
+
552
+ A single occurrence is normal — another host held the file for the few
553
+ milliseconds the mutation takes.
554
+
555
+ ### Fix
556
+
557
+ Nothing, if it is occasional. If it is constant, either another host is
558
+ hammering the same workspace, or the lock file cannot be created at all
559
+ (a read-only mount, a missing `data/calendar` directory, a full disk) —
560
+ check those before treating it as a calendar problem.
561
+
464
562
  ## Fallback
465
563
 
466
564
  If none of the above matches the failing tool output:
@@ -1,3 +1,14 @@
1
1
  /** Keep only `fields` (+ `primaryKey`, always) on each record. No `fields`
2
2
  * ⇒ records pass through untouched. */
3
3
  export declare function projectRecordFields<T extends Record<string, unknown>>(items: T[], fields: readonly string[] | undefined, primaryKey: string): T[];
4
+ /** Retrieved values laid over whatever the record already holds.
5
+ *
6
+ * A record file is written whole (`writeItem`), so writing the retrieved item
7
+ * alone would drop every column the retrieval does not produce — a collection
8
+ * could not then carry a local note beside a mirrored item, because the next
9
+ * refresh that touched it would silently delete the note. The retrieved values
10
+ * still win on the fields they cover: those belong to the source.
11
+ *
12
+ * Shared by the Google Calendar pull (#2620) and the feeds ingest (#2696),
13
+ * which had the same bug and only one of the fixes. */
14
+ export declare function mergeIntoExisting(existing: Record<string, unknown> | null, retrieved: Record<string, unknown>): Record<string, unknown>;
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_dist = require("../dist-pWpC-b04.cjs");
2
+ const require_dist = require("../dist-21pMsI1a.cjs");
3
3
  const require_calendarGrid = require("../calendarGrid-CaS9er8i.cjs");
4
- const require_project = require("../project-BWI5w_BT.cjs");
4
+ const require_project = require("../project-CCtT_fQr.cjs");
5
5
  const require_promptSafety = require("../promptSafety-FD8cQn3e.cjs");
6
6
  //#region src/collection/core/presentCollection.ts
7
7
  var TOOL_NAME = "presentCollection";
@@ -658,6 +658,7 @@ exports.itemLabelOf = itemLabelOf;
658
658
  exports.itemMatchesQuery = itemMatchesQuery;
659
659
  exports.labelFieldFor = labelFieldFor;
660
660
  exports.matchesWhere = require_promptSafety.matchesWhere;
661
+ exports.mergeIntoExisting = require_project.mergeIntoExisting;
661
662
  exports.monthAnchorDate = require_calendarGrid.monthAnchorDate;
662
663
  exports.nextSortDirection = nextSortDirection;
663
664
  exports.nextUniqueItemId = require_calendarGrid.nextUniqueItemId;
@@ -1,6 +1,6 @@
1
- import { t as errorMessage } from "../dist-Cwk0e12G.js";
1
+ import { t as errorMessage } from "../dist-DP1FTGnO.js";
2
2
  import { A as fieldTextOrNull, C as FEED_SCHEDULES, D as isReadOnlySchema, E as isFieldDrivenEvery, O as storageKindFor, S as COMPUTED_TYPES, T as embedTargetId, _ as generateUniqueId, a as compareYmd, b as nextUniqueItemId, c as monthAnchorDate, d as parseTimeRange, f as recordSpan, g as SAFE_SLUG_PATTERN, h as SAFE_RECORD_ID_PATTERN, i as buildMonthGrid, k as fieldText, l as parseIsoDate, m as ymdKey, n as assignLanes, o as dateOf, p as spanCoversDay, r as bucketRecords, s as daySlice, t as MINUTES_PER_DAY, u as parseIsoDateTime, v as isSafeRecordId, w as INGEST_KINDS, x as AGENT_INGEST_KIND, y as isSafeSlug } from "../calendarGrid-CrGxeCOG.js";
3
- import { t as projectRecordFields } from "../project-bU98ycsy.js";
3
+ import { n as projectRecordFields, t as mergeIntoExisting } from "../project-B9NSyr6L.js";
4
4
  import { C as actionVisible, E as whenMatches, S as viaMatches, T as fieldVisible, _ as uniqueRefTargets, a as evaluateDerived, b as projectBacklinkRow, c as selectDynamicRecord, d as flagFieldValue, f as itemIsDone, g as uniqueEmbedTargets, h as uniqueBacklinkSources, l as chipMatches, m as matchesWhere, n as deriveAll, o as firstDateField, p as toggleChecked, r as resolveRowRefs, s as resolveIcon, t as defangForPrompt, u as completionCoveredByFieldChip, v as backlinkRows, w as agentActionRunKey, x as rollupValue, y as coerceNumeric } from "../promptSafety-C--op_6a.js";
5
5
  //#region src/collection/core/presentCollection.ts
6
6
  var TOOL_NAME = "presentCollection";
@@ -596,6 +596,6 @@ var buildOntologyGraph = (entries) => {
596
596
  };
597
597
  };
598
598
  //#endregion
599
- export { AGENT_INGEST_KIND, COMPUTED_TYPES, ENUM_ALERT, ENUM_NEUTRAL, ENUM_NUDGE, FEED_SCHEDULES, INGEST_KINDS, MINUTES_PER_DAY, SAFE_RECORD_ID_PATTERN, SAFE_SLUG_PATTERN, TOOL_DEFINITION, TOOL_NAME, actionVisible, agentActionRunKey, assignLanes, backlinkRows, boolSortValue, bucketRecords, buildMonthGrid, buildOntologyGraph, buildUpdatedRecord, cellKey, chipMatches, coerceInlineValue, coerceNumeric, compareSortValues, compareYmd, completionCoveredByFieldChip, dateOf, dateSortValue, daySlice, defangForPrompt, deriveAll, derivedSortValue, draftToRecord, embedTargetId, emptyRow, enumColorClasses, enumSortValue, enumValueIndex, errorMessage, evaluateDerived, executePresentCollection, fieldText, fieldTextOrNull, fieldVisible, firstDateField, firstMissingRequiredField, flagFieldValue, generateUniqueId, isFieldDrivenEvery, isReadOnlySchema, isSafeRecordId, isSafeSlug, isSortableField, itemIdOf, itemIsDone, itemLabelOf, itemMatchesQuery, labelFieldFor, matchesWhere, monthAnchorDate, nextSortDirection, nextUniqueItemId, numericSortValue, parseIsoDate, parseIsoDateTime, parseTimeRange, projectBacklinkRow, projectRecordFields, recordSpan, resolveEnumColor, resolveIcon, resolveRowRefs, rollupValue, rowFromItem, rowIdOf, scalarSortValue, selectDynamicRecord, shortHexId, skillCommandSeed, snapshotEmptyEnums, sortItems, sortValueOf, spanCoversDay, storageKindFor, stringSortValue, toggleChecked, uniqueBacklinkSources, uniqueEmbedTargets, uniqueRefTargets, viaMatches, whenMatches, ymdKey };
599
+ export { AGENT_INGEST_KIND, COMPUTED_TYPES, ENUM_ALERT, ENUM_NEUTRAL, ENUM_NUDGE, FEED_SCHEDULES, INGEST_KINDS, MINUTES_PER_DAY, SAFE_RECORD_ID_PATTERN, SAFE_SLUG_PATTERN, TOOL_DEFINITION, TOOL_NAME, actionVisible, agentActionRunKey, assignLanes, backlinkRows, boolSortValue, bucketRecords, buildMonthGrid, buildOntologyGraph, buildUpdatedRecord, cellKey, chipMatches, coerceInlineValue, coerceNumeric, compareSortValues, compareYmd, completionCoveredByFieldChip, dateOf, dateSortValue, daySlice, defangForPrompt, deriveAll, derivedSortValue, draftToRecord, embedTargetId, emptyRow, enumColorClasses, enumSortValue, enumValueIndex, errorMessage, evaluateDerived, executePresentCollection, fieldText, fieldTextOrNull, fieldVisible, firstDateField, firstMissingRequiredField, flagFieldValue, generateUniqueId, isFieldDrivenEvery, isReadOnlySchema, isSafeRecordId, isSafeSlug, isSortableField, itemIdOf, itemIsDone, itemLabelOf, itemMatchesQuery, labelFieldFor, matchesWhere, mergeIntoExisting, monthAnchorDate, nextSortDirection, nextUniqueItemId, numericSortValue, parseIsoDate, parseIsoDateTime, parseTimeRange, projectBacklinkRow, projectRecordFields, recordSpan, resolveEnumColor, resolveIcon, resolveRowRefs, rollupValue, rowFromItem, rowIdOf, scalarSortValue, selectDynamicRecord, shortHexId, skillCommandSeed, snapshotEmptyEnums, sortItems, sortValueOf, spanCoversDay, storageKindFor, stringSortValue, toggleChecked, uniqueBacklinkSources, uniqueEmbedTargets, uniqueRefTargets, viaMatches, whenMatches, ymdKey };
600
600
 
601
601
  //# sourceMappingURL=index.js.map
@@ -1,12 +1,12 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_rolldown_runtime = require("../../../rolldown-runtime-D6vf50IK.cjs");
3
- const require_dist = require("../../../dist-pWpC-b04.cjs");
3
+ const require_dist = require("../../../dist-21pMsI1a.cjs");
4
4
  const require_atomic = require("../../../atomic-C_7YpMiM.cjs");
5
5
  const require_relPath = require("../../../relPath-CgGi4-Nv.cjs");
6
6
  const require_utils_fetch = require("../../../utils/fetch.cjs");
7
- const require_discovery = require("../../../discovery-NRy3tyUA.cjs");
7
+ const require_discovery = require("../../../discovery-DAoMnBYM.cjs");
8
8
  const require_templatePath = require("../../../templatePath-27vUZowm.cjs");
9
- const require_server = require("../../../server-7U-3DE2e.cjs");
9
+ const require_server = require("../../../server-B_b0bLSW.cjs");
10
10
  const require_skill_bridge_index = require("../../../skill-bridge/index.cjs");
11
11
  const require_types = require("../../../types-CNqkLT4M.cjs");
12
12
  let node_fs = require("node:fs");
@@ -1,10 +1,10 @@
1
- import { t as errorMessage } from "../../../dist-Cwk0e12G.js";
1
+ import { t as errorMessage } from "../../../dist-DP1FTGnO.js";
2
2
  import { t as writeFileAtomic } from "../../../atomic-DPpdrJzO.js";
3
3
  import { n as toPosixRelPath } from "../../../relPath-DW8MC8VO.js";
4
4
  import { fetchWithTimeout } from "../../../utils/fetch.js";
5
- import { K as collectionsRegistriesConfigPath, U as safeRecordId, X as log, r as loadCollection, s as CollectionSchemaZ, t as acceptParsedSchema } from "../../../discovery-B4CZvrXR.js";
5
+ import { K as collectionsRegistriesConfigPath, U as safeRecordId, X as log, r as loadCollection, s as CollectionSchemaZ, t as acceptParsedSchema } from "../../../discovery-D-ZJ6a6z.js";
6
6
  import { t as isSafeActionTemplatePath } from "../../../templatePath-k_WNbL_Q.js";
7
- import { g as ONE_SECOND_MS } from "../../../server-DdyIvFhz.js";
7
+ import { g as ONE_SECOND_MS } from "../../../server-Ci_A3chZ.js";
8
8
  import { claudeSkillDir, dataSkillDir, mirrorSkillWrite } from "../../../skill-bridge/index.js";
9
9
  import { n as parseRegistryIndex, r as isRecord, t as OFFICIAL_REGISTRY_NAME } from "../../../types-BKVZrtyc.js";
10
10
  import { readFileSync } from "node:fs";
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_calendarGrid = require("../../calendarGrid-CaS9er8i.cjs");
3
- const require_discovery = require("../../discovery-NRy3tyUA.cjs");
3
+ const require_discovery = require("../../discovery-DAoMnBYM.cjs");
4
4
  const require_templatePath = require("../../templatePath-27vUZowm.cjs");
5
- const require_server = require("../../server-7U-3DE2e.cjs");
5
+ const require_server = require("../../server-B_b0bLSW.cjs");
6
6
  exports.BackendUnavailableError = require_discovery.BackendUnavailableError;
7
7
  exports.COMPUTED_TYPES = require_calendarGrid.COMPUTED_TYPES;
8
8
  exports.CollectionQueryZ = require_discovery.CollectionQueryZ;
@@ -1,5 +1,5 @@
1
1
  import { S as COMPUTED_TYPES } from "../../calendarGrid-CrGxeCOG.js";
2
- import { A as deleteItem, B as itemFilePath, C as compileCsvQuery, D as MAX_QUERY_ROWS, E as DEFAULT_QUERY_ROWS, F as resolveCreateItemId, H as resolveTemplatePath, I as writeItem, J as getWorkspaceRoot, L as SCHEMA_FILE, M as isRegularFile, N as listItems, O as BackendUnavailableError, P as readItem, Q as setCollectionChangePublisher, R as isContainedInRoot, T as CollectionQueryZ, U as safeRecordId, V as resolveDataDir, W as safeSlugName, X as log, Z as publishCollectionChange, _ as csvRowToItem, a as toDetail, b as encodeCsvRecordId, d as storeFor, h as MAX_CSV_ROWS, i as resolvePrimaryField, j as generateItemId, k as isBackendUnavailable, l as collectionWritable, m as projectItemFields, n as discoverCollections, o as toSummary, p as pageFromFullRead, q as configureCollectionHost, r as loadCollection, s as CollectionSchemaZ, t as acceptParsedSchema, u as readOnlyRefusal, v as decodeCsvRecordId, w as compileJsonlQuery, x as normalizeCsvValue, y as dedupeByRecordId, z as isContainedInWorkspace } from "../../discovery-B4CZvrXR.js";
2
+ import { A as deleteItem, B as itemFilePath, C as compileCsvQuery, D as MAX_QUERY_ROWS, E as DEFAULT_QUERY_ROWS, F as resolveCreateItemId, H as resolveTemplatePath, I as writeItem, J as getWorkspaceRoot, L as SCHEMA_FILE, M as isRegularFile, N as listItems, O as BackendUnavailableError, P as readItem, Q as setCollectionChangePublisher, R as isContainedInRoot, T as CollectionQueryZ, U as safeRecordId, V as resolveDataDir, W as safeSlugName, X as log, Z as publishCollectionChange, _ as csvRowToItem, a as toDetail, b as encodeCsvRecordId, d as storeFor, h as MAX_CSV_ROWS, i as resolvePrimaryField, j as generateItemId, k as isBackendUnavailable, l as collectionWritable, m as projectItemFields, n as discoverCollections, o as toSummary, p as pageFromFullRead, q as configureCollectionHost, r as loadCollection, s as CollectionSchemaZ, t as acceptParsedSchema, u as readOnlyRefusal, v as decodeCsvRecordId, w as compileJsonlQuery, x as normalizeCsvValue, y as dedupeByRecordId, z as isContainedInWorkspace } from "../../discovery-D-ZJ6a6z.js";
3
3
  import { i as isSafeTemplatePath, n as isSafeCustomViewI18nPath, r as isSafeCustomViewPath, t as isSafeActionTemplatePath } from "../../templatePath-k_WNbL_Q.js";
4
- import { A as buildCollectionActionSeedPrompt, C as validateRecordObject, D as enrichItems, E as runCollectionQuery, M as readCustomViewHtml, N as readCustomViewI18n, O as runQueryOverRows, P as readSkillTemplate, S as validateCollectionRecords, T as recordFieldProblem, _ as computeCollectionIcon, a as deleteCollection, b as applyMutateAction, c as computeSuccessor, d as isTriggerDue, f as maybeSpawnSuccessor, h as successorId, i as deleteCustomView, j as promptPathsFor, k as buildActionSeedPrompt, l as daysInMonth, m as resolveEvery, n as MAX_UNSELECTIVE_ITEMS, o as deleteCollectionRefusalMessage, p as parseCivil, r as makeManageCollectionTool, s as advanceTriggerDate, t as MAX_SCHEMA_ISSUES, u as formatCivil, v as buildWorkspaceOntology, w as compileRecordZ, x as firstMutateParamProblem, y as schemaRelations } from "../../server-DdyIvFhz.js";
4
+ import { A as buildCollectionActionSeedPrompt, C as validateRecordObject, D as enrichItems, E as runCollectionQuery, M as readCustomViewHtml, N as readCustomViewI18n, O as runQueryOverRows, P as readSkillTemplate, S as validateCollectionRecords, T as recordFieldProblem, _ as computeCollectionIcon, a as deleteCollection, b as applyMutateAction, c as computeSuccessor, d as isTriggerDue, f as maybeSpawnSuccessor, h as successorId, i as deleteCustomView, j as promptPathsFor, k as buildActionSeedPrompt, l as daysInMonth, m as resolveEvery, n as MAX_UNSELECTIVE_ITEMS, o as deleteCollectionRefusalMessage, p as parseCivil, r as makeManageCollectionTool, s as advanceTriggerDate, t as MAX_SCHEMA_ISSUES, u as formatCivil, v as buildWorkspaceOntology, w as compileRecordZ, x as firstMutateParamProblem, y as schemaRelations } from "../../server-Ci_A3chZ.js";
5
5
  export { BackendUnavailableError, COMPUTED_TYPES, CollectionQueryZ, CollectionSchemaZ, DEFAULT_QUERY_ROWS, MAX_CSV_ROWS, MAX_QUERY_ROWS, MAX_SCHEMA_ISSUES, MAX_UNSELECTIVE_ITEMS, SCHEMA_FILE, acceptParsedSchema, advanceTriggerDate, applyMutateAction, buildActionSeedPrompt, buildCollectionActionSeedPrompt, buildWorkspaceOntology, collectionWritable, compileCsvQuery, compileJsonlQuery, compileRecordZ, computeCollectionIcon, computeSuccessor, configureCollectionHost, csvRowToItem, daysInMonth, decodeCsvRecordId, dedupeByRecordId, deleteCollection, deleteCollectionRefusalMessage, deleteCustomView, deleteItem, discoverCollections, encodeCsvRecordId, enrichItems, firstMutateParamProblem, formatCivil, generateItemId, getWorkspaceRoot, isBackendUnavailable, isContainedInRoot, isContainedInWorkspace, isRegularFile, isSafeActionTemplatePath, isSafeCustomViewI18nPath, isSafeCustomViewPath, isSafeTemplatePath, isTriggerDue, itemFilePath, listItems, loadCollection, log, makeManageCollectionTool, maybeSpawnSuccessor, normalizeCsvValue, pageFromFullRead, parseCivil, projectItemFields, promptPathsFor, publishCollectionChange, readCustomViewHtml, readCustomViewI18n, readItem, readOnlyRefusal, readSkillTemplate, recordFieldProblem, resolveCreateItemId, resolveDataDir, resolveEvery, resolvePrimaryField, resolveTemplatePath, runCollectionQuery, runQueryOverRows, safeRecordId, safeSlugName, schemaRelations, setCollectionChangePublisher, storeFor, successorId, toDetail, toSummary, validateCollectionRecords, validateRecordObject, writeItem };
@@ -2,9 +2,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_calendarGrid = require("../calendarGrid-CaS9er8i.cjs");
3
3
  const require_promptSafety = require("../promptSafety-FD8cQn3e.cjs");
4
4
  require("../collection/index.cjs");
5
- const require_discovery = require("../discovery-NRy3tyUA.cjs");
6
- const require_server = require("../server-7U-3DE2e.cjs");
7
- const require_notifier = require("../notifier-tMsAXyXp.cjs");
5
+ const require_discovery = require("../discovery-DAoMnBYM.cjs");
6
+ const require_server = require("../server-B_b0bLSW.cjs");
7
+ const require_notifier = require("../notifier-C3IhYxqh.cjs");
8
8
  let node_fs_promises = require("node:fs/promises");
9
9
  //#region src/collection-watchers/config.ts
10
10
  var NOOP_LOG = {
@@ -1,9 +1,9 @@
1
1
  import { k as fieldText } from "../calendarGrid-CrGxeCOG.js";
2
2
  import { E as whenMatches, f as itemIsDone } from "../promptSafety-C--op_6a.js";
3
3
  import "../collection/index.js";
4
- import { B as itemFilePath, Z as publishCollectionChange, d as storeFor, n as discoverCollections, r as loadCollection } from "../discovery-B4CZvrXR.js";
5
- import { d as isTriggerDue, f as maybeSpawnSuccessor } from "../server-DdyIvFhz.js";
6
- import { d as publish, m as updateForPlugin, n as clear, s as listAll } from "../notifier-BdA5qzhe.js";
4
+ import { B as itemFilePath, Z as publishCollectionChange, d as storeFor, n as discoverCollections, r as loadCollection } from "../discovery-D-ZJ6a6z.js";
5
+ import { d as isTriggerDue, f as maybeSpawnSuccessor } from "../server-Ci_A3chZ.js";
6
+ import { d as publish, m as updateForPlugin, n as clear, s as listAll } from "../notifier-CMFlw74b.js";
7
7
  import { access } from "node:fs/promises";
8
8
  //#region src/collection-watchers/config.ts
9
9
  var NOOP_LOG = {
@@ -1,6 +1,7 @@
1
+ import { a as isErrorWithCode, o as isRecord, r as hasNumberProp } from "./dist-DP1FTGnO.js";
1
2
  import { t as writeFileAtomic } from "./atomic-DPpdrJzO.js";
2
3
  import { A as fieldTextOrNull, C as FEED_SCHEDULES, D as isReadOnlySchema, O as storageKindFor, S as COMPUTED_TYPES, g as SAFE_SLUG_PATTERN, h as SAFE_RECORD_ID_PATTERN, k as fieldText, v as isSafeRecordId, w as INGEST_KINDS, x as AGENT_INGEST_KIND, y as isSafeSlug } from "./calendarGrid-CrGxeCOG.js";
3
- import { t as projectRecordFields } from "./project-bU98ycsy.js";
4
+ import { n as projectRecordFields } from "./project-B9NSyr6L.js";
4
5
  import { n as isSafeCustomViewI18nPath, r as isSafeCustomViewPath, t as isSafeActionTemplatePath } from "./templatePath-k_WNbL_Q.js";
5
6
  import { realpathSync, watch } from "node:fs";
6
7
  import path from "node:path";
@@ -1054,14 +1055,23 @@ function pageFromFullRead(items, opts, primaryKey, truncated) {
1054
1055
  }
1055
1056
  //#endregion
1056
1057
  //#region src/collection/server/sqliteStore.ts
1058
+ /** A constructor's parameter and return types are not observable at runtime,
1059
+ * so the check stops at "DatabaseSync is constructible" — the only member of
1060
+ * the module this store ever touches. */
1061
+ function isSqliteModule(mod) {
1062
+ return isRecord(mod) && typeof mod.DatabaseSync === "function";
1063
+ }
1057
1064
  var sqliteModule = null;
1065
+ /** Drops the memo first so a later call can retry (e.g. tests stubbing the
1066
+ * runtime), then reports why the backend is unusable. */
1067
+ function sqliteUnavailable(reason) {
1068
+ sqliteModule = null;
1069
+ throw new BackendUnavailableError(`sqlite storage needs the node:sqlite module (Node.js >= 22.5) — this runtime cannot load it: ${reason}`);
1070
+ }
1058
1071
  /** Lazy-load node:sqlite once. A runtime without it (Node < 22.5) throws a
1059
1072
  * clearly-worded error the caller surfaces — never a bare MODULE_NOT_FOUND. */
1060
1073
  function loadSqlite() {
1061
- sqliteModule ??= import("node:sqlite").then((mod) => mod, (err) => {
1062
- sqliteModule = null;
1063
- throw new BackendUnavailableError(`sqlite storage needs the node:sqlite module (Node.js >= 22.5) — this runtime cannot load it: ${String(err)}`);
1064
- });
1074
+ sqliteModule ??= import("node:sqlite").then((mod) => isSqliteModule(mod) ? mod : sqliteUnavailable("the module exposes no DatabaseSync constructor"), (err) => sqliteUnavailable(String(err)));
1065
1075
  return sqliteModule;
1066
1076
  }
1067
1077
  /** The db file's on-disk state. A symlink or non-regular file is refused
@@ -1073,7 +1083,7 @@ async function dbFileState(absPath) {
1073
1083
  try {
1074
1084
  return (await lstat(absPath)).isFile() ? "file" : "refused";
1075
1085
  } catch (err) {
1076
- if (err.code === "ENOENT") return "missing";
1086
+ if (isErrorWithCode(err) && err.code === "ENOENT") return "missing";
1077
1087
  throw err;
1078
1088
  }
1079
1089
  }
@@ -1125,27 +1135,39 @@ async function withDb(absPath, workspaceRoot, mode, onUnavailable, operation) {
1125
1135
  handle.database.close();
1126
1136
  }
1127
1137
  }
1138
+ var SQLITE_CONSTRAINT_PRIMARYKEY = 1555;
1139
+ var SQLITE_CONSTRAINT_UNIQUE = 2067;
1128
1140
  /** node:sqlite throws ERR_SQLITE_ERROR with the SQLite extended result
1129
- * code on `errcode`. Our INSERT's duplicate-id failure is
1130
- * SQLITE_CONSTRAINT_PRIMARYKEY (1555); SQLITE_CONSTRAINT_UNIQUE (2067)
1131
- * covers a plain UNIQUE index. Checked structurally (message text kept
1132
- * only as a fallback for runtimes that don't expose `errcode`). */
1141
+ * code on `errcode`. Checked structurally (message text kept only as a
1142
+ * fallback for runtimes that don't expose `errcode`). */
1133
1143
  function isUniqueConstraintError(err) {
1134
- const { errcode } = err;
1135
- if (errcode !== void 0) return errcode === 1555 || errcode === 2067;
1144
+ if (hasNumberProp(err, "errcode")) return err.errcode === SQLITE_CONSTRAINT_PRIMARYKEY || err.errcode === SQLITE_CONSTRAINT_UNIQUE;
1136
1145
  return String(err).includes("UNIQUE constraint");
1137
1146
  }
1138
1147
  function parseRow(raw) {
1139
1148
  if (typeof raw !== "string") return null;
1140
1149
  try {
1141
1150
  const parsed = JSON.parse(raw);
1142
- return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
1151
+ return isRecord(parsed) ? parsed : null;
1143
1152
  } catch {
1144
1153
  return null;
1145
1154
  }
1146
1155
  }
1156
+ /** One column of a result row. node:sqlite types rows as `unknown`, so a
1157
+ * value that is not a row object yields no column at all. */
1158
+ function readColumn(row, column) {
1159
+ return isRecord(row) ? row[column] : void 0;
1160
+ }
1147
1161
  function rowsToItems(rows) {
1148
- return rows.map((row) => parseRow(row.record)).filter((item) => item !== null);
1162
+ return rows.map((row) => parseRow(readColumn(row, "record"))).filter((item) => item !== null);
1163
+ }
1164
+ /** node:sqlite hands back an integer column as `number`, or as `bigint` once
1165
+ * it leaves the safe-integer range — COUNT(*) can be either. */
1166
+ function countRecords(database) {
1167
+ const count = readColumn(database.prepare("SELECT COUNT(*) AS n FROM records").get(), "n");
1168
+ if (typeof count === "number") return count;
1169
+ if (typeof count === "bigint") return Number(count);
1170
+ throw new Error(`sqlite COUNT(*) returned no numeric row count (got ${typeof count})`);
1149
1171
  }
1150
1172
  async function sqliteList(absPath, workspaceRoot) {
1151
1173
  return withDb(absPath, workspaceRoot, "read", () => [], (database) => rowsToItems(database.prepare("SELECT record FROM records ORDER BY id").all()));
@@ -1157,7 +1179,7 @@ async function sqlitePage(absPath, primaryKey, opts, workspaceRoot) {
1157
1179
  truncated: false
1158
1180
  };
1159
1181
  return withDb(absPath, workspaceRoot, "read", () => emptyPage, (database) => {
1160
- const total = Number(database.prepare("SELECT COUNT(*) AS n FROM records").get().n);
1182
+ const total = countRecords(database);
1161
1183
  const offset = Math.max(0, opts.offset ?? 0);
1162
1184
  const limit = opts.limit === void 0 ? -1 : Math.max(0, opts.limit);
1163
1185
  return {
@@ -1171,8 +1193,7 @@ async function sqliteRead(absPath, itemId, workspaceRoot) {
1171
1193
  const safeId = safeRecordId(itemId);
1172
1194
  if (safeId === null) return null;
1173
1195
  return withDb(absPath, workspaceRoot, "read", () => null, (database) => {
1174
- const row = database.prepare("SELECT record FROM records WHERE id = ?").get(safeId);
1175
- return row === void 0 ? null : parseRow(row.record);
1196
+ return parseRow(readColumn(database.prepare("SELECT record FROM records WHERE id = ?").get(safeId), "record"));
1176
1197
  });
1177
1198
  }
1178
1199
  async function sqliteWrite(absPath, itemId, item, opts) {
@@ -2674,4 +2695,4 @@ function toDetail(collection) {
2674
2695
  //#endregion
2675
2696
  export { skillsStagingDir as $, deleteItem as A, itemFilePath as B, compileCsvQuery as C, MAX_QUERY_ROWS as D, DEFAULT_QUERY_ROWS as E, resolveCreateItemId as F, archiveDir as G, resolveTemplatePath as H, writeItem as I, getWorkspaceRoot as J, collectionsRegistriesConfigPath as K, SCHEMA_FILE as L, isRegularFile as M, listItems as N, BackendUnavailableError as O, readItem as P, setCollectionChangePublisher as Q, isContainedInRoot as R, queryCsv as S, CollectionQueryZ as T, safeRecordId as U, resolveDataDir as V, safeSlugName as W, log as X, isPresetSlug as Y, publishCollectionChange as Z, csvRowToItem as _, toDetail as a, encodeCsvRecordId as b, resolveMutateSet as c, storeFor as d, createForwardingLogger as et, checkpointSqliteDatabase as f, cacheDir as g, MAX_CSV_ROWS as h, resolvePrimaryField as i, generateItemId as j, isBackendUnavailable as k, collectionWritable as l, projectItemFields as m, discoverCollections as n, toSummary as o, pageFromFullRead as p, configureCollectionHost as q, loadCollection as r, CollectionSchemaZ as s, acceptParsedSchema as t, createHostSlot as tt, readOnlyRefusal as u, decodeCsvRecordId as v, compileJsonlQuery as w, normalizeCsvValue as x, dedupeByRecordId as y, isContainedInWorkspace as z };
2676
2697
 
2677
- //# sourceMappingURL=discovery-B4CZvrXR.js.map
2698
+ //# sourceMappingURL=discovery-D-ZJ6a6z.js.map