@mulmoclaude/core 5.3.0 → 5.5.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 (43) hide show
  1. package/README.md +17 -1
  2. package/assets/helps/custom-view-remote.md +19 -10
  3. package/assets/helps/custom-view.md +2 -2
  4. package/dist/collection/core/viewChatPolicy.d.ts +15 -6
  5. package/dist/collection/firestore.cjs +2 -1
  6. package/dist/collection/firestore.cjs.map +1 -1
  7. package/dist/collection/firestore.js +3 -2
  8. package/dist/collection/firestore.js.map +1 -1
  9. package/dist/collection/index.cjs +15 -6
  10. package/dist/collection/index.cjs.map +1 -1
  11. package/dist/collection/index.js +15 -6
  12. package/dist/collection/index.js.map +1 -1
  13. package/dist/collection/registry/server/index.cjs +2 -2
  14. package/dist/collection/registry/server/index.js +2 -2
  15. package/dist/collection/server/firestoreDocs.d.ts +10 -0
  16. package/dist/collection/server/index.cjs +2 -2
  17. package/dist/collection/server/index.js +2 -2
  18. package/dist/collection-watchers/index.cjs +2 -2
  19. package/dist/collection-watchers/index.js +2 -2
  20. package/dist/{discovery-CDXYswtw.cjs → discovery-B79IxEM6.cjs} +2 -3
  21. package/dist/discovery-B79IxEM6.cjs.map +1 -0
  22. package/dist/{discovery-B_64PBZU.js → discovery-DIGau7M8.js} +2 -3
  23. package/dist/discovery-DIGau7M8.js.map +1 -0
  24. package/dist/feeds/server/index.cjs +2 -2
  25. package/dist/feeds/server/index.js +2 -2
  26. package/dist/google/collectionPush.d.ts +29 -0
  27. package/dist/google/index.cjs +25 -6
  28. package/dist/google/index.cjs.map +1 -1
  29. package/dist/google/index.d.ts +1 -1
  30. package/dist/google/index.js +25 -7
  31. package/dist/google/index.js.map +1 -1
  32. package/dist/remote-view/index.cjs +7 -5
  33. package/dist/remote-view/index.cjs.map +1 -1
  34. package/dist/remote-view/index.d.ts +2 -2
  35. package/dist/remote-view/index.js +7 -5
  36. package/dist/remote-view/index.js.map +1 -1
  37. package/dist/{server-DfYwSX8b.cjs → server-BUbU9G-J.cjs} +2 -2
  38. package/dist/{server-DfYwSX8b.cjs.map → server-BUbU9G-J.cjs.map} +1 -1
  39. package/dist/{server-7POrhHKv.js → server-DZ7Cq7s_.js} +2 -2
  40. package/dist/{server-7POrhHKv.js.map → server-DZ7Cq7s_.js.map} +1 -1
  41. package/package.json +6 -6
  42. package/dist/discovery-B_64PBZU.js.map +0 -1
  43. package/dist/discovery-CDXYswtw.cjs.map +0 -1
@@ -4,8 +4,8 @@ const require_dist = require("../../dist-Gj7ygaW2.cjs");
4
4
  const require_root = require("../../root-BvwBUcol.cjs");
5
5
  const require_itemId = require("../../itemId-CGT2J7YK.cjs");
6
6
  const require_project = require("../../project-C1ep9pvo.cjs");
7
- const require_discovery = require("../../discovery-CDXYswtw.cjs");
8
- const require_server = require("../../server-DfYwSX8b.cjs");
7
+ const require_discovery = require("../../discovery-B79IxEM6.cjs");
8
+ const require_server = require("../../server-BUbU9G-J.cjs");
9
9
  const require_feeds_paths = require("../paths.cjs");
10
10
  const require_ingestTypes = require("../../ingestTypes-DsVH9BYy.cjs");
11
11
  const require_notifier = require("../../notifier-B65Mvngb.cjs");
@@ -2,8 +2,8 @@ import { a as isErrorWithCode, l as isUnknownArray, s as isRecord$1 } from "../.
2
2
  import { t as canonicalRoot } from "../../root-BcS4-Kge.js";
3
3
  import { G as INGEST_KINDS, W as FEED_SCHEDULES } from "../../itemId-4P9S_ehz.js";
4
4
  import { t as mergeIntoExisting } from "../../project-B0j_Vf_Q.js";
5
- import { W as resolveDataDir, _t as createForwardingLogger, d as storeFor, k as listItems, n as discoverCollections, q as safeSlugName, vt as createHostSlot } from "../../discovery-B_64PBZU.js";
6
- import { F as buildCollectionActionSeedPrompt, I as promptPathsFor, z as readSkillTemplate } from "../../server-7POrhHKv.js";
5
+ import { W as resolveDataDir, _t as createForwardingLogger, d as storeFor, k as listItems, n as discoverCollections, q as safeSlugName, vt as createHostSlot } from "../../discovery-DIGau7M8.js";
6
+ import { F as buildCollectionActionSeedPrompt, I as promptPathsFor, z as readSkillTemplate } from "../../server-DZ7Cq7s_.js";
7
7
  import { FEEDS_DIR, feedDir, feedStatePath, feedsRoot, ingestStateDir, ingestStatePath } from "../paths.js";
8
8
  import { n as DEFAULT_FEED_MAX_ITEMS, r as isFeedSchedule, t as AGENT_INGEST_KIND } from "../../ingestTypes-GkG7bJdB.js";
9
9
  import { d as publish, n as clear } from "../../notifier-vAp5t6wL.js";
@@ -39,6 +39,13 @@ export interface CalendarCollectionPushResult {
39
39
  deletedInGoogle: number;
40
40
  /** Records that cannot be pushed as they stand, each with the reason. */
41
41
  skipped: string[];
42
+ /** Deletions the sweep left standing in Google, each with the reason.
43
+ *
44
+ * NOT merged into `skipped`: that list means "this push did not do what you
45
+ * asked", and a refused deletion is "it was deliberately not deleted" while
46
+ * the rest of the run carried. Merging them made one refusal hide every
47
+ * successful create and update from the caller (#3272). */
48
+ keptInGoogle: string[];
42
49
  errors: string[];
43
50
  /** Records whose local edit did NOT reach Google and would be destroyed by
44
51
  * the pull that follows an automatic push (#2620).
@@ -108,9 +115,28 @@ type PushOutcome = {
108
115
  message: string;
109
116
  };
110
117
  export type PushOutcomeKind = PushOutcome["kind"];
118
+ /** One record's push, kept with the id so the pull can be told which records to
119
+ * leave alone. */
120
+ export interface PushAttempt {
121
+ eventId: string;
122
+ outcome: PushOutcome;
123
+ }
111
124
  /** Whether this outcome leaves a local edit that only exists locally, so the
112
125
  * pull must not overwrite the record and the baseline must not advance. */
113
126
  export declare const isUnpushed: (kind: PushOutcomeKind) => boolean;
127
+ /** The whole report one run produces, from what each record's push did and what
128
+ * the delete sweep did.
129
+ *
130
+ * A sweep's refusal goes to `keptInGoogle`, NEVER to `skipped`: that list means
131
+ * "this push did not do what you asked", and a refusal means "the event was
132
+ * deliberately left standing" while the rest of the run carried. Merged, one
133
+ * refusal took the caller's problem branch and hid every create and update
134
+ * (#3272).
135
+ *
136
+ * Exported because it is pure — a list of attempts and a sweep, no workspace,
137
+ * grant or clock — so the separation above is something a test drives rather
138
+ * than argues. */
139
+ export declare function pushResultFrom(slug: string, attempts: readonly PushAttempt[], deletes: DeleteSweep): CalendarCollectionPushResult;
114
140
  /** Record ids whose local value no longer matches the baseline — edits that have
115
141
  * not reached Google.
116
142
  *
@@ -133,6 +159,9 @@ export declare function unsentLocalEdits(collection: LoadedCollection, workspace
133
159
  export interface DeleteSweep {
134
160
  seen: number;
135
161
  deleted: string[];
162
+ /** Deletions left standing in Google, each with the reason. Reported apart
163
+ * from the push's own `skipped` on the result: that list means "could not be
164
+ * sent", and a refusal means "deliberately left alone" (#3272). */
136
165
  skipped: string[];
137
166
  errors: string[];
138
167
  }
@@ -7,7 +7,7 @@ const require_root = require("../root-BvwBUcol.cjs");
7
7
  const require_utils_fetch = require("../utils/fetch.cjs");
8
8
  const require_itemId = require("../itemId-CGT2J7YK.cjs");
9
9
  const require_project = require("../project-C1ep9pvo.cjs");
10
- const require_discovery = require("../discovery-CDXYswtw.cjs");
10
+ const require_discovery = require("../discovery-B79IxEM6.cjs");
11
11
  const require_paths = require("../paths-C8-jxR0s.cjs");
12
12
  let node_fs = require("node:fs");
13
13
  let node_path = require("node:path");
@@ -2034,9 +2034,22 @@ var UNPUSHED_KINDS = ["conflict", "error"];
2034
2034
  /** Whether this outcome leaves a local edit that only exists locally, so the
2035
2035
  * pull must not overwrite the record and the baseline must not advance. */
2036
2036
  var isUnpushed = (kind) => UNPUSHED_KINDS.includes(kind);
2037
- function tally(slug, attempts, deletes) {
2037
+ /** The whole report one run produces, from what each record's push did and what
2038
+ * the delete sweep did.
2039
+ *
2040
+ * A sweep's refusal goes to `keptInGoogle`, NEVER to `skipped`: that list means
2041
+ * "this push did not do what you asked", and a refusal means "the event was
2042
+ * deliberately left standing" while the rest of the run carried. Merged, one
2043
+ * refusal took the caller's problem branch and hid every create and update
2044
+ * (#3272).
2045
+ *
2046
+ * Exported because it is pure — a list of attempts and a sweep, no workspace,
2047
+ * grant or clock — so the separation above is something a test drives rather
2048
+ * than argues. */
2049
+ function pushResultFrom(slug, attempts, deletes) {
2038
2050
  const outcomes = attempts.map((attempt) => attempt.outcome);
2039
2051
  const count = (kind) => outcomes.filter((outcome) => outcome.kind === kind).length;
2052
+ const messagesOf = (kind) => outcomes.flatMap((outcome) => outcome.kind === kind ? [outcome.message] : []);
2040
2053
  return {
2041
2054
  slug,
2042
2055
  created: count("created"),
@@ -2044,8 +2057,9 @@ function tally(slug, attempts, deletes) {
2044
2057
  conflicts: count("conflict"),
2045
2058
  localDeletes: deletes.seen,
2046
2059
  deletedInGoogle: deletes.deleted.length,
2047
- skipped: [...outcomes.flatMap((outcome) => outcome.kind === "skipped" ? [outcome.message] : []), ...deletes.skipped],
2048
- errors: [...outcomes.flatMap((outcome) => outcome.kind === "error" ? [outcome.message] : []), ...deletes.errors],
2060
+ skipped: messagesOf("skipped"),
2061
+ keptInGoogle: [...deletes.skipped],
2062
+ errors: [...messagesOf("error"), ...deletes.errors],
2049
2063
  unpushedIds: attempts.filter((attempt) => isUnpushed(attempt.outcome.kind)).map((attempt) => attempt.eventId)
2050
2064
  };
2051
2065
  }
@@ -2175,7 +2189,7 @@ async function pushCollectionNow(collection, workspaceRoot, deps = liveDeps) {
2175
2189
  });
2176
2190
  await saveCalendarShadow(calendarId, pushedShadow([outcome]), workspaceRoot);
2177
2191
  }
2178
- const result = tally(slug, attempts, await sweepDeletes(locallyDeletedIds(shadow, records.map((record) => fieldText(record[schema.primaryKey]))), schema.googleCalendar?.propagateDeletes === true, {
2192
+ const result = pushResultFrom(slug, attempts, await sweepDeletes(locallyDeletedIds(shadow, records.map((record) => fieldText(record[schema.primaryKey]))), schema.googleCalendar?.propagateDeletes === true, {
2179
2193
  fetchEvent: (eventId) => (deps.fetchEvent ?? getCalendarEvent)(accessToken, {
2180
2194
  calendarId,
2181
2195
  eventId
@@ -2315,7 +2329,7 @@ function pullableEvents(events, unpushed) {
2315
2329
  * A conflict or an error means that record now diverges from Google until
2316
2330
  * someone resolves it, which must not be silent. */
2317
2331
  function reportAutoPush(slug, result) {
2318
- const { created, updated, conflicts, skipped, errors, unpushedIds } = result;
2332
+ const { created, updated, conflicts, skipped, keptInGoogle, errors, unpushedIds } = result;
2319
2333
  if (created + updated > 0) log.info("google", "auto-pushed local calendar edits", {
2320
2334
  slug,
2321
2335
  created,
@@ -2330,6 +2344,10 @@ function reportAutoPush(slug, result) {
2330
2344
  slug,
2331
2345
  skipped
2332
2346
  });
2347
+ if (keptInGoogle.length > 0) log.warn("google", "deletions the auto push left standing in Google", {
2348
+ slug,
2349
+ keptInGoogle
2350
+ });
2333
2351
  if (errors.length > 0) log.warn("google", "auto push errors", {
2334
2352
  slug,
2335
2353
  errors
@@ -3264,6 +3282,7 @@ exports.pullableEvents = pullableEvents;
3264
3282
  exports.pushAndProtect = pushAndProtect;
3265
3283
  exports.pushCalendarForCollection = pushCalendarForCollection;
3266
3284
  exports.pushCollectionNow = pushCollectionNow;
3285
+ exports.pushResultFrom = pushResultFrom;
3267
3286
  exports.pushableMap = pushableMap;
3268
3287
  exports.readDriveFile = readDriveFile;
3269
3288
  exports.releaseOrphanedCalendarToken = releaseOrphanedCalendarToken;