sticky-note-cli 2.6.13 → 2.6.14

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.
package/bin/cli.js CHANGED
@@ -854,7 +854,7 @@ function cmdStatus() {
854
854
  if (fs.existsSync(memoryPath)) {
855
855
  try {
856
856
  const memory = JSON.parse(fs.readFileSync(memoryPath, "utf-8"));
857
- const threads = memory.threads || [];
857
+ const threads = (memory.threads || []).filter(Boolean);
858
858
  const schemaVersion = memory.version || "2";
859
859
 
860
860
  const openThreads = threads.filter((t) => t.status === "open").length;
@@ -999,7 +999,7 @@ function cmdThreads() {
999
999
  }
1000
1000
 
1001
1001
  const memory = readJsonSafe(memoryPath, { threads: [] });
1002
- const threads = memory.threads || [];
1002
+ const threads = (memory.threads || []).filter(Boolean);
1003
1003
 
1004
1004
  // Filter: show open, stuck, closed (not expired)
1005
1005
  const live = threads.filter((t) => ["open", "stuck", "closed", "stale"].includes(t.status));
@@ -1057,7 +1057,7 @@ function cmdResume() {
1057
1057
  // resume --list: show resumable threads
1058
1058
  if (args.includes("--list") || args.length === 0) {
1059
1059
  const memory = readJsonSafe(memoryPath, { threads: [] });
1060
- const threads = memory.threads || [];
1060
+ const threads = (memory.threads || []).filter(Boolean);
1061
1061
  const resumable = threads.filter((t) =>
1062
1062
  ["closed", "stuck", "open", "stale"].includes(t.status)
1063
1063
  );
@@ -1098,9 +1098,7 @@ function cmdResume() {
1098
1098
  // resume <thread-id>: set the resume signal
1099
1099
  const threadId = args[0];
1100
1100
  const memory = readJsonSafe(memoryPath, { threads: [] });
1101
- const threads = memory.threads || [];
1102
-
1103
- // Support partial ID matching (first 8 chars)
1101
+ const threads = (memory.threads || []).filter(Boolean);
1104
1102
  const match = threads.find((t) =>
1105
1103
  t.id === threadId || t.id.startsWith(threadId)
1106
1104
  );
@@ -1196,7 +1194,7 @@ function cmdReset() {
1196
1194
  const force = args.includes("--force");
1197
1195
 
1198
1196
  const memory = readJsonSafe(memoryPath, { version: "2", threads: [] });
1199
- const threadCount = (memory.threads || []).length;
1197
+ const threadCount = (memory.threads || []).filter(Boolean).length;
1200
1198
 
1201
1199
  if (threadCount === 0) {
1202
1200
  print(" Nothing to reset -- 0 threads.");
@@ -1503,7 +1501,7 @@ function cmdOverlap() {
1503
1501
  const isMe = (user) => currentUserNames.has(user || "");
1504
1502
  const memory = readJsonSafe(memoryPath, { threads: [] });
1505
1503
  const threads = (memory.threads || []).filter(
1506
- (t) => t.status === "open" || t.status === "stuck"
1504
+ (t) => t && (t.status === "open" || t.status === "stuck")
1507
1505
  );
1508
1506
 
1509
1507
  // Find overlaps
@@ -1852,7 +1850,7 @@ function cmdResumeThread() {
1852
1850
  }
1853
1851
 
1854
1852
  const memory = readJsonSafe(memoryPath, { threads: [] });
1855
- const threads = (memory.threads || []).filter((t) => t.status !== "expired");
1853
+ const threads = (memory.threads || []).filter((t) => t && t.status !== "expired");
1856
1854
 
1857
1855
  // Load attribution engine for search
1858
1856
  let attribution;
@@ -2212,7 +2210,7 @@ function cmdGc() {
2212
2210
  const memory = readJsonSafe(memoryPath, { version: "2", threads: [] });
2213
2211
  const config = readJsonSafe(configPath, { stale_days: 14 });
2214
2212
  const staleDays = config.stale_days ?? 14;
2215
- const threads = memory.threads || [];
2213
+ const threads = (memory.threads || []).filter(Boolean);
2216
2214
  const now = new Date();
2217
2215
 
2218
2216
  let tombstoned = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sticky-note-cli",
3
- "version": "2.6.13",
3
+ "version": "2.6.14",
4
4
  "description": "Human-to-human handoff for AI coding assistants. Git-backed shared memory for Claude Code and Copilot CLI.",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -408,7 +408,7 @@ function main() {
408
408
  }
409
409
 
410
410
  const memory = loadJson(getMemoryPath(), { version: "2", threads: [] });
411
- const threads = memory.threads || [];
411
+ const threads = (memory.threads || []).filter(Boolean);
412
412
 
413
413
  const live = threads.filter(
414
414
  (t) => t.status === "open" || t.status === "stuck" || t.status === "closed"
@@ -213,7 +213,7 @@ async function main() {
213
213
  const narrative = buildNarrativeFromAudit(auditData);
214
214
  const workType = classifyWorkType(auditData);
215
215
 
216
- const threads = memory.threads || [];
216
+ const threads = (memory.threads || []).filter(Boolean);
217
217
  let found = false;
218
218
 
219
219
  for (const thread of threads) {
@@ -175,7 +175,7 @@ function _checkOverlapsAndDeny() {
175
175
  let threads;
176
176
  try {
177
177
  const data = loadJson(getMemoryPath());
178
- threads = data.threads || [];
178
+ threads = (data.threads || []).filter(Boolean);
179
179
  } catch (_) {
180
180
  return null;
181
181
  }
@@ -765,7 +765,7 @@ function main() {
765
765
  filesTouched = [...new Set([...filesTouched, ...gitFiles])];
766
766
  }
767
767
 
768
- const threads = memory.threads || [];
768
+ const threads = (memory.threads || []).filter(Boolean);
769
769
  memory.threads = threads;
770
770
  let existing = null;
771
771
 
@@ -68,7 +68,7 @@ const {
68
68
  function ageStaleThreads(memory, staleDays) {
69
69
  const now = Date.now();
70
70
  let changed = false;
71
- for (const thread of memory.threads || []) {
71
+ for (const thread of (memory.threads || []).filter(Boolean)) {
72
72
  if (thread.status !== "open" && thread.status !== "stuck") continue;
73
73
  const tsField =
74
74
  thread.last_activity_at || thread.updated_at || thread.created_at || "";
@@ -95,7 +95,7 @@ function ageStaleThreads(memory, staleDays) {
95
95
  function autoCloseCopilotCliThreads(memory, autoCloseHours) {
96
96
  const now = Date.now();
97
97
  let changed = false;
98
- for (const thread of memory.threads || []) {
98
+ for (const thread of (memory.threads || []).filter(Boolean)) {
99
99
  if (thread.status !== "open") continue;
100
100
  if (thread.tool !== "copilot-cli") continue;
101
101
  const tsField =
@@ -468,7 +468,7 @@ function main() {
468
468
  const resumeThreadId = getResumeThreadId();
469
469
  let resumedThread = null;
470
470
  if (resumeThreadId) {
471
- const threads = memory.threads || [];
471
+ const threads = (memory.threads || []).filter(Boolean);
472
472
  resumedThread = findThreadById(threads, resumeThreadId);
473
473
  if (resumedThread) {
474
474
  resumedThread.status = "open";
@@ -494,13 +494,13 @@ function main() {
494
494
  }
495
495
 
496
496
  // ── Build context pieces ──────────────────────────────
497
- const threadResult = formatThreadsForInjection(memory.threads || []);
497
+ const threadResult = formatThreadsForInjection((memory.threads || []).filter(Boolean));
498
498
  const threadContext = threadResult.text;
499
499
  const configContext = formatConfigForInjection(config);
500
500
  const presenceData = loadAllPresence();
501
- const presenceContext = formatPresence(presenceData, memory.threads || []);
501
+ const presenceContext = formatPresence(presenceData, (memory.threads || []).filter(Boolean));
502
502
  const overlapContext = formatOverlapWarnings(
503
- memory.threads || [], getUser(), memory
503
+ (memory.threads || []).filter(Boolean), getUser(), memory
504
504
  );
505
505
 
506
506
  // V2.5: Mark eagerly-injected stuck threads so PreToolUse won't re-inject.
@@ -165,7 +165,7 @@ function resolveViaHeuristic(sha, file) {
165
165
  const results = [];
166
166
  const normalizedFile = file ? normalizeSep(file) : null;
167
167
 
168
- for (const thread of memory.threads || []) {
168
+ for (const thread of (memory.threads || []).filter(Boolean)) {
169
169
  if (thread.status === "expired") continue;
170
170
  if (!normalizedFile) continue;
171
171
 
@@ -230,7 +230,7 @@ function resolveThreads(attributionEntries) {
230
230
  const memory = utils.loadJson(utils.getMemoryPath(), { version: "2", threads: [] });
231
231
  const threads = [];
232
232
 
233
- for (const thread of memory.threads || []) {
233
+ for (const thread of (memory.threads || []).filter(Boolean)) {
234
234
  if (thread.status === "expired") continue;
235
235
  if (sessionIds.has(thread.session_id) || sessionIds.has(thread.id)) {
236
236
  threads.push(thread);
@@ -214,8 +214,8 @@ function saveJson(filePath, data) {
214
214
  function saveMemoryMerged(memoryPath, memory) {
215
215
  try {
216
216
  const onDisk = loadJson(memoryPath, { threads: [] });
217
- const onDiskThreads = Array.isArray(onDisk.threads) ? onDisk.threads : [];
218
- const inMemoryThreads = Array.isArray(memory.threads) ? memory.threads : [];
217
+ const onDiskThreads = Array.isArray(onDisk.threads) ? onDisk.threads.filter(Boolean) : [];
218
+ const inMemoryThreads = Array.isArray(memory.threads) ? memory.threads.filter(Boolean) : [];
219
219
  const inMemoryIds = new Set(inMemoryThreads.map((t) => t.id));
220
220
 
221
221
  for (const diskThread of onDiskThreads) {