@massu/core 2.5.6 → 2.5.7

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.
@@ -2157,6 +2157,8 @@ __export(memory_db_exports, {
2157
2157
  MEMORY_FILE_TITLE_LIKE: () => MEMORY_FILE_TITLE_LIKE,
2158
2158
  MEMORY_FILE_TITLE_PREFIX: () => MEMORY_FILE_TITLE_PREFIX,
2159
2159
  MEMORY_SCHEMA_VERSION: () => MEMORY_SCHEMA_VERSION,
2160
+ PENDING_SYNC_MAX_AGE_DAYS: () => PENDING_SYNC_MAX_AGE_DAYS,
2161
+ PENDING_SYNC_MAX_ITEMS: () => PENDING_SYNC_MAX_ITEMS,
2160
2162
  TOOL_COST_EVENTS_RETENTION_DAYS: () => TOOL_COST_EVENTS_RETENTION_DAYS,
2161
2163
  USAGE_COUNTER_ARMED_KEY: () => USAGE_COUNTER_ARMED_KEY,
2162
2164
  addConversationTurn: () => addConversationTurn,
@@ -2165,6 +2167,7 @@ __export(memory_db_exports, {
2165
2167
  addSummary: () => addSummary,
2166
2168
  addToolCallDetail: () => addToolCallDetail,
2167
2169
  addUserPrompt: () => addUserPrompt,
2170
+ allPendingSync: () => allPendingSync,
2168
2171
  appendIncidentToFailureClass: () => appendIncidentToFailureClass,
2169
2172
  armUsageCounter: () => armUsageCounter,
2170
2173
  assignImportance: () => assignImportance,
@@ -2172,6 +2175,7 @@ __export(memory_db_exports, {
2172
2175
  createSession: () => createSession,
2173
2176
  deduplicateFailedAttempt: () => deduplicateFailedAttempt,
2174
2177
  dequeuePendingSync: () => dequeuePendingSync,
2178
+ discardPendingSync: () => discardPendingSync,
2175
2179
  embedMissingObservations: () => embedMissingObservations,
2176
2180
  endSession: () => endSession,
2177
2181
  enqueueRulePromotionEvent: () => enqueueRulePromotionEvent,
@@ -3154,6 +3158,35 @@ function initMemorySchema(db) {
3154
3158
  }
3155
3159
  function enqueueSyncPayload(db, payload) {
3156
3160
  db.prepare("INSERT INTO pending_sync (payload) VALUES (?)").run(payload);
3161
+ const overflow = db.prepare(
3162
+ `SELECT id, retry_count, last_error, payload FROM pending_sync
3163
+ WHERE created_at < datetime('now', ?)
3164
+ OR id NOT IN (SELECT id FROM pending_sync ORDER BY created_at DESC, id DESC LIMIT ?)
3165
+ LIMIT 10000`
3166
+ ).all(`-${PENDING_SYNC_MAX_AGE_DAYS} days`, PENDING_SYNC_MAX_ITEMS);
3167
+ if (overflow.length > 0) {
3168
+ discardPendingSync(db, overflow, `over the queue limit (${PENDING_SYNC_MAX_ITEMS} items / ${PENDING_SYNC_MAX_AGE_DAYS} days)`);
3169
+ }
3170
+ }
3171
+ function discardPendingSync(db, rows, why) {
3172
+ if (rows.length === 0) return 0;
3173
+ const rescued = rescueLearningFromStalePayloads(db, rows);
3174
+ for (let i = 0; i < rows.length; i += 500) {
3175
+ const ids = rows.slice(i, i + 500).map((r) => r.id);
3176
+ db.prepare(`DELETE FROM pending_sync WHERE id IN (${ids.map(() => "?").join(",")})`).run(...ids);
3177
+ }
3178
+ if (rescued > 0) {
3179
+ process.stderr.write(
3180
+ `[massu] RESCUED ${rescued} learned rule(s) from ${rows.length} discarded payload(s) \u2014 they were re-queued for delivery, NOT discarded.
3181
+ `
3182
+ );
3183
+ }
3184
+ process.stderr.write(`[massu] cloud sync: discarded ${rows.length} queued upload(s): ${why}.
3185
+ `);
3186
+ return rows.length;
3187
+ }
3188
+ function allPendingSync(db) {
3189
+ return db.prepare("SELECT id, retry_count, last_error, payload FROM pending_sync").all();
3157
3190
  }
3158
3191
  function getMemoryMeta(db, key) {
3159
3192
  const row = db.prepare("SELECT value FROM memory_meta WHERE key = ?").get(key);
@@ -3356,7 +3389,9 @@ function dequeuePendingSync(db, limit = 10) {
3356
3389
  }
3357
3390
  }
3358
3391
  return db.prepare(
3359
- "SELECT id, payload, retry_count FROM pending_sync ORDER BY created_at ASC LIMIT ?"
3392
+ // Least-retried first: oldest-first retried the same 10 items until they were discarded
3393
+ // while every newer item waited at retry 0 (2026-11-09: 43,492 never attempted).
3394
+ "SELECT id, payload, retry_count FROM pending_sync ORDER BY retry_count ASC, created_at ASC LIMIT ?"
3360
3395
  ).all(limit);
3361
3396
  }
3362
3397
  function removePendingSync(db, id) {
@@ -4029,7 +4064,7 @@ function scoreFailureClasses(db, matchText, filePath, promptContext, weights) {
4029
4064
  }
4030
4065
  return bestMatch;
4031
4066
  }
4032
- var MEMORY_SCHEMA_VERSION, TOOL_COST_EVENTS_RETENTION_DAYS, MAX_DRAFT_TEXT_LEN, FUNNEL_EVENT_OUTBOX_CAP, _temporalColCache, CONSOLIDATION_LESSON_EVIDENCE, MEMORY_FILE_TITLE_PREFIX, MEMORY_FILE_TITLE_LIKE, USAGE_COUNTER_ARMED_KEY;
4067
+ var MEMORY_SCHEMA_VERSION, TOOL_COST_EVENTS_RETENTION_DAYS, PENDING_SYNC_MAX_ITEMS, PENDING_SYNC_MAX_AGE_DAYS, MAX_DRAFT_TEXT_LEN, FUNNEL_EVENT_OUTBOX_CAP, _temporalColCache, CONSOLIDATION_LESSON_EVIDENCE, MEMORY_FILE_TITLE_PREFIX, MEMORY_FILE_TITLE_LIKE, USAGE_COUNTER_ARMED_KEY;
4033
4068
  var init_memory_db = __esm({
4034
4069
  "src/memory-db.ts"() {
4035
4070
  "use strict";
@@ -4044,6 +4079,8 @@ var init_memory_db = __esm({
4044
4079
  init_memory_embed_sweep();
4045
4080
  MEMORY_SCHEMA_VERSION = 2;
4046
4081
  TOOL_COST_EVENTS_RETENTION_DAYS = 90;
4082
+ PENDING_SYNC_MAX_ITEMS = 500;
4083
+ PENDING_SYNC_MAX_AGE_DAYS = 30;
4047
4084
  MAX_DRAFT_TEXT_LEN = 16384;
4048
4085
  FUNNEL_EVENT_OUTBOX_CAP = 2e4;
4049
4086
  _temporalColCache = /* @__PURE__ */ new WeakMap();
@@ -4707,13 +4744,41 @@ async function runPreToolUseDecision(hookName, event) {
4707
4744
  process.exit(EXIT_ALLOW);
4708
4745
  }
4709
4746
 
4747
+ // src/lib/safe-write.ts
4748
+ import {
4749
+ writeFileSync as writeFileSync3,
4750
+ renameSync,
4751
+ openSync as openSync2,
4752
+ fsyncSync as fsyncSync2,
4753
+ closeSync as closeSync2,
4754
+ existsSync as existsSync10,
4755
+ realpathSync,
4756
+ unlinkSync as unlinkSync2,
4757
+ accessSync as accessSync2,
4758
+ statSync as statSync2,
4759
+ chmodSync as chmodSync3,
4760
+ constants
4761
+ } from "fs";
4762
+ function isSameRealPath(a, b) {
4763
+ try {
4764
+ return realpathSync(a) === realpathSync(b);
4765
+ } catch {
4766
+ return false;
4767
+ }
4768
+ }
4769
+
4710
4770
  // src/hooks/lib/is-direct-invocation.ts
4711
- import { pathToFileURL } from "url";
4771
+ import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
4712
4772
  function isDirectInvocation(moduleUrl) {
4713
4773
  const entry = process.argv[1];
4714
4774
  if (!entry) return false;
4715
4775
  try {
4716
- return moduleUrl === pathToFileURL(entry).href;
4776
+ if (moduleUrl === pathToFileURL(entry).href) return true;
4777
+ } catch {
4778
+ return false;
4779
+ }
4780
+ try {
4781
+ return isSameRealPath(fileURLToPath2(moduleUrl), entry);
4717
4782
  } catch {
4718
4783
  return false;
4719
4784
  }
@@ -2157,6 +2157,8 @@ __export(memory_db_exports, {
2157
2157
  MEMORY_FILE_TITLE_LIKE: () => MEMORY_FILE_TITLE_LIKE,
2158
2158
  MEMORY_FILE_TITLE_PREFIX: () => MEMORY_FILE_TITLE_PREFIX,
2159
2159
  MEMORY_SCHEMA_VERSION: () => MEMORY_SCHEMA_VERSION,
2160
+ PENDING_SYNC_MAX_AGE_DAYS: () => PENDING_SYNC_MAX_AGE_DAYS,
2161
+ PENDING_SYNC_MAX_ITEMS: () => PENDING_SYNC_MAX_ITEMS,
2160
2162
  TOOL_COST_EVENTS_RETENTION_DAYS: () => TOOL_COST_EVENTS_RETENTION_DAYS,
2161
2163
  USAGE_COUNTER_ARMED_KEY: () => USAGE_COUNTER_ARMED_KEY,
2162
2164
  addConversationTurn: () => addConversationTurn,
@@ -2165,6 +2167,7 @@ __export(memory_db_exports, {
2165
2167
  addSummary: () => addSummary,
2166
2168
  addToolCallDetail: () => addToolCallDetail,
2167
2169
  addUserPrompt: () => addUserPrompt,
2170
+ allPendingSync: () => allPendingSync,
2168
2171
  appendIncidentToFailureClass: () => appendIncidentToFailureClass,
2169
2172
  armUsageCounter: () => armUsageCounter,
2170
2173
  assignImportance: () => assignImportance,
@@ -2172,6 +2175,7 @@ __export(memory_db_exports, {
2172
2175
  createSession: () => createSession,
2173
2176
  deduplicateFailedAttempt: () => deduplicateFailedAttempt,
2174
2177
  dequeuePendingSync: () => dequeuePendingSync,
2178
+ discardPendingSync: () => discardPendingSync,
2175
2179
  embedMissingObservations: () => embedMissingObservations,
2176
2180
  endSession: () => endSession,
2177
2181
  enqueueRulePromotionEvent: () => enqueueRulePromotionEvent,
@@ -3154,6 +3158,35 @@ function initMemorySchema(db) {
3154
3158
  }
3155
3159
  function enqueueSyncPayload(db, payload) {
3156
3160
  db.prepare("INSERT INTO pending_sync (payload) VALUES (?)").run(payload);
3161
+ const overflow = db.prepare(
3162
+ `SELECT id, retry_count, last_error, payload FROM pending_sync
3163
+ WHERE created_at < datetime('now', ?)
3164
+ OR id NOT IN (SELECT id FROM pending_sync ORDER BY created_at DESC, id DESC LIMIT ?)
3165
+ LIMIT 10000`
3166
+ ).all(`-${PENDING_SYNC_MAX_AGE_DAYS} days`, PENDING_SYNC_MAX_ITEMS);
3167
+ if (overflow.length > 0) {
3168
+ discardPendingSync(db, overflow, `over the queue limit (${PENDING_SYNC_MAX_ITEMS} items / ${PENDING_SYNC_MAX_AGE_DAYS} days)`);
3169
+ }
3170
+ }
3171
+ function discardPendingSync(db, rows, why) {
3172
+ if (rows.length === 0) return 0;
3173
+ const rescued = rescueLearningFromStalePayloads(db, rows);
3174
+ for (let i = 0; i < rows.length; i += 500) {
3175
+ const ids = rows.slice(i, i + 500).map((r) => r.id);
3176
+ db.prepare(`DELETE FROM pending_sync WHERE id IN (${ids.map(() => "?").join(",")})`).run(...ids);
3177
+ }
3178
+ if (rescued > 0) {
3179
+ process.stderr.write(
3180
+ `[massu] RESCUED ${rescued} learned rule(s) from ${rows.length} discarded payload(s) \u2014 they were re-queued for delivery, NOT discarded.
3181
+ `
3182
+ );
3183
+ }
3184
+ process.stderr.write(`[massu] cloud sync: discarded ${rows.length} queued upload(s): ${why}.
3185
+ `);
3186
+ return rows.length;
3187
+ }
3188
+ function allPendingSync(db) {
3189
+ return db.prepare("SELECT id, retry_count, last_error, payload FROM pending_sync").all();
3157
3190
  }
3158
3191
  function getMemoryMeta(db, key) {
3159
3192
  const row = db.prepare("SELECT value FROM memory_meta WHERE key = ?").get(key);
@@ -3356,7 +3389,9 @@ function dequeuePendingSync(db, limit = 10) {
3356
3389
  }
3357
3390
  }
3358
3391
  return db.prepare(
3359
- "SELECT id, payload, retry_count FROM pending_sync ORDER BY created_at ASC LIMIT ?"
3392
+ // Least-retried first: oldest-first retried the same 10 items until they were discarded
3393
+ // while every newer item waited at retry 0 (2026-11-09: 43,492 never attempted).
3394
+ "SELECT id, payload, retry_count FROM pending_sync ORDER BY retry_count ASC, created_at ASC LIMIT ?"
3360
3395
  ).all(limit);
3361
3396
  }
3362
3397
  function removePendingSync(db, id) {
@@ -4029,7 +4064,7 @@ function scoreFailureClasses(db, matchText, filePath, promptContext, weights) {
4029
4064
  }
4030
4065
  return bestMatch;
4031
4066
  }
4032
- var MEMORY_SCHEMA_VERSION, TOOL_COST_EVENTS_RETENTION_DAYS, MAX_DRAFT_TEXT_LEN, FUNNEL_EVENT_OUTBOX_CAP, _temporalColCache, CONSOLIDATION_LESSON_EVIDENCE, MEMORY_FILE_TITLE_PREFIX, MEMORY_FILE_TITLE_LIKE, USAGE_COUNTER_ARMED_KEY;
4067
+ var MEMORY_SCHEMA_VERSION, TOOL_COST_EVENTS_RETENTION_DAYS, PENDING_SYNC_MAX_ITEMS, PENDING_SYNC_MAX_AGE_DAYS, MAX_DRAFT_TEXT_LEN, FUNNEL_EVENT_OUTBOX_CAP, _temporalColCache, CONSOLIDATION_LESSON_EVIDENCE, MEMORY_FILE_TITLE_PREFIX, MEMORY_FILE_TITLE_LIKE, USAGE_COUNTER_ARMED_KEY;
4033
4068
  var init_memory_db = __esm({
4034
4069
  "src/memory-db.ts"() {
4035
4070
  "use strict";
@@ -4044,6 +4079,8 @@ var init_memory_db = __esm({
4044
4079
  init_memory_embed_sweep();
4045
4080
  MEMORY_SCHEMA_VERSION = 2;
4046
4081
  TOOL_COST_EVENTS_RETENTION_DAYS = 90;
4082
+ PENDING_SYNC_MAX_ITEMS = 500;
4083
+ PENDING_SYNC_MAX_AGE_DAYS = 30;
4047
4084
  MAX_DRAFT_TEXT_LEN = 16384;
4048
4085
  FUNNEL_EVENT_OUTBOX_CAP = 2e4;
4049
4086
  _temporalColCache = /* @__PURE__ */ new WeakMap();
@@ -4707,13 +4744,41 @@ async function runPreToolUseDecision(hookName, event) {
4707
4744
  process.exit(EXIT_ALLOW);
4708
4745
  }
4709
4746
 
4747
+ // src/lib/safe-write.ts
4748
+ import {
4749
+ writeFileSync as writeFileSync3,
4750
+ renameSync,
4751
+ openSync as openSync2,
4752
+ fsyncSync as fsyncSync2,
4753
+ closeSync as closeSync2,
4754
+ existsSync as existsSync10,
4755
+ realpathSync,
4756
+ unlinkSync as unlinkSync2,
4757
+ accessSync as accessSync2,
4758
+ statSync as statSync2,
4759
+ chmodSync as chmodSync3,
4760
+ constants
4761
+ } from "fs";
4762
+ function isSameRealPath(a, b) {
4763
+ try {
4764
+ return realpathSync(a) === realpathSync(b);
4765
+ } catch {
4766
+ return false;
4767
+ }
4768
+ }
4769
+
4710
4770
  // src/hooks/lib/is-direct-invocation.ts
4711
- import { pathToFileURL } from "url";
4771
+ import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
4712
4772
  function isDirectInvocation(moduleUrl) {
4713
4773
  const entry = process.argv[1];
4714
4774
  if (!entry) return false;
4715
4775
  try {
4716
- return moduleUrl === pathToFileURL(entry).href;
4776
+ if (moduleUrl === pathToFileURL(entry).href) return true;
4777
+ } catch {
4778
+ return false;
4779
+ }
4780
+ try {
4781
+ return isSameRealPath(fileURLToPath2(moduleUrl), entry);
4717
4782
  } catch {
4718
4783
  return false;
4719
4784
  }
@@ -2157,6 +2157,8 @@ __export(memory_db_exports, {
2157
2157
  MEMORY_FILE_TITLE_LIKE: () => MEMORY_FILE_TITLE_LIKE,
2158
2158
  MEMORY_FILE_TITLE_PREFIX: () => MEMORY_FILE_TITLE_PREFIX,
2159
2159
  MEMORY_SCHEMA_VERSION: () => MEMORY_SCHEMA_VERSION,
2160
+ PENDING_SYNC_MAX_AGE_DAYS: () => PENDING_SYNC_MAX_AGE_DAYS,
2161
+ PENDING_SYNC_MAX_ITEMS: () => PENDING_SYNC_MAX_ITEMS,
2160
2162
  TOOL_COST_EVENTS_RETENTION_DAYS: () => TOOL_COST_EVENTS_RETENTION_DAYS,
2161
2163
  USAGE_COUNTER_ARMED_KEY: () => USAGE_COUNTER_ARMED_KEY,
2162
2164
  addConversationTurn: () => addConversationTurn,
@@ -2165,6 +2167,7 @@ __export(memory_db_exports, {
2165
2167
  addSummary: () => addSummary,
2166
2168
  addToolCallDetail: () => addToolCallDetail,
2167
2169
  addUserPrompt: () => addUserPrompt,
2170
+ allPendingSync: () => allPendingSync,
2168
2171
  appendIncidentToFailureClass: () => appendIncidentToFailureClass,
2169
2172
  armUsageCounter: () => armUsageCounter,
2170
2173
  assignImportance: () => assignImportance,
@@ -2172,6 +2175,7 @@ __export(memory_db_exports, {
2172
2175
  createSession: () => createSession,
2173
2176
  deduplicateFailedAttempt: () => deduplicateFailedAttempt,
2174
2177
  dequeuePendingSync: () => dequeuePendingSync,
2178
+ discardPendingSync: () => discardPendingSync,
2175
2179
  embedMissingObservations: () => embedMissingObservations,
2176
2180
  endSession: () => endSession,
2177
2181
  enqueueRulePromotionEvent: () => enqueueRulePromotionEvent,
@@ -3154,6 +3158,35 @@ function initMemorySchema(db) {
3154
3158
  }
3155
3159
  function enqueueSyncPayload(db, payload) {
3156
3160
  db.prepare("INSERT INTO pending_sync (payload) VALUES (?)").run(payload);
3161
+ const overflow = db.prepare(
3162
+ `SELECT id, retry_count, last_error, payload FROM pending_sync
3163
+ WHERE created_at < datetime('now', ?)
3164
+ OR id NOT IN (SELECT id FROM pending_sync ORDER BY created_at DESC, id DESC LIMIT ?)
3165
+ LIMIT 10000`
3166
+ ).all(`-${PENDING_SYNC_MAX_AGE_DAYS} days`, PENDING_SYNC_MAX_ITEMS);
3167
+ if (overflow.length > 0) {
3168
+ discardPendingSync(db, overflow, `over the queue limit (${PENDING_SYNC_MAX_ITEMS} items / ${PENDING_SYNC_MAX_AGE_DAYS} days)`);
3169
+ }
3170
+ }
3171
+ function discardPendingSync(db, rows, why) {
3172
+ if (rows.length === 0) return 0;
3173
+ const rescued = rescueLearningFromStalePayloads(db, rows);
3174
+ for (let i = 0; i < rows.length; i += 500) {
3175
+ const ids = rows.slice(i, i + 500).map((r) => r.id);
3176
+ db.prepare(`DELETE FROM pending_sync WHERE id IN (${ids.map(() => "?").join(",")})`).run(...ids);
3177
+ }
3178
+ if (rescued > 0) {
3179
+ process.stderr.write(
3180
+ `[massu] RESCUED ${rescued} learned rule(s) from ${rows.length} discarded payload(s) \u2014 they were re-queued for delivery, NOT discarded.
3181
+ `
3182
+ );
3183
+ }
3184
+ process.stderr.write(`[massu] cloud sync: discarded ${rows.length} queued upload(s): ${why}.
3185
+ `);
3186
+ return rows.length;
3187
+ }
3188
+ function allPendingSync(db) {
3189
+ return db.prepare("SELECT id, retry_count, last_error, payload FROM pending_sync").all();
3157
3190
  }
3158
3191
  function getMemoryMeta(db, key) {
3159
3192
  const row = db.prepare("SELECT value FROM memory_meta WHERE key = ?").get(key);
@@ -3356,7 +3389,9 @@ function dequeuePendingSync(db, limit = 10) {
3356
3389
  }
3357
3390
  }
3358
3391
  return db.prepare(
3359
- "SELECT id, payload, retry_count FROM pending_sync ORDER BY created_at ASC LIMIT ?"
3392
+ // Least-retried first: oldest-first retried the same 10 items until they were discarded
3393
+ // while every newer item waited at retry 0 (2026-11-09: 43,492 never attempted).
3394
+ "SELECT id, payload, retry_count FROM pending_sync ORDER BY retry_count ASC, created_at ASC LIMIT ?"
3360
3395
  ).all(limit);
3361
3396
  }
3362
3397
  function removePendingSync(db, id) {
@@ -4029,7 +4064,7 @@ function scoreFailureClasses(db, matchText, filePath, promptContext, weights) {
4029
4064
  }
4030
4065
  return bestMatch;
4031
4066
  }
4032
- var MEMORY_SCHEMA_VERSION, TOOL_COST_EVENTS_RETENTION_DAYS, MAX_DRAFT_TEXT_LEN, FUNNEL_EVENT_OUTBOX_CAP, _temporalColCache, CONSOLIDATION_LESSON_EVIDENCE, MEMORY_FILE_TITLE_PREFIX, MEMORY_FILE_TITLE_LIKE, USAGE_COUNTER_ARMED_KEY;
4067
+ var MEMORY_SCHEMA_VERSION, TOOL_COST_EVENTS_RETENTION_DAYS, PENDING_SYNC_MAX_ITEMS, PENDING_SYNC_MAX_AGE_DAYS, MAX_DRAFT_TEXT_LEN, FUNNEL_EVENT_OUTBOX_CAP, _temporalColCache, CONSOLIDATION_LESSON_EVIDENCE, MEMORY_FILE_TITLE_PREFIX, MEMORY_FILE_TITLE_LIKE, USAGE_COUNTER_ARMED_KEY;
4033
4068
  var init_memory_db = __esm({
4034
4069
  "src/memory-db.ts"() {
4035
4070
  "use strict";
@@ -4044,6 +4079,8 @@ var init_memory_db = __esm({
4044
4079
  init_memory_embed_sweep();
4045
4080
  MEMORY_SCHEMA_VERSION = 2;
4046
4081
  TOOL_COST_EVENTS_RETENTION_DAYS = 90;
4082
+ PENDING_SYNC_MAX_ITEMS = 500;
4083
+ PENDING_SYNC_MAX_AGE_DAYS = 30;
4047
4084
  MAX_DRAFT_TEXT_LEN = 16384;
4048
4085
  FUNNEL_EVENT_OUTBOX_CAP = 2e4;
4049
4086
  _temporalColCache = /* @__PURE__ */ new WeakMap();
@@ -4156,13 +4193,41 @@ function toolResponseText(raw) {
4156
4193
  init_hook_failure_signal();
4157
4194
  init_timestamps();
4158
4195
 
4196
+ // src/lib/safe-write.ts
4197
+ import {
4198
+ writeFileSync as writeFileSync3,
4199
+ renameSync,
4200
+ openSync as openSync2,
4201
+ fsyncSync as fsyncSync2,
4202
+ closeSync as closeSync2,
4203
+ existsSync as existsSync9,
4204
+ realpathSync,
4205
+ unlinkSync as unlinkSync2,
4206
+ accessSync as accessSync2,
4207
+ statSync as statSync2,
4208
+ chmodSync as chmodSync3,
4209
+ constants
4210
+ } from "fs";
4211
+ function isSameRealPath(a, b) {
4212
+ try {
4213
+ return realpathSync(a) === realpathSync(b);
4214
+ } catch {
4215
+ return false;
4216
+ }
4217
+ }
4218
+
4159
4219
  // src/hooks/lib/is-direct-invocation.ts
4160
- import { pathToFileURL } from "url";
4220
+ import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
4161
4221
  function isDirectInvocation(moduleUrl) {
4162
4222
  const entry = process.argv[1];
4163
4223
  if (!entry) return false;
4164
4224
  try {
4165
- return moduleUrl === pathToFileURL(entry).href;
4225
+ if (moduleUrl === pathToFileURL(entry).href) return true;
4226
+ } catch {
4227
+ return false;
4228
+ }
4229
+ try {
4230
+ return isSameRealPath(fileURLToPath2(moduleUrl), entry);
4166
4231
  } catch {
4167
4232
  return false;
4168
4233
  }
@@ -2086,6 +2086,8 @@ __export(memory_db_exports, {
2086
2086
  MEMORY_FILE_TITLE_LIKE: () => MEMORY_FILE_TITLE_LIKE,
2087
2087
  MEMORY_FILE_TITLE_PREFIX: () => MEMORY_FILE_TITLE_PREFIX,
2088
2088
  MEMORY_SCHEMA_VERSION: () => MEMORY_SCHEMA_VERSION,
2089
+ PENDING_SYNC_MAX_AGE_DAYS: () => PENDING_SYNC_MAX_AGE_DAYS,
2090
+ PENDING_SYNC_MAX_ITEMS: () => PENDING_SYNC_MAX_ITEMS,
2089
2091
  TOOL_COST_EVENTS_RETENTION_DAYS: () => TOOL_COST_EVENTS_RETENTION_DAYS,
2090
2092
  USAGE_COUNTER_ARMED_KEY: () => USAGE_COUNTER_ARMED_KEY,
2091
2093
  addConversationTurn: () => addConversationTurn,
@@ -2094,6 +2096,7 @@ __export(memory_db_exports, {
2094
2096
  addSummary: () => addSummary,
2095
2097
  addToolCallDetail: () => addToolCallDetail,
2096
2098
  addUserPrompt: () => addUserPrompt,
2099
+ allPendingSync: () => allPendingSync,
2097
2100
  appendIncidentToFailureClass: () => appendIncidentToFailureClass,
2098
2101
  armUsageCounter: () => armUsageCounter,
2099
2102
  assignImportance: () => assignImportance,
@@ -2101,6 +2104,7 @@ __export(memory_db_exports, {
2101
2104
  createSession: () => createSession,
2102
2105
  deduplicateFailedAttempt: () => deduplicateFailedAttempt,
2103
2106
  dequeuePendingSync: () => dequeuePendingSync,
2107
+ discardPendingSync: () => discardPendingSync,
2104
2108
  embedMissingObservations: () => embedMissingObservations,
2105
2109
  endSession: () => endSession,
2106
2110
  enqueueRulePromotionEvent: () => enqueueRulePromotionEvent,
@@ -3083,6 +3087,35 @@ function initMemorySchema(db) {
3083
3087
  }
3084
3088
  function enqueueSyncPayload(db, payload) {
3085
3089
  db.prepare("INSERT INTO pending_sync (payload) VALUES (?)").run(payload);
3090
+ const overflow = db.prepare(
3091
+ `SELECT id, retry_count, last_error, payload FROM pending_sync
3092
+ WHERE created_at < datetime('now', ?)
3093
+ OR id NOT IN (SELECT id FROM pending_sync ORDER BY created_at DESC, id DESC LIMIT ?)
3094
+ LIMIT 10000`
3095
+ ).all(`-${PENDING_SYNC_MAX_AGE_DAYS} days`, PENDING_SYNC_MAX_ITEMS);
3096
+ if (overflow.length > 0) {
3097
+ discardPendingSync(db, overflow, `over the queue limit (${PENDING_SYNC_MAX_ITEMS} items / ${PENDING_SYNC_MAX_AGE_DAYS} days)`);
3098
+ }
3099
+ }
3100
+ function discardPendingSync(db, rows, why) {
3101
+ if (rows.length === 0) return 0;
3102
+ const rescued = rescueLearningFromStalePayloads(db, rows);
3103
+ for (let i = 0; i < rows.length; i += 500) {
3104
+ const ids = rows.slice(i, i + 500).map((r) => r.id);
3105
+ db.prepare(`DELETE FROM pending_sync WHERE id IN (${ids.map(() => "?").join(",")})`).run(...ids);
3106
+ }
3107
+ if (rescued > 0) {
3108
+ process.stderr.write(
3109
+ `[massu] RESCUED ${rescued} learned rule(s) from ${rows.length} discarded payload(s) \u2014 they were re-queued for delivery, NOT discarded.
3110
+ `
3111
+ );
3112
+ }
3113
+ process.stderr.write(`[massu] cloud sync: discarded ${rows.length} queued upload(s): ${why}.
3114
+ `);
3115
+ return rows.length;
3116
+ }
3117
+ function allPendingSync(db) {
3118
+ return db.prepare("SELECT id, retry_count, last_error, payload FROM pending_sync").all();
3086
3119
  }
3087
3120
  function getMemoryMeta(db, key) {
3088
3121
  const row = db.prepare("SELECT value FROM memory_meta WHERE key = ?").get(key);
@@ -3285,7 +3318,9 @@ function dequeuePendingSync(db, limit = 10) {
3285
3318
  }
3286
3319
  }
3287
3320
  return db.prepare(
3288
- "SELECT id, payload, retry_count FROM pending_sync ORDER BY created_at ASC LIMIT ?"
3321
+ // Least-retried first: oldest-first retried the same 10 items until they were discarded
3322
+ // while every newer item waited at retry 0 (2026-11-09: 43,492 never attempted).
3323
+ "SELECT id, payload, retry_count FROM pending_sync ORDER BY retry_count ASC, created_at ASC LIMIT ?"
3289
3324
  ).all(limit);
3290
3325
  }
3291
3326
  function removePendingSync(db, id) {
@@ -3958,7 +3993,7 @@ function scoreFailureClasses(db, matchText, filePath, promptContext, weights) {
3958
3993
  }
3959
3994
  return bestMatch;
3960
3995
  }
3961
- var MEMORY_SCHEMA_VERSION, TOOL_COST_EVENTS_RETENTION_DAYS, MAX_DRAFT_TEXT_LEN, FUNNEL_EVENT_OUTBOX_CAP, _temporalColCache, CONSOLIDATION_LESSON_EVIDENCE, MEMORY_FILE_TITLE_PREFIX, MEMORY_FILE_TITLE_LIKE, USAGE_COUNTER_ARMED_KEY;
3996
+ var MEMORY_SCHEMA_VERSION, TOOL_COST_EVENTS_RETENTION_DAYS, PENDING_SYNC_MAX_ITEMS, PENDING_SYNC_MAX_AGE_DAYS, MAX_DRAFT_TEXT_LEN, FUNNEL_EVENT_OUTBOX_CAP, _temporalColCache, CONSOLIDATION_LESSON_EVIDENCE, MEMORY_FILE_TITLE_PREFIX, MEMORY_FILE_TITLE_LIKE, USAGE_COUNTER_ARMED_KEY;
3962
3997
  var init_memory_db = __esm({
3963
3998
  "src/memory-db.ts"() {
3964
3999
  "use strict";
@@ -3973,6 +4008,8 @@ var init_memory_db = __esm({
3973
4008
  init_memory_embed_sweep();
3974
4009
  MEMORY_SCHEMA_VERSION = 2;
3975
4010
  TOOL_COST_EVENTS_RETENTION_DAYS = 90;
4011
+ PENDING_SYNC_MAX_ITEMS = 500;
4012
+ PENDING_SYNC_MAX_AGE_DAYS = 30;
3976
4013
  MAX_DRAFT_TEXT_LEN = 16384;
3977
4014
  FUNNEL_EVENT_OUTBOX_CAP = 2e4;
3978
4015
  _temporalColCache = /* @__PURE__ */ new WeakMap();
@@ -4056,7 +4093,7 @@ var init_hook_failure_signal = __esm({
4056
4093
 
4057
4094
  // src/hooks/rule-enforcement-pipeline.ts
4058
4095
  init_config();
4059
- import { existsSync as existsSync9, readFileSync as readFileSync6, readdirSync as readdirSync2 } from "fs";
4096
+ import { existsSync as existsSync10, readFileSync as readFileSync6, readdirSync as readdirSync2 } from "fs";
4060
4097
  import { basename as basename3, resolve as resolve5 } from "path";
4061
4098
 
4062
4099
  // src/hooks/lib/write-hook-message.ts
@@ -4097,13 +4134,41 @@ function writeHookContext(hookEventName, message) {
4097
4134
  // src/hooks/rule-enforcement-pipeline.ts
4098
4135
  init_hook_failure_signal();
4099
4136
 
4137
+ // src/lib/safe-write.ts
4138
+ import {
4139
+ writeFileSync as writeFileSync3,
4140
+ renameSync,
4141
+ openSync as openSync2,
4142
+ fsyncSync as fsyncSync2,
4143
+ closeSync as closeSync2,
4144
+ existsSync as existsSync9,
4145
+ realpathSync,
4146
+ unlinkSync as unlinkSync2,
4147
+ accessSync as accessSync2,
4148
+ statSync as statSync2,
4149
+ chmodSync as chmodSync3,
4150
+ constants
4151
+ } from "fs";
4152
+ function isSameRealPath(a, b) {
4153
+ try {
4154
+ return realpathSync(a) === realpathSync(b);
4155
+ } catch {
4156
+ return false;
4157
+ }
4158
+ }
4159
+
4100
4160
  // src/hooks/lib/is-direct-invocation.ts
4101
- import { pathToFileURL } from "url";
4161
+ import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
4102
4162
  function isDirectInvocation(moduleUrl) {
4103
4163
  const entry = process.argv[1];
4104
4164
  if (!entry) return false;
4105
4165
  try {
4106
- return moduleUrl === pathToFileURL(entry).href;
4166
+ if (moduleUrl === pathToFileURL(entry).href) return true;
4167
+ } catch {
4168
+ return false;
4169
+ }
4170
+ try {
4171
+ return isSameRealPath(fileURLToPath2(moduleUrl), entry);
4107
4172
  } catch {
4108
4173
  return false;
4109
4174
  }
@@ -4139,7 +4204,7 @@ async function main() {
4139
4204
  process.exit(0);
4140
4205
  return;
4141
4206
  }
4142
- if (!existsSync9(filePath)) {
4207
+ if (!existsSync10(filePath)) {
4143
4208
  process.exit(0);
4144
4209
  return;
4145
4210
  }
@@ -4154,7 +4219,7 @@ async function main() {
4154
4219
  const ruleDesc = descMatch?.[1]?.trim() ?? "";
4155
4220
  const enforcementDirAbs = resolve5(root, enforcementDir);
4156
4221
  let hasEnforcement = false;
4157
- if (existsSync9(enforcementDirAbs)) {
4222
+ if (existsSync10(enforcementDirAbs)) {
4158
4223
  const hookFiles = readdirSync2(enforcementDirAbs).filter((f) => f.endsWith(".sh") || f.endsWith(".ts") || f.endsWith(".js"));
4159
4224
  for (const hookFile of hookFiles) {
4160
4225
  try {
@@ -2157,6 +2157,8 @@ __export(memory_db_exports, {
2157
2157
  MEMORY_FILE_TITLE_LIKE: () => MEMORY_FILE_TITLE_LIKE,
2158
2158
  MEMORY_FILE_TITLE_PREFIX: () => MEMORY_FILE_TITLE_PREFIX,
2159
2159
  MEMORY_SCHEMA_VERSION: () => MEMORY_SCHEMA_VERSION,
2160
+ PENDING_SYNC_MAX_AGE_DAYS: () => PENDING_SYNC_MAX_AGE_DAYS,
2161
+ PENDING_SYNC_MAX_ITEMS: () => PENDING_SYNC_MAX_ITEMS,
2160
2162
  TOOL_COST_EVENTS_RETENTION_DAYS: () => TOOL_COST_EVENTS_RETENTION_DAYS,
2161
2163
  USAGE_COUNTER_ARMED_KEY: () => USAGE_COUNTER_ARMED_KEY,
2162
2164
  addConversationTurn: () => addConversationTurn,
@@ -2165,6 +2167,7 @@ __export(memory_db_exports, {
2165
2167
  addSummary: () => addSummary,
2166
2168
  addToolCallDetail: () => addToolCallDetail,
2167
2169
  addUserPrompt: () => addUserPrompt,
2170
+ allPendingSync: () => allPendingSync,
2168
2171
  appendIncidentToFailureClass: () => appendIncidentToFailureClass,
2169
2172
  armUsageCounter: () => armUsageCounter,
2170
2173
  assignImportance: () => assignImportance,
@@ -2172,6 +2175,7 @@ __export(memory_db_exports, {
2172
2175
  createSession: () => createSession,
2173
2176
  deduplicateFailedAttempt: () => deduplicateFailedAttempt,
2174
2177
  dequeuePendingSync: () => dequeuePendingSync,
2178
+ discardPendingSync: () => discardPendingSync,
2175
2179
  embedMissingObservations: () => embedMissingObservations,
2176
2180
  endSession: () => endSession,
2177
2181
  enqueueRulePromotionEvent: () => enqueueRulePromotionEvent,
@@ -3154,6 +3158,35 @@ function initMemorySchema(db) {
3154
3158
  }
3155
3159
  function enqueueSyncPayload(db, payload) {
3156
3160
  db.prepare("INSERT INTO pending_sync (payload) VALUES (?)").run(payload);
3161
+ const overflow = db.prepare(
3162
+ `SELECT id, retry_count, last_error, payload FROM pending_sync
3163
+ WHERE created_at < datetime('now', ?)
3164
+ OR id NOT IN (SELECT id FROM pending_sync ORDER BY created_at DESC, id DESC LIMIT ?)
3165
+ LIMIT 10000`
3166
+ ).all(`-${PENDING_SYNC_MAX_AGE_DAYS} days`, PENDING_SYNC_MAX_ITEMS);
3167
+ if (overflow.length > 0) {
3168
+ discardPendingSync(db, overflow, `over the queue limit (${PENDING_SYNC_MAX_ITEMS} items / ${PENDING_SYNC_MAX_AGE_DAYS} days)`);
3169
+ }
3170
+ }
3171
+ function discardPendingSync(db, rows, why) {
3172
+ if (rows.length === 0) return 0;
3173
+ const rescued = rescueLearningFromStalePayloads(db, rows);
3174
+ for (let i = 0; i < rows.length; i += 500) {
3175
+ const ids = rows.slice(i, i + 500).map((r) => r.id);
3176
+ db.prepare(`DELETE FROM pending_sync WHERE id IN (${ids.map(() => "?").join(",")})`).run(...ids);
3177
+ }
3178
+ if (rescued > 0) {
3179
+ process.stderr.write(
3180
+ `[massu] RESCUED ${rescued} learned rule(s) from ${rows.length} discarded payload(s) \u2014 they were re-queued for delivery, NOT discarded.
3181
+ `
3182
+ );
3183
+ }
3184
+ process.stderr.write(`[massu] cloud sync: discarded ${rows.length} queued upload(s): ${why}.
3185
+ `);
3186
+ return rows.length;
3187
+ }
3188
+ function allPendingSync(db) {
3189
+ return db.prepare("SELECT id, retry_count, last_error, payload FROM pending_sync").all();
3157
3190
  }
3158
3191
  function getMemoryMeta(db, key) {
3159
3192
  const row = db.prepare("SELECT value FROM memory_meta WHERE key = ?").get(key);
@@ -3356,7 +3389,9 @@ function dequeuePendingSync(db, limit = 10) {
3356
3389
  }
3357
3390
  }
3358
3391
  return db.prepare(
3359
- "SELECT id, payload, retry_count FROM pending_sync ORDER BY created_at ASC LIMIT ?"
3392
+ // Least-retried first: oldest-first retried the same 10 items until they were discarded
3393
+ // while every newer item waited at retry 0 (2026-11-09: 43,492 never attempted).
3394
+ "SELECT id, payload, retry_count FROM pending_sync ORDER BY retry_count ASC, created_at ASC LIMIT ?"
3360
3395
  ).all(limit);
3361
3396
  }
3362
3397
  function removePendingSync(db, id) {
@@ -4029,7 +4064,7 @@ function scoreFailureClasses(db, matchText, filePath, promptContext, weights) {
4029
4064
  }
4030
4065
  return bestMatch;
4031
4066
  }
4032
- var MEMORY_SCHEMA_VERSION, TOOL_COST_EVENTS_RETENTION_DAYS, MAX_DRAFT_TEXT_LEN, FUNNEL_EVENT_OUTBOX_CAP, _temporalColCache, CONSOLIDATION_LESSON_EVIDENCE, MEMORY_FILE_TITLE_PREFIX, MEMORY_FILE_TITLE_LIKE, USAGE_COUNTER_ARMED_KEY;
4067
+ var MEMORY_SCHEMA_VERSION, TOOL_COST_EVENTS_RETENTION_DAYS, PENDING_SYNC_MAX_ITEMS, PENDING_SYNC_MAX_AGE_DAYS, MAX_DRAFT_TEXT_LEN, FUNNEL_EVENT_OUTBOX_CAP, _temporalColCache, CONSOLIDATION_LESSON_EVIDENCE, MEMORY_FILE_TITLE_PREFIX, MEMORY_FILE_TITLE_LIKE, USAGE_COUNTER_ARMED_KEY;
4033
4068
  var init_memory_db = __esm({
4034
4069
  "src/memory-db.ts"() {
4035
4070
  "use strict";
@@ -4044,6 +4079,8 @@ var init_memory_db = __esm({
4044
4079
  init_memory_embed_sweep();
4045
4080
  MEMORY_SCHEMA_VERSION = 2;
4046
4081
  TOOL_COST_EVENTS_RETENTION_DAYS = 90;
4082
+ PENDING_SYNC_MAX_ITEMS = 500;
4083
+ PENDING_SYNC_MAX_AGE_DAYS = 30;
4047
4084
  MAX_DRAFT_TEXT_LEN = 16384;
4048
4085
  FUNNEL_EVENT_OUTBOX_CAP = 2e4;
4049
4086
  _temporalColCache = /* @__PURE__ */ new WeakMap();
@@ -4710,13 +4747,41 @@ async function runPreToolUseDecision(hookName, event) {
4710
4747
  process.exit(EXIT_ALLOW);
4711
4748
  }
4712
4749
 
4750
+ // src/lib/safe-write.ts
4751
+ import {
4752
+ writeFileSync as writeFileSync3,
4753
+ renameSync,
4754
+ openSync as openSync2,
4755
+ fsyncSync as fsyncSync2,
4756
+ closeSync as closeSync2,
4757
+ existsSync as existsSync10,
4758
+ realpathSync,
4759
+ unlinkSync as unlinkSync2,
4760
+ accessSync as accessSync2,
4761
+ statSync as statSync2,
4762
+ chmodSync as chmodSync3,
4763
+ constants
4764
+ } from "fs";
4765
+ function isSameRealPath(a, b) {
4766
+ try {
4767
+ return realpathSync(a) === realpathSync(b);
4768
+ } catch {
4769
+ return false;
4770
+ }
4771
+ }
4772
+
4713
4773
  // src/hooks/lib/is-direct-invocation.ts
4714
- import { pathToFileURL } from "url";
4774
+ import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
4715
4775
  function isDirectInvocation(moduleUrl) {
4716
4776
  const entry = process.argv[1];
4717
4777
  if (!entry) return false;
4718
4778
  try {
4719
- return moduleUrl === pathToFileURL(entry).href;
4779
+ if (moduleUrl === pathToFileURL(entry).href) return true;
4780
+ } catch {
4781
+ return false;
4782
+ }
4783
+ try {
4784
+ return isSameRealPath(fileURLToPath2(moduleUrl), entry);
4720
4785
  } catch {
4721
4786
  return false;
4722
4787
  }