sticky-note-cli 2.6.1 → 2.6.2
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/package.json
CHANGED
|
@@ -120,6 +120,69 @@ function extractKeywords(prompt) {
|
|
|
120
120
|
return keywords;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
// ── Overlap detection (for Copilot CLI where session-start output is ignored) ──
|
|
124
|
+
|
|
125
|
+
function detectAndFormatOverlaps(threads, currentUser) {
|
|
126
|
+
const modifiedFiles = getRecentlyModifiedFiles();
|
|
127
|
+
if (modifiedFiles.size === 0) return "";
|
|
128
|
+
|
|
129
|
+
const activeThreads = (threads || []).filter(
|
|
130
|
+
(t) => t.status === "open" || t.status === "stuck"
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
const warnings = [];
|
|
134
|
+
for (const thread of activeThreads) {
|
|
135
|
+
const threadUser = thread.user || thread.author || "";
|
|
136
|
+
if (threadUser === currentUser) continue;
|
|
137
|
+
const threadFiles = (thread.files_touched || []).map(normalizeSep);
|
|
138
|
+
const overlap = threadFiles.filter((f) => modifiedFiles.has(f));
|
|
139
|
+
if (overlap.length === 0) continue;
|
|
140
|
+
warnings.push({ thread, overlap });
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (warnings.length === 0) return "";
|
|
144
|
+
|
|
145
|
+
warnings.sort((a, b) => {
|
|
146
|
+
if (a.thread.status !== b.thread.status) {
|
|
147
|
+
return a.thread.status === "stuck" ? -1 : 1;
|
|
148
|
+
}
|
|
149
|
+
return b.overlap.length - a.overlap.length;
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const lines = [
|
|
153
|
+
"## [STICKY-NOTE] ⚠️ OVERLAP DETECTED\n",
|
|
154
|
+
"Someone else is working on files you're touching:\n",
|
|
155
|
+
];
|
|
156
|
+
for (const { thread, overlap } of warnings) {
|
|
157
|
+
const user = thread.user || thread.author || "unknown";
|
|
158
|
+
const status = thread.status === "stuck" ? "[STUCK]" : "[OPEN]";
|
|
159
|
+
const narrative = thread.narrative || thread.last_note || "";
|
|
160
|
+
const narrativeSnip = narrative.length > 100
|
|
161
|
+
? narrative.substring(0, 100) + "…"
|
|
162
|
+
: narrative;
|
|
163
|
+
const branch = thread.branch ? ` on \`${thread.branch}\`` : "";
|
|
164
|
+
const threadId = (thread.id || "").substring(0, 8);
|
|
165
|
+
|
|
166
|
+
lines.push(`- ${status} **${user}**${branch}: ${overlap.join(", ")}`);
|
|
167
|
+
if (narrativeSnip) lines.push(` _${narrativeSnip}_`);
|
|
168
|
+
const failed = thread.failed_approaches || [];
|
|
169
|
+
if (failed.length > 0) {
|
|
170
|
+
lines.push(` ⚠️ ${failed.length} failed approach(es):`);
|
|
171
|
+
for (const fa of failed.slice(0, 2)) {
|
|
172
|
+
lines.push(` - ${(fa.description || "").substring(0, 80)}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (threadId) {
|
|
176
|
+
lines.push(` → Resume: \`npx sticky-note resume ${threadId}\``);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
lines.push(
|
|
181
|
+
"\n**Consider coordinating with these teammates before starting work.**\n"
|
|
182
|
+
);
|
|
183
|
+
return lines.join("\n");
|
|
184
|
+
}
|
|
185
|
+
|
|
123
186
|
// ── Scoring ───────────────────────────────────────────────
|
|
124
187
|
|
|
125
188
|
function scoreThread(thread, recentlyModified, currentBranch, currentUser, promptKeywords) {
|
|
@@ -442,6 +505,13 @@ function main() {
|
|
|
442
505
|
const scoringBlock = debugLines.join("\n");
|
|
443
506
|
|
|
444
507
|
if (scored.length === 0) {
|
|
508
|
+
// Even with no scored threads, check for overlaps
|
|
509
|
+
const overlapWarning = detectAndFormatOverlaps(threads, currentUser);
|
|
510
|
+
if (overlapWarning) {
|
|
511
|
+
_auditInject("no_scored_threads", 0);
|
|
512
|
+
_emit(overlapWarning);
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
445
515
|
_auditInject("no_scored_threads", 0);
|
|
446
516
|
_emit("");
|
|
447
517
|
return;
|
|
@@ -492,6 +562,12 @@ function main() {
|
|
|
492
562
|
let output = outputLines.join("\n").trim();
|
|
493
563
|
output += scoringBlock;
|
|
494
564
|
|
|
565
|
+
// Prepend overlap warning if other users' threads touch the same files
|
|
566
|
+
const overlapWarning = detectAndFormatOverlaps(threads, currentUser);
|
|
567
|
+
if (overlapWarning) {
|
|
568
|
+
output = overlapWarning + "\n" + output;
|
|
569
|
+
}
|
|
570
|
+
|
|
495
571
|
_auditInject(
|
|
496
572
|
"injected",
|
|
497
573
|
scored.length,
|