sticky-note-cli 2.6.16 → 2.7.1
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/README.md +119 -4
- package/bin/cli.js +589 -0
- package/bin/mcp-server.js +788 -0
- package/package.json +3 -2
- package/templates/CLAUDE.md +37 -16
- package/templates/copilot-instructions.md +69 -35
- package/templates/environment/manifest.json +37 -0
- package/templates/hooks/inject-context.js +41 -22
- package/templates/hooks/pre-tool-use.js +4 -56
- package/templates/hooks/session-end.js +3 -3
- package/templates/hooks/session-start.js +341 -25
- package/templates/hooks.json +12 -12
- package/templates/settings.json +7 -7
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sticky-note-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.1",
|
|
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": {
|
|
7
|
-
"sticky-note": "./bin/cli.js"
|
|
7
|
+
"sticky-note": "./bin/cli.js",
|
|
8
|
+
"sticky-note-mcp": "./bin/mcp-server.js"
|
|
8
9
|
},
|
|
9
10
|
"keywords": [
|
|
10
11
|
"ai",
|
package/templates/CLAUDE.md
CHANGED
|
@@ -186,33 +186,54 @@ after. A raw `git checkout` or `git switch` will fail if sticky-note
|
|
|
186
186
|
files have uncommitted changes. The alias `git sw <branch>` also works
|
|
187
187
|
if set up by `npx sticky-note init`.
|
|
188
188
|
|
|
189
|
-
### ⚠️ Overlap warnings
|
|
189
|
+
### ⚠️ Overlap warnings
|
|
190
190
|
|
|
191
|
-
Sticky-note
|
|
192
|
-
open or stuck threads.
|
|
191
|
+
Sticky-note detects when your files overlap with other teammates'
|
|
192
|
+
open or stuck threads. When the MCP server is available, use the
|
|
193
|
+
`check_overlaps` tool before editing files for the most reliable detection.
|
|
194
|
+
|
|
195
|
+
Hooks also inject overlap context through two fallback channels:
|
|
193
196
|
|
|
194
197
|
1. **Injected context** — `[STICKY-NOTE] ⚠️ OVERLAP DETECTED` appears in
|
|
195
198
|
your hook output. This fires on every user prompt.
|
|
196
199
|
2. **Tool call deny** — Your first tool call may be denied with a reason
|
|
197
|
-
containing
|
|
200
|
+
containing overlap details (Copilot CLI only).
|
|
198
201
|
|
|
199
|
-
When you
|
|
200
|
-
|
|
202
|
+
When you detect an overlap (via MCP tool or hook), surface it to the user
|
|
203
|
+
using this styled banner format:
|
|
201
204
|
|
|
202
205
|
```
|
|
203
|
-
⚠️
|
|
204
|
-
|
|
206
|
+
⚠️ ━━━ OVERLAP DETECTED ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
207
|
+
|
|
208
|
+
🔴 [user] (STUCK) · [branch]
|
|
209
|
+
Files: [file1], [file2], [file3]
|
|
210
|
+
"[narrative summary]"
|
|
211
|
+
→ Resume: npx sticky-note resume [id]
|
|
212
|
+
|
|
213
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
205
214
|
```
|
|
206
215
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
216
|
+
Use 🔴 for STUCK threads, 🟡 for OPEN threads. For multiple overlaps,
|
|
217
|
+
add additional entries between the bars.
|
|
218
|
+
|
|
219
|
+
## Sticky Note MCP Server
|
|
220
|
+
|
|
221
|
+
You have access to a `sticky-note` MCP server. Use it:
|
|
222
|
+
|
|
223
|
+
1. **At session start**: Call `get_stuck_threads()` and `get_environment_status()`
|
|
224
|
+
to check for team blockers and environment changes. Surface any warnings.
|
|
225
|
+
|
|
226
|
+
2. **Before editing files**: Call `check_overlaps(files)` with the files you
|
|
227
|
+
plan to edit. If overlaps exist, warn the user before proceeding.
|
|
228
|
+
|
|
229
|
+
3. **For prior work context**: Call `get_thread_context_for_files(files)` or
|
|
230
|
+
`search_threads(query)` to find relevant thread history.
|
|
231
|
+
|
|
232
|
+
4. **For audit history**: Call `get_audit_trail(file)` to understand who
|
|
233
|
+
changed a file and when.
|
|
213
234
|
|
|
214
|
-
|
|
215
|
-
|
|
235
|
+
These tools are the primary way sticky-note communicates with you.
|
|
236
|
+
Hook-injected context supplements but does not replace MCP tool calls.
|
|
216
237
|
|
|
217
238
|
### `[STICKY-NOTE]` tags
|
|
218
239
|
|
|
@@ -2,7 +2,34 @@
|
|
|
2
2
|
# Sticky Note — Copilot CLI Instructions
|
|
3
3
|
|
|
4
4
|
This repository uses **Sticky Note** for team handoff context.
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
## ⚠️ MANDATORY: Sticky Note MCP Tools (DO THIS FIRST)
|
|
7
|
+
|
|
8
|
+
You have a `sticky-note` MCP server connected. You MUST call these tools:
|
|
9
|
+
|
|
10
|
+
### On EVERY session — before doing any work:
|
|
11
|
+
```
|
|
12
|
+
get_stuck_threads() → surface stuck threads to user
|
|
13
|
+
get_environment_status() → check for missing MCP servers/secrets
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### Before EVERY file edit:
|
|
17
|
+
```
|
|
18
|
+
check_overlaps(files) → detect if teammates are working on same files
|
|
19
|
+
```
|
|
20
|
+
If overlaps are found, display the overlap banner BEFORE proceeding.
|
|
21
|
+
|
|
22
|
+
### When you need context:
|
|
23
|
+
```
|
|
24
|
+
get_thread_context_for_files(files) → who worked on these files, what happened
|
|
25
|
+
search_threads(query) → keyword search across all threads
|
|
26
|
+
get_session_context(id) → full thread payload by ID
|
|
27
|
+
get_audit_trail(file, user, since) → query per-user audit logs
|
|
28
|
+
get_presence() → who is currently active
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
These MCP tools are the PRIMARY way sticky-note communicates with you.
|
|
32
|
+
Do NOT skip them. Do NOT substitute with manual file reads.
|
|
6
33
|
|
|
7
34
|
## When asked about threads, sessions, or teammate activity
|
|
8
35
|
|
|
@@ -17,20 +44,18 @@ git history, your own session memory, or any other source.
|
|
|
17
44
|
- [CLOSED] `closed` — completed
|
|
18
45
|
- [EXPIRED] `expired` — tombstoned, minimal data remains
|
|
19
46
|
|
|
20
|
-
###
|
|
47
|
+
### Fallback: Manual context injection (if MCP is unavailable)
|
|
21
48
|
|
|
22
|
-
|
|
23
|
-
Follow these two rules every session:
|
|
49
|
+
If the sticky-note MCP server is not connected, fall back to self-serve:
|
|
24
50
|
|
|
25
|
-
#### 1.
|
|
51
|
+
#### 1. At session start, check for stuck/open threads
|
|
26
52
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
to the user (what's blocked, what files are involved).
|
|
53
|
+
Read `.sticky-note/sticky-note.json` and check for threads with status
|
|
54
|
+
`stuck` or `open`. If any exist, briefly summarize them to the user.
|
|
30
55
|
|
|
31
|
-
#### 2.
|
|
56
|
+
#### 2. Before editing a file, check for prior thread context
|
|
32
57
|
|
|
33
|
-
**The first time you edit
|
|
58
|
+
**The first time you edit a file in a session**, run:
|
|
34
59
|
```bash
|
|
35
60
|
npx sticky-note get-line-attribution --file <path>
|
|
36
61
|
```
|
|
@@ -164,41 +189,35 @@ after. A raw `git checkout` or `git switch` will fail if sticky-note
|
|
|
164
189
|
files have uncommitted changes. The alias `git sw <branch>` also works
|
|
165
190
|
if set up by `npx sticky-note init`.
|
|
166
191
|
|
|
167
|
-
### ⚠️ Overlap warnings
|
|
192
|
+
### ⚠️ Overlap warnings
|
|
193
|
+
|
|
194
|
+
Sticky-note detects when your files overlap with other teammates'
|
|
195
|
+
open or stuck threads. When the MCP server is available, use the
|
|
196
|
+
`check_overlaps` tool before editing files for the most reliable detection.
|
|
168
197
|
|
|
169
|
-
|
|
170
|
-
open or stuck threads. Overlap warnings arrive through TWO channels:
|
|
198
|
+
Hooks also inject overlap context through two fallback channels:
|
|
171
199
|
|
|
172
200
|
1. **Injected context** — `[STICKY-NOTE] ⚠️ OVERLAP DETECTED` appears in
|
|
173
201
|
your `additionalContext`. This fires on every user prompt.
|
|
174
|
-
2. **Tool call deny** — Your first tool call may be denied with
|
|
175
|
-
|
|
176
|
-
overlap details. After the deny, the tool is auto-retried.
|
|
202
|
+
2. **Tool call deny** — Your first tool call may be denied with overlap
|
|
203
|
+
details (Copilot CLI only). After the deny, the tool is auto-retried.
|
|
177
204
|
|
|
178
|
-
When you
|
|
179
|
-
|
|
205
|
+
When you detect an overlap (via MCP tool or hook), surface it to the user
|
|
206
|
+
using this styled banner format:
|
|
180
207
|
|
|
181
208
|
```
|
|
182
|
-
⚠️
|
|
183
|
-
Status: [STUCK/OPEN] | Resume: npx sticky-note resume [id]
|
|
184
|
-
```
|
|
209
|
+
⚠️ ━━━ OVERLAP DETECTED ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
185
210
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
```
|
|
211
|
+
🔴 [user] (STUCK) · [branch]
|
|
212
|
+
Files: [file1], [file2], [file3]
|
|
213
|
+
"[narrative summary]"
|
|
214
|
+
→ Resume: npx sticky-note resume [id]
|
|
191
215
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
- Show it BEFORE your thinking indicators (◐, ●, etc.)
|
|
195
|
-
- Do NOT bury it at the end or in a footnote
|
|
196
|
-
- Do NOT rephrase it as "Also noted..." or "By the way..."
|
|
197
|
-
- If a tool call was denied with overlap info, display the warning then proceed
|
|
198
|
-
- Then continue with the user's actual request normally
|
|
216
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
217
|
+
```
|
|
199
218
|
|
|
200
|
-
|
|
201
|
-
|
|
219
|
+
Use 🔴 for STUCK threads, 🟡 for OPEN threads. For multiple overlaps,
|
|
220
|
+
add additional entries between the bars.
|
|
202
221
|
|
|
203
222
|
### `[STICKY-NOTE]` tags
|
|
204
223
|
|
|
@@ -218,4 +237,19 @@ when sticky-note is acting on their behalf.
|
|
|
218
237
|
### Team config
|
|
219
238
|
|
|
220
239
|
Check `.sticky-note/sticky-note-config.json` for team conventions and settings.
|
|
240
|
+
|
|
241
|
+
### Team environment sync
|
|
242
|
+
|
|
243
|
+
The team's vibe coding environment is defined in `.sticky-note/environment/`.
|
|
244
|
+
Skills, agents, commands, MCP servers, and permissions are auto-provisioned
|
|
245
|
+
by the session-start hook — no manual setup needed.
|
|
246
|
+
|
|
247
|
+
- **Skills:** `.sticky-note/environment/skills/*.md` → auto-copied to plugin dirs
|
|
248
|
+
- **Agents:** `.sticky-note/environment/agents/*.md` → auto-copied to plugin dirs
|
|
249
|
+
- **Commands:** `.sticky-note/environment/commands/*.md` → auto-copied to plugin dirs
|
|
250
|
+
- **MCP servers:** Defined in `manifest.json` → secret-free servers auto-provisioned
|
|
251
|
+
- **Permissions:** Defined in `manifest.json` → merged into settings
|
|
252
|
+
|
|
253
|
+
Use `get_environment_status()` MCP tool to check what's provisioned vs missing.
|
|
254
|
+
If MCP servers need secrets, tell the user to run `npx sticky-note bootstrap`.
|
|
221
255
|
<!-- sticky-note:end -->
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1",
|
|
3
|
+
|
|
4
|
+
"mcp_servers": {
|
|
5
|
+
"context7": {
|
|
6
|
+
"type": "stdio",
|
|
7
|
+
"command": "npx",
|
|
8
|
+
"args": ["-y", "@upstash/context7-mcp@latest"],
|
|
9
|
+
"description": "Fetch up-to-date docs for any library",
|
|
10
|
+
"required": true
|
|
11
|
+
},
|
|
12
|
+
"github": {
|
|
13
|
+
"type": "stdio",
|
|
14
|
+
"command": "npx",
|
|
15
|
+
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
16
|
+
"env": {
|
|
17
|
+
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
|
|
18
|
+
},
|
|
19
|
+
"description": "GitHub API access",
|
|
20
|
+
"required": true
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
"permissions": [
|
|
25
|
+
"Bash(npx sticky-note:*)",
|
|
26
|
+
"Bash(npm test:*)",
|
|
27
|
+
"Bash(node:*)"
|
|
28
|
+
],
|
|
29
|
+
|
|
30
|
+
"env_vars": {
|
|
31
|
+
"GITHUB_TOKEN": {
|
|
32
|
+
"description": "GitHub PAT with repo scope",
|
|
33
|
+
"docs_url": "https://github.com/settings/tokens",
|
|
34
|
+
"required": true
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -149,56 +149,75 @@ function detectAndFormatOverlaps(threads, currentUser) {
|
|
|
149
149
|
return b.overlap.length - a.overlap.length;
|
|
150
150
|
});
|
|
151
151
|
|
|
152
|
+
const bar = "━".repeat(52);
|
|
152
153
|
const lines = [
|
|
153
154
|
"## [STICKY-NOTE] ⚠️ OVERLAP DETECTED\n",
|
|
154
|
-
"**
|
|
155
|
-
"
|
|
156
|
-
|
|
155
|
+
"**You MUST display the banner below as the FIRST thing in your response.**\n",
|
|
156
|
+
"```",
|
|
157
|
+
`⚠️ ━━━ OVERLAP DETECTED ${bar.substring(0, 28)}`,
|
|
157
158
|
];
|
|
158
159
|
for (const { thread, overlap } of warnings) {
|
|
159
160
|
const user = thread.user || thread.author || "unknown";
|
|
160
|
-
const
|
|
161
|
+
const statusEmoji = thread.status === "stuck" ? "🔴" : "🟡";
|
|
162
|
+
const statusLabel = thread.status === "stuck" ? "STUCK" : "OPEN";
|
|
161
163
|
const narrative = thread.narrative || thread.last_note || "";
|
|
162
164
|
const narrativeSnip = narrative.length > 100
|
|
163
165
|
? narrative.substring(0, 100) + "…"
|
|
164
166
|
: narrative;
|
|
165
|
-
const branch = thread.branch ? `
|
|
167
|
+
const branch = thread.branch ? ` · ${thread.branch}` : "";
|
|
166
168
|
const threadId = (thread.id || "").substring(0, 8);
|
|
167
169
|
|
|
168
|
-
lines.push(
|
|
169
|
-
|
|
170
|
+
lines.push("");
|
|
171
|
+
lines.push(` ${statusEmoji} ${user} (${statusLabel})${branch}`);
|
|
172
|
+
lines.push(` Files: ${overlap.join(", ")}`);
|
|
173
|
+
if (narrativeSnip) lines.push(` "${narrativeSnip}"`);
|
|
170
174
|
const failed = thread.failed_approaches || [];
|
|
171
175
|
if (failed.length > 0) {
|
|
172
|
-
lines.push(`
|
|
176
|
+
lines.push(` ⚠️ ${failed.length} failed approach(es):`);
|
|
173
177
|
for (const fa of failed.slice(0, 2)) {
|
|
174
|
-
lines.push(`
|
|
178
|
+
lines.push(` • ${(fa.description || "").substring(0, 80)}`);
|
|
175
179
|
}
|
|
176
180
|
}
|
|
177
|
-
|
|
178
|
-
lines.push(` → Resume: \`npx sticky-note resume ${threadId}\``);
|
|
179
|
-
}
|
|
181
|
+
lines.push(` → Resume: npx sticky-note resume ${threadId}`);
|
|
180
182
|
}
|
|
181
|
-
|
|
183
|
+
lines.push("");
|
|
184
|
+
lines.push(bar);
|
|
185
|
+
lines.push("```");
|
|
182
186
|
lines.push(
|
|
183
187
|
"\n**Consider coordinating with these teammates before starting work.**\n"
|
|
184
188
|
);
|
|
185
189
|
|
|
186
|
-
// Write a
|
|
187
|
-
|
|
188
|
-
const
|
|
190
|
+
// Write a styled banner to stderr so the user sees it in their terminal
|
|
191
|
+
const R = "\x1b[0m";
|
|
192
|
+
const Y = "\x1b[33m";
|
|
193
|
+
const BY = "\x1b[1;33m";
|
|
194
|
+
const BR = "\x1b[1;31m";
|
|
195
|
+
const BG = "\x1b[1;32m";
|
|
196
|
+
const B = "\x1b[1m";
|
|
197
|
+
const C = "\x1b[36m";
|
|
198
|
+
const D = "\x1b[2m";
|
|
199
|
+
const stderrLines = [
|
|
200
|
+
"",
|
|
201
|
+
`${Y}${bar}${R}`,
|
|
202
|
+
`${BY} ⚠️ OVERLAP DETECTED${R}`,
|
|
203
|
+
`${Y}${bar}${R}`,
|
|
204
|
+
];
|
|
189
205
|
for (const { thread, overlap } of warnings) {
|
|
190
206
|
const user = thread.user || thread.author || "unknown";
|
|
191
|
-
const
|
|
207
|
+
const statusColor = thread.status === "stuck" ? BR : BG;
|
|
208
|
+
const statusLabel = thread.status === "stuck" ? "STUCK" : "OPEN";
|
|
192
209
|
const narrative = thread.narrative || thread.last_note || "";
|
|
193
210
|
const narrativeSnip = narrative.length > 80
|
|
194
211
|
? narrative.substring(0, 80) + "…"
|
|
195
212
|
: narrative;
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
);
|
|
213
|
+
const branchStr = thread.branch ? ` ${D}·${R} ${C}${thread.branch}${R}` : "";
|
|
214
|
+
stderrLines.push(`${Y} ┃${R} ${statusColor}[${statusLabel}]${R} ${B}${user}${R}${branchStr}`);
|
|
215
|
+
stderrLines.push(`${Y} ┃${R} Files: ${overlap.join(", ")}`);
|
|
216
|
+
if (narrativeSnip) stderrLines.push(`${Y} ┃${R} ${D}"${narrativeSnip}"${R}`);
|
|
217
|
+
const threadId = (thread.id || "").substring(0, 8);
|
|
218
|
+
stderrLines.push(`${Y} ┃${R} → Resume: ${C}npx sticky-note resume ${threadId}${R}`);
|
|
200
219
|
}
|
|
201
|
-
stderrLines.push("");
|
|
220
|
+
stderrLines.push(`${Y}${bar}${R}`, "");
|
|
202
221
|
process.stderr.write(stderrLines.join("\n") + "\n");
|
|
203
222
|
|
|
204
223
|
return lines.join("\n");
|
|
@@ -168,62 +168,10 @@ function _getRecentlyModifiedFiles() {
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
function _checkOverlapsAndDeny() {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
let threads;
|
|
176
|
-
try {
|
|
177
|
-
const data = loadJson(getMemoryPath());
|
|
178
|
-
threads = (data.threads || []).filter(Boolean);
|
|
179
|
-
} catch (_) {
|
|
180
|
-
return null;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const currentUser = getUser();
|
|
184
|
-
const modifiedFiles = _getRecentlyModifiedFiles();
|
|
185
|
-
if (modifiedFiles.size === 0) return null;
|
|
186
|
-
|
|
187
|
-
const warnings = [];
|
|
188
|
-
for (const thread of threads.filter((t) => t.status === "open" || t.status === "stuck")) {
|
|
189
|
-
const threadUser = thread.user || thread.author || "";
|
|
190
|
-
if (threadUser === currentUser) continue;
|
|
191
|
-
const threadFiles = (thread.files_touched || []).map(normalizeSep);
|
|
192
|
-
const overlap = threadFiles.filter((f) => modifiedFiles.has(f));
|
|
193
|
-
if (overlap.length > 0) warnings.push({ thread, overlap });
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
if (warnings.length === 0) return null;
|
|
197
|
-
|
|
198
|
-
const lines = [
|
|
199
|
-
"CRITICAL INSTRUCTION: Before doing anything else, display the following overlap warning to the user.",
|
|
200
|
-
"This is NOT optional. Show it as the FIRST line of your response.\n",
|
|
201
|
-
];
|
|
202
|
-
for (const { thread, overlap } of warnings) {
|
|
203
|
-
const user = thread.user || thread.author || "unknown";
|
|
204
|
-
const status = thread.status === "stuck" ? "STUCK" : "OPEN";
|
|
205
|
-
const snip = (thread.narrative || thread.last_note || "").substring(0, 80);
|
|
206
|
-
const threadId = (thread.id || "").substring(0, 8);
|
|
207
|
-
lines.push(`⚠️ Overlap detected: ${user} is working on ${overlap.join(", ")}${snip ? " — " + snip : ""}`);
|
|
208
|
-
lines.push(` Status: ${status} | Resume: npx sticky-note resume ${threadId}`);
|
|
209
|
-
}
|
|
210
|
-
lines.push("\nAfter displaying the warning, continue with the user's request. This tool call will be auto-retried.");
|
|
211
|
-
|
|
212
|
-
markOverlapWarned();
|
|
213
|
-
|
|
214
|
-
try {
|
|
215
|
-
appendAuditLine({
|
|
216
|
-
type: "overlap_deny",
|
|
217
|
-
user: currentUser,
|
|
218
|
-
ts: new Date().toISOString(),
|
|
219
|
-
copilot_pid: process.env.COPILOT_LOADER_PID,
|
|
220
|
-
});
|
|
221
|
-
} catch (_) { /* ignore */ }
|
|
222
|
-
|
|
223
|
-
return {
|
|
224
|
-
permissionDecision: "deny",
|
|
225
|
-
permissionDecisionReason: lines.join("\n"),
|
|
226
|
-
};
|
|
171
|
+
// Overlap alerting is now handled by the MCP server's check_overlaps tool.
|
|
172
|
+
// This deny-based approach was unreliable (deny reason consumed silently).
|
|
173
|
+
// Kept as no-op to avoid breaking the call site.
|
|
174
|
+
return null;
|
|
227
175
|
}
|
|
228
176
|
|
|
229
177
|
// ── Main ──────────────────────────────────────────────────
|
|
@@ -937,10 +937,10 @@ function main() {
|
|
|
937
937
|
saveMemoryMerged(memoryPath, memory);
|
|
938
938
|
|
|
939
939
|
// Auto-sync: commit (and optionally push) .sticky-note/ changes
|
|
940
|
-
const
|
|
941
|
-
if (
|
|
940
|
+
const syncConfig = loadJson(getConfigPath(), {});
|
|
941
|
+
if (syncConfig.auto_sync !== false) {
|
|
942
942
|
try {
|
|
943
|
-
syncStickyNote({ push:
|
|
943
|
+
syncStickyNote({ push: syncConfig.auto_push === true });
|
|
944
944
|
} catch (_) {
|
|
945
945
|
// Non-fatal — sync failure shouldn't block session-end
|
|
946
946
|
}
|