@@ -45,18 +45,39 @@ const SEARCH_RESULT_CREATED_AT_FALLBACK = "1970-01-01T00:00:00.000Z";
4545
4646export const SESSION_NOTES_WRITE_DESCRIPTION = [
4747 "Pin working context as a session note so it survives topic switches, long tool" ,
48- "loops, and compaction. Use this BEFORE drifting away from important context:" ,
48+ "loops, and compaction. Notes are the primary continuity surface — write or" ,
49+ "update one BEFORE you stop, hand back to the user, or risk losing context." ,
50+ "" ,
51+ "Required lifecycle (follow this protocol — do not skip steps):" ,
52+ "" ,
53+ "1. **Starting a new task** → first run `session_search` and" ,
54+ " `session_notes_read` on relevant note hits to check whether an existing" ,
55+ " note already covers this work. If one does, upsert it (see step 2). If" ,
56+ " none exists, create a new note with a short description and a markdown" ,
57+ " checklist of the planned sub-tasks." ,
58+ "2. **Finishing a sub-task** → upsert the same note (call this tool with" ,
59+ " non-empty `text` and `replace: <id>`) to check off the completed item." ,
60+ "3. **Stopping mid-task** (blocker, finding, awaiting user input) → upsert" ,
61+ " the note with current progress and findings BEFORE reporting back to the" ,
62+ " user. Approaching ~75% context usage counts as stopping mid-task: upsert" ,
63+ " with full detail so a post-compaction agent can resume without" ,
64+ " re-derivation." ,
65+ "4. **Completing the task** → ONLY when the task is fully done, clear the" ,
66+ " note BEFORE reporting back. Clearing means deleting it: call this tool" ,
67+ ' with empty `text` and `replace: <id>` (or `replace: "*"` with empty text' ,
68+ " to clear all notes for this scope). Do not clear a note for a paused," ,
69+ " blocked, or partially complete task — upsert per step 3 instead." ,
70+ "" ,
71+ "Also write/update a note:" ,
4972 "" ,
50- "- Before switching to a different topic or task" ,
5173 "- After a user correction changes your assumptions" ,
52- "- When a small task stalls and work shifts elsewhere " ,
74+ "- Before switching to a different topic or task " ,
5375 "- During long tool-calling sequences where key state lives only in your context" ,
54- "- Before compaction is likely (many messages into a session)" ,
5576 "" ,
5677 "Do NOT use this for ephemeral state that will be irrelevant within a few turns" ,
5778 "(e.g., intermediate variable values, transient build errors you are about to" ,
58- "fix, or scratchpad reasoning). Notes are for context you need to survive" ,
59- "across topic switches or compaction — not for every observation ." ,
79+ "fix, or scratchpad reasoning). Notes are for context that must survive topic " ,
80+ "switches, compaction, or a fresh agent picking up the work ." ,
6081 "" ,
6182 "Accepts `text` (markdown body) and optional `replace`:" ,
6283 "" ,
@@ -70,59 +91,84 @@ export const SESSION_NOTES_WRITE_DESCRIPTION = [
7091 '- omit `replace` to create a new note and return `{ action: "created", id }`' ,
7192 "" ,
7293 "Always rely on the returned `action` instead of inferring the outcome from the" ,
73- "inputs alone." ,
94+ "inputs alone. Capture the returned `id` so subsequent updates upsert the same" ,
95+ "note rather than creating duplicates." ,
7496 "" ,
75- "Prefer concise markdown with headings, bullets, and short code snippets :" ,
97+ "Prefer concise markdown with a heading and a checklist :" ,
7698 "" ,
7799 " ## Current Task: Fix Redis TTL bug" ,
78100 " - **File:** `src/services/redis-client.ts`" ,
79101 " - **Root cause:** TTL not refreshed on read" ,
80- " - **Next step:** Add EXPIRE call after GET in `refreshEntry()`" ,
102+ " - **Progress:**" ,
103+ " - [x] Reproduce on staging" ,
104+ " - [x] Identify missing EXPIRE in `refreshEntry()`" ,
105+ " - [ ] Add regression test" ,
106+ " - [ ] Land fix" ,
81107 " - **User correction:** Use seconds not milliseconds for TTL" ,
82108] . join ( "\n" ) ;
83109
84110export const SESSION_NOTES_READ_DESCRIPTION = [
85- "Reopen exact pinned note text instead of reconstructing it from memory. Use this" ,
86- "when you resume an interrupted topic, need the exact wording of a pinned user" ,
87- "instruction, or want to verify what you previously noted before acting on it." ,
111+ "Reopen exact pinned note text instead of reconstructing it from memory. This" ,
112+ "is the second step of the recall protocol: after `session_search` surfaces a" ,
113+ "matching note hit, call `session_notes_read` with that note `id` to load the" ,
114+ "full body before acting." ,
115+ "" ,
116+ "Call this tool whenever you need authoritative pinned context, especially:" ,
117+ "" ,
118+ "- At the start of a new session, after compaction, or when resuming an" ,
119+ " interrupted task — these are the highest-priority recall moments." ,
120+ '- When `session_search` returns a `type: "note"` hit relevant to your task.' ,
121+ "- When you need the exact wording of a pinned user instruction, plan, or" ,
122+ " checklist before acting on it." ,
88123 "" ,
89124 "If `id` is provided, returns that single note as" ,
90125 "`{ note: { id, text, created_at, updated_at } }`; when the id does not exist," ,
91126 "returns `{ note: null }`." ,
92127 "" ,
93128 "Always prefer reading a pinned note over reciting its contents from recall —" ,
94- "notes are the source of truth for intentionally preserved context." ,
129+ "notes are the source of truth for intentionally preserved context. After" ,
130+ "reading, update the note as you make progress by calling" ,
131+ "`session_notes_write` with non-empty `text` and `replace: <id>` (passing" ,
132+ "empty `text` would delete the note — only do that when the task is fully" ,
133+ "complete)." ,
95134] . join ( "\n" ) ;
96135
97136export const SESSION_SEARCH_BASELINE_DESCRIPTION = [
98- "Search local indexed content for the current root session. This is the default" ,
99- "recall path — use it FIRST when you need prior context, especially:" ,
137+ "Search local indexed content for the current root session. This is the FIRST" ,
138+ "step of the recall protocol — run a `session_search` BEFORE doing other work" ,
139+ "whenever prior context may exist, especially:" ,
100140 "" ,
101- "- At the start of a new session or after compaction" ,
102- "- When resuming a topic you worked on earlier" ,
103- "- Before re-solving a problem that may already have a solution in session history" ,
104- "- To check whether pinned session notes already contain the context you need" ,
141+ "- At the start of a new session or immediately after compaction (highest" ,
142+ " priority — pinned notes and prior decisions may not be in working memory)." ,
143+ "- When resuming a topic you worked on earlier in this or a sibling session." ,
144+ "- Before re-solving a problem that may already have a solution in session" ,
145+ " history, or contradicting an earlier decision." ,
146+ "- To check whether pinned session notes already contain the context you need." ,
105147 "" ,
106148 'Results may include indexed memory content (type: "memory") and, when pinned' ,
107149 'session notes exist, matching notes (type: "note"). Note results include' ,
108150 '`id`, `root_session_id`, `scope: "local" | "project"`, `created_at`, and' ,
109- "`updated_at` — use `session_notes_read` with the note `id` to reopen the full" ,
110- "note text. Not every query will return note results; notes only appear when they" ,
111- "match the search query and the session has pinned notes." ,
151+ "`updated_at` — when a note hit is relevant, immediately call" ,
152+ "`session_notes_read` with that `id` to load the full note text. Do not" ,
153+ "paraphrase a note from its snippet. Not every query returns note results;" ,
154+ "notes only appear when they match the query and the session has pinned notes." ,
112155 "" ,
113- "Prefer session_search over reconstructing context from scratch. If search" ,
114- "returns relevant note hits, read the note before duplicating its contents." ,
156+ "Prefer `session_search` over reconstructing context from scratch. The full" ,
157+ "continuity protocol is: (1) `session_search` to discover, (2)" ,
158+ "`session_notes_read` for relevant note hits, (3) `session_notes_write` to" ,
159+ "pin or update progress before stopping or reporting back." ,
115160] . join ( "\n" ) ;
116161
117162export const SESSION_SEARCH_STRENGTHENED_DESCRIPTION =
118163 SESSION_SEARCH_BASELINE_DESCRIPTION +
119164 "\n\n" +
120165 [
121166 "⚠️ This is a new session or a post-compaction turn. Prior context may have been" ,
122- "summarized or is not yet in your working memory. STRONGLY RECOMMENDED: run a" ,
123- "session_search query before starting work to recover earlier decisions, pinned" ,
124- "notes, and task state. This avoids re-solving problems or contradicting earlier" ,
125- "decisions that survived compaction." ,
167+ "summarized or is not yet in your working memory. STRONGLY RECOMMENDED before" ,
168+ "doing anything else: run `session_search` to recover earlier decisions, pinned" ,
169+ "notes, and task state, then call `session_notes_read` on any relevant note" ,
170+ "hits to load their exact text. This avoids re-solving problems, contradicting" ,
171+ "earlier decisions, or duplicating notes that already track the work." ,
126172 ] . join ( "\n" ) ;
127173
128174type PluginToolArgs = Parameters < typeof tool > [ 0 ] [ "args" ] ;
0 commit comments