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 +8 -10
- package/package.json +1 -1
- package/templates/hooks/inject-context.js +1 -1
- package/templates/hooks/on-stop.js +1 -1
- package/templates/hooks/pre-tool-use.js +1 -1
- package/templates/hooks/session-end.js +1 -1
- package/templates/hooks/session-start.js +6 -6
- package/templates/hooks/sticky-attribution.js +2 -2
- package/templates/hooks/sticky-utils.js +2 -2
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
|
@@ -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) {
|
|
@@ -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) {
|