@tekmidian/pai 0.5.7 → 0.6.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.
Files changed (138) hide show
  1. package/ARCHITECTURE.md +198 -47
  2. package/FEATURE.md +2 -2
  3. package/README.md +87 -1
  4. package/dist/{auto-route-BG6I_4B1.mjs → auto-route-C-DrW6BL.mjs} +3 -3
  5. package/dist/{auto-route-BG6I_4B1.mjs.map → auto-route-C-DrW6BL.mjs.map} +1 -1
  6. package/dist/cli/index.mjs +1482 -1628
  7. package/dist/cli/index.mjs.map +1 -1
  8. package/dist/clusters-JIDQW65f.mjs +201 -0
  9. package/dist/clusters-JIDQW65f.mjs.map +1 -0
  10. package/dist/{config-Cf92lGX_.mjs → config-BuhHWyOK.mjs} +21 -6
  11. package/dist/config-BuhHWyOK.mjs.map +1 -0
  12. package/dist/daemon/index.mjs +11 -8
  13. package/dist/daemon/index.mjs.map +1 -1
  14. package/dist/{daemon-2ND5WO2j.mjs → daemon-D3hYb5_C.mjs} +669 -218
  15. package/dist/daemon-D3hYb5_C.mjs.map +1 -0
  16. package/dist/daemon-mcp/index.mjs +4597 -4
  17. package/dist/daemon-mcp/index.mjs.map +1 -1
  18. package/dist/db-DdUperSl.mjs +110 -0
  19. package/dist/db-DdUperSl.mjs.map +1 -0
  20. package/dist/{detect-BU3Nx_2L.mjs → detect-CdaA48EI.mjs} +1 -1
  21. package/dist/{detect-BU3Nx_2L.mjs.map → detect-CdaA48EI.mjs.map} +1 -1
  22. package/dist/{detector-Bp-2SM3x.mjs → detector-jGBuYQJM.mjs} +2 -2
  23. package/dist/{detector-Bp-2SM3x.mjs.map → detector-jGBuYQJM.mjs.map} +1 -1
  24. package/dist/{factory-Bzcy70G9.mjs → factory-Ygqe_bVZ.mjs} +7 -5
  25. package/dist/{factory-Bzcy70G9.mjs.map → factory-Ygqe_bVZ.mjs.map} +1 -1
  26. package/dist/helpers-BEST-4Gx.mjs +420 -0
  27. package/dist/helpers-BEST-4Gx.mjs.map +1 -0
  28. package/dist/hooks/capture-all-events.mjs +2 -2
  29. package/dist/hooks/capture-all-events.mjs.map +3 -3
  30. package/dist/hooks/capture-session-summary.mjs +38 -0
  31. package/dist/hooks/capture-session-summary.mjs.map +3 -3
  32. package/dist/hooks/cleanup-session-files.mjs +6 -12
  33. package/dist/hooks/cleanup-session-files.mjs.map +4 -4
  34. package/dist/hooks/context-compression-hook.mjs +93 -104
  35. package/dist/hooks/context-compression-hook.mjs.map +4 -4
  36. package/dist/hooks/initialize-session.mjs +14 -11
  37. package/dist/hooks/initialize-session.mjs.map +4 -4
  38. package/dist/hooks/inject-observations.mjs +220 -0
  39. package/dist/hooks/inject-observations.mjs.map +7 -0
  40. package/dist/hooks/load-core-context.mjs +2 -2
  41. package/dist/hooks/load-core-context.mjs.map +3 -3
  42. package/dist/hooks/load-project-context.mjs +90 -91
  43. package/dist/hooks/load-project-context.mjs.map +4 -4
  44. package/dist/hooks/observe.mjs +354 -0
  45. package/dist/hooks/observe.mjs.map +7 -0
  46. package/dist/hooks/stop-hook.mjs +94 -107
  47. package/dist/hooks/stop-hook.mjs.map +4 -4
  48. package/dist/hooks/sync-todo-to-md.mjs +31 -33
  49. package/dist/hooks/sync-todo-to-md.mjs.map +4 -4
  50. package/dist/index.d.mts +30 -7
  51. package/dist/index.d.mts.map +1 -1
  52. package/dist/index.mjs +5 -8
  53. package/dist/indexer-D53l5d1U.mjs +1 -0
  54. package/dist/{indexer-backend-CIMXedqk.mjs → indexer-backend-jcJFsmB4.mjs} +37 -127
  55. package/dist/indexer-backend-jcJFsmB4.mjs.map +1 -0
  56. package/dist/{ipc-client-Bjg_a1dc.mjs → ipc-client-CoyUHPod.mjs} +2 -7
  57. package/dist/{ipc-client-Bjg_a1dc.mjs.map → ipc-client-CoyUHPod.mjs.map} +1 -1
  58. package/dist/latent-ideas-bTJo6Omd.mjs +191 -0
  59. package/dist/latent-ideas-bTJo6Omd.mjs.map +1 -0
  60. package/dist/neighborhood-BYYbEkUJ.mjs +135 -0
  61. package/dist/neighborhood-BYYbEkUJ.mjs.map +1 -0
  62. package/dist/note-context-BK24bX8Y.mjs +126 -0
  63. package/dist/note-context-BK24bX8Y.mjs.map +1 -0
  64. package/dist/postgres-CKf-EDtS.mjs +846 -0
  65. package/dist/postgres-CKf-EDtS.mjs.map +1 -0
  66. package/dist/{reranker-D7bRAHi6.mjs → reranker-CMNZcfVx.mjs} +1 -1
  67. package/dist/{reranker-D7bRAHi6.mjs.map → reranker-CMNZcfVx.mjs.map} +1 -1
  68. package/dist/{search-_oHfguA5.mjs → search-DC1qhkKn.mjs} +2 -58
  69. package/dist/search-DC1qhkKn.mjs.map +1 -0
  70. package/dist/{sqlite-WWBq7_2C.mjs → sqlite-l-s9xPjY.mjs} +160 -3
  71. package/dist/sqlite-l-s9xPjY.mjs.map +1 -0
  72. package/dist/state-C6_vqz7w.mjs +102 -0
  73. package/dist/state-C6_vqz7w.mjs.map +1 -0
  74. package/dist/stop-words-BaMEGVeY.mjs +326 -0
  75. package/dist/stop-words-BaMEGVeY.mjs.map +1 -0
  76. package/dist/{indexer-CMPOiY1r.mjs → sync-BOsnEj2-.mjs} +14 -216
  77. package/dist/sync-BOsnEj2-.mjs.map +1 -0
  78. package/dist/themes-BvYF0W8T.mjs +148 -0
  79. package/dist/themes-BvYF0W8T.mjs.map +1 -0
  80. package/dist/{tools-DV_lsiCc.mjs → tools-DcaJlYDN.mjs} +162 -273
  81. package/dist/tools-DcaJlYDN.mjs.map +1 -0
  82. package/dist/trace-CRx9lPuc.mjs +137 -0
  83. package/dist/trace-CRx9lPuc.mjs.map +1 -0
  84. package/dist/{vault-indexer-k-kUlaZ-.mjs → vault-indexer-Bi2cRmn7.mjs} +134 -132
  85. package/dist/vault-indexer-Bi2cRmn7.mjs.map +1 -0
  86. package/dist/zettelkasten-cdajbnPr.mjs +708 -0
  87. package/dist/zettelkasten-cdajbnPr.mjs.map +1 -0
  88. package/package.json +1 -2
  89. package/src/hooks/ts/lib/project-utils/index.ts +50 -0
  90. package/src/hooks/ts/lib/project-utils/notify.ts +75 -0
  91. package/src/hooks/ts/lib/project-utils/paths.ts +218 -0
  92. package/src/hooks/ts/lib/project-utils/session-notes.ts +363 -0
  93. package/src/hooks/ts/lib/project-utils/todo.ts +178 -0
  94. package/src/hooks/ts/lib/project-utils/tokens.ts +39 -0
  95. package/src/hooks/ts/lib/project-utils.ts +40 -1018
  96. package/src/hooks/ts/post-tool-use/observe.ts +327 -0
  97. package/src/hooks/ts/session-end/capture-session-summary.ts +41 -0
  98. package/src/hooks/ts/session-start/inject-observations.ts +254 -0
  99. package/dist/chunker-CbnBe0s0.mjs +0 -191
  100. package/dist/chunker-CbnBe0s0.mjs.map +0 -1
  101. package/dist/config-Cf92lGX_.mjs.map +0 -1
  102. package/dist/daemon-2ND5WO2j.mjs.map +0 -1
  103. package/dist/db-Dp8VXIMR.mjs +0 -212
  104. package/dist/db-Dp8VXIMR.mjs.map +0 -1
  105. package/dist/indexer-CMPOiY1r.mjs.map +0 -1
  106. package/dist/indexer-backend-CIMXedqk.mjs.map +0 -1
  107. package/dist/mcp/index.d.mts +0 -1
  108. package/dist/mcp/index.mjs +0 -500
  109. package/dist/mcp/index.mjs.map +0 -1
  110. package/dist/postgres-FXrHDPcE.mjs +0 -358
  111. package/dist/postgres-FXrHDPcE.mjs.map +0 -1
  112. package/dist/schemas-BFIgGntb.mjs +0 -3405
  113. package/dist/schemas-BFIgGntb.mjs.map +0 -1
  114. package/dist/search-_oHfguA5.mjs.map +0 -1
  115. package/dist/sqlite-WWBq7_2C.mjs.map +0 -1
  116. package/dist/tools-DV_lsiCc.mjs.map +0 -1
  117. package/dist/vault-indexer-k-kUlaZ-.mjs.map +0 -1
  118. package/dist/zettelkasten-e-a4rW_6.mjs +0 -901
  119. package/dist/zettelkasten-e-a4rW_6.mjs.map +0 -1
  120. package/templates/README.md +0 -181
  121. package/templates/skills/CORE/Aesthetic.md +0 -333
  122. package/templates/skills/CORE/CONSTITUTION.md +0 -1502
  123. package/templates/skills/CORE/HistorySystem.md +0 -427
  124. package/templates/skills/CORE/HookSystem.md +0 -1082
  125. package/templates/skills/CORE/Prompting.md +0 -509
  126. package/templates/skills/CORE/ProsodyAgentTemplate.md +0 -53
  127. package/templates/skills/CORE/ProsodyGuide.md +0 -416
  128. package/templates/skills/CORE/SKILL.md +0 -741
  129. package/templates/skills/CORE/SkillSystem.md +0 -213
  130. package/templates/skills/CORE/TerminalTabs.md +0 -119
  131. package/templates/skills/CORE/VOICE.md +0 -106
  132. package/templates/skills/createskill-skill.template.md +0 -78
  133. package/templates/skills/history-system.template.md +0 -371
  134. package/templates/skills/hook-system.template.md +0 -913
  135. package/templates/skills/sessions-skill.template.md +0 -102
  136. package/templates/skills/skill-system.template.md +0 -214
  137. package/templates/skills/terminal-tabs.template.md +0 -120
  138. package/templates/templates.md +0 -20
@@ -1,13 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/hooks/ts/stop/stop-hook.ts
4
- import { readFileSync as readFileSync3 } from "fs";
5
- import { basename as basename2, dirname } from "path";
4
+ import { readFileSync as readFileSync5 } from "fs";
5
+ import { basename as basename3, dirname } from "path";
6
6
 
7
- // src/hooks/ts/lib/project-utils.ts
8
- import { existsSync as existsSync2, mkdirSync, readdirSync, readFileSync as readFileSync2, writeFileSync, renameSync } from "fs";
7
+ // src/hooks/ts/lib/project-utils/paths.ts
8
+ import { existsSync as existsSync2, mkdirSync, readdirSync, renameSync } from "fs";
9
9
  import { join as join2, basename } from "path";
10
- import { homedir as homedir2 } from "os";
11
10
 
12
11
  // src/hooks/ts/lib/pai-paths.ts
13
12
  import { homedir } from "os";
@@ -67,7 +66,8 @@ function validatePAIStructure() {
67
66
  }
68
67
  validatePAIStructure();
69
68
 
70
- // src/hooks/ts/lib/project-utils.ts
69
+ // src/hooks/ts/lib/project-utils/paths.ts
70
+ var PROJECTS_DIR = join2(PAI_DIR, "projects");
71
71
  var PROBE_CWD_PATTERNS = [
72
72
  "/CodexBar/ClaudeProbe",
73
73
  "/ClaudeProbe"
@@ -76,7 +76,6 @@ function isProbeSession(cwd) {
76
76
  const dir = cwd || process.cwd();
77
77
  return PROBE_CWD_PATTERNS.some((pattern) => dir.includes(pattern));
78
78
  }
79
- var PROJECTS_DIR = join2(PAI_DIR, "projects");
80
79
  function encodePath(path) {
81
80
  return path.replace(/\//g, "-").replace(/\./g, "-").replace(/ /g, "-");
82
81
  }
@@ -107,10 +106,55 @@ function findNotesDir(cwd) {
107
106
  function getSessionsDirFromProjectDir(projectDir) {
108
107
  return join2(projectDir, "sessions");
109
108
  }
109
+ function ensureSessionsDirFromProjectDir(projectDir) {
110
+ const sessionsDir = getSessionsDirFromProjectDir(projectDir);
111
+ if (!existsSync2(sessionsDir)) {
112
+ mkdirSync(sessionsDir, { recursive: true });
113
+ console.error(`Created sessions directory: ${sessionsDir}`);
114
+ }
115
+ return sessionsDir;
116
+ }
117
+ function moveSessionFilesToSessionsDir(projectDir, excludeFile, silent = false) {
118
+ const sessionsDir = ensureSessionsDirFromProjectDir(projectDir);
119
+ if (!existsSync2(projectDir)) return 0;
120
+ const files = readdirSync(projectDir);
121
+ let movedCount = 0;
122
+ for (const file of files) {
123
+ if (file.endsWith(".jsonl") && file !== excludeFile) {
124
+ const sourcePath = join2(projectDir, file);
125
+ const destPath = join2(sessionsDir, file);
126
+ try {
127
+ renameSync(sourcePath, destPath);
128
+ if (!silent) console.error(`Moved ${file} \u2192 sessions/`);
129
+ movedCount++;
130
+ } catch (error) {
131
+ if (!silent) console.error(`Could not move ${file}: ${error}`);
132
+ }
133
+ }
134
+ }
135
+ return movedCount;
136
+ }
137
+ function findTodoPath(cwd) {
138
+ const localPaths = [
139
+ join2(cwd, "TODO.md"),
140
+ join2(cwd, "notes", "TODO.md"),
141
+ join2(cwd, "Notes", "TODO.md"),
142
+ join2(cwd, ".claude", "TODO.md")
143
+ ];
144
+ for (const path of localPaths) {
145
+ if (existsSync2(path)) return path;
146
+ }
147
+ return join2(getNotesDir(cwd), "TODO.md");
148
+ }
149
+
150
+ // src/hooks/ts/lib/project-utils/notify.ts
151
+ import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
152
+ import { join as join3 } from "path";
153
+ import { homedir as homedir2 } from "os";
110
154
  function isWhatsAppEnabled() {
111
155
  try {
112
- const settingsPath = join2(homedir2(), ".claude", "settings.json");
113
- if (!existsSync2(settingsPath)) return false;
156
+ const settingsPath = join3(homedir2(), ".claude", "settings.json");
157
+ if (!existsSync3(settingsPath)) return false;
114
158
  const settings = JSON.parse(readFileSync2(settingsPath, "utf-8"));
115
159
  const enabled = settings.enabledMcpjsonServers || [];
116
160
  return enabled.includes("aibroker") || enabled.includes("whazaa") || enabled.includes("telex");
@@ -154,81 +198,47 @@ async function sendNtfyNotification(message, retries = 2) {
154
198
  console.error("ntfy.sh notification failed after all retries");
155
199
  return false;
156
200
  }
157
- function ensureSessionsDirFromProjectDir(projectDir) {
158
- const sessionsDir = getSessionsDirFromProjectDir(projectDir);
159
- if (!existsSync2(sessionsDir)) {
160
- mkdirSync(sessionsDir, { recursive: true });
161
- console.error(`Created sessions directory: ${sessionsDir}`);
162
- }
163
- return sessionsDir;
164
- }
165
- function moveSessionFilesToSessionsDir(projectDir, excludeFile, silent = false) {
166
- const sessionsDir = ensureSessionsDirFromProjectDir(projectDir);
167
- if (!existsSync2(projectDir)) {
168
- return 0;
169
- }
170
- const files = readdirSync(projectDir);
171
- let movedCount = 0;
172
- for (const file of files) {
173
- if (file.endsWith(".jsonl") && file !== excludeFile) {
174
- const sourcePath = join2(projectDir, file);
175
- const destPath = join2(sessionsDir, file);
176
- try {
177
- renameSync(sourcePath, destPath);
178
- if (!silent) {
179
- console.error(`Moved ${file} \u2192 sessions/`);
180
- }
181
- movedCount++;
182
- } catch (error) {
183
- if (!silent) {
184
- console.error(`Could not move ${file}: ${error}`);
185
- }
186
- }
187
- }
188
- }
189
- return movedCount;
190
- }
201
+
202
+ // src/hooks/ts/lib/project-utils/session-notes.ts
203
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, readdirSync as readdirSync2, readFileSync as readFileSync3, writeFileSync, renameSync as renameSync2 } from "fs";
204
+ import { join as join4, basename as basename2 } from "path";
191
205
  function getCurrentNotePath(notesDir) {
192
- if (!existsSync2(notesDir)) {
193
- return null;
194
- }
206
+ if (!existsSync4(notesDir)) return null;
195
207
  const findLatestIn = (dir) => {
196
- if (!existsSync2(dir)) return null;
197
- const files = readdirSync(dir).filter((f) => f.match(/^\d{3,4}[\s_-].*\.md$/)).sort((a, b) => {
208
+ if (!existsSync4(dir)) return null;
209
+ const files = readdirSync2(dir).filter((f) => f.match(/^\d{3,4}[\s_-].*\.md$/)).sort((a, b) => {
198
210
  const numA = parseInt(a.match(/^(\d+)/)?.[1] || "0", 10);
199
211
  const numB = parseInt(b.match(/^(\d+)/)?.[1] || "0", 10);
200
212
  return numA - numB;
201
213
  });
202
214
  if (files.length === 0) return null;
203
- return join2(dir, files[files.length - 1]);
215
+ return join4(dir, files[files.length - 1]);
204
216
  };
205
217
  const now = /* @__PURE__ */ new Date();
206
218
  const year = String(now.getFullYear());
207
219
  const month = String(now.getMonth() + 1).padStart(2, "0");
208
- const currentMonthDir = join2(notesDir, year, month);
220
+ const currentMonthDir = join4(notesDir, year, month);
209
221
  const found = findLatestIn(currentMonthDir);
210
222
  if (found) return found;
211
223
  const prevDate = new Date(now.getFullYear(), now.getMonth() - 1, 1);
212
224
  const prevYear = String(prevDate.getFullYear());
213
225
  const prevMonth = String(prevDate.getMonth() + 1).padStart(2, "0");
214
- const prevMonthDir = join2(notesDir, prevYear, prevMonth);
226
+ const prevMonthDir = join4(notesDir, prevYear, prevMonth);
215
227
  const prevFound = findLatestIn(prevMonthDir);
216
228
  if (prevFound) return prevFound;
217
229
  return findLatestIn(notesDir);
218
230
  }
219
231
  function addWorkToSessionNote(notePath, workItems, sectionTitle) {
220
- if (!existsSync2(notePath)) {
232
+ if (!existsSync4(notePath)) {
221
233
  console.error(`Note file not found: ${notePath}`);
222
234
  return;
223
235
  }
224
- let content = readFileSync2(notePath, "utf-8");
236
+ let content = readFileSync3(notePath, "utf-8");
225
237
  let workText = "";
226
- if (sectionTitle) {
227
- workText += `
238
+ if (sectionTitle) workText += `
228
239
  ### ${sectionTitle}
229
240
 
230
241
  `;
231
- }
232
242
  for (const item of workItems) {
233
243
  const checkbox = item.completed !== false ? "[x]" : "[ ]";
234
244
  workText += `- ${checkbox} **${item.title}**
@@ -251,7 +261,7 @@ function addWorkToSessionNote(notePath, workItems, sectionTitle) {
251
261
  }
252
262
  }
253
263
  writeFileSync(notePath, content);
254
- console.error(`Added ${workItems.length} work item(s) to: ${basename(notePath)}`);
264
+ console.error(`Added ${workItems.length} work item(s) to: ${basename2(notePath)}`);
255
265
  }
256
266
  function sanitizeForFilename(str) {
257
267
  return str.toLowerCase().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").substring(0, 50);
@@ -275,40 +285,30 @@ function extractMeaningfulName(noteContent, summary) {
275
285
  }
276
286
  }
277
287
  const numberedItems = workDoneSection.match(/^\d+\.\s+\*\*([^*]+)\*\*/m);
278
- if (numberedItems) {
279
- return sanitizeForFilename(numberedItems[1]);
280
- }
288
+ if (numberedItems) return sanitizeForFilename(numberedItems[1]);
281
289
  }
282
290
  if (summary && summary.length > 5 && summary !== "Session completed.") {
283
291
  const cleanSummary = summary.replace(/[^\w\s-]/g, " ").trim().split(/\s+/).slice(0, 5).join(" ");
284
- if (cleanSummary.length > 3) {
285
- return sanitizeForFilename(cleanSummary);
286
- }
292
+ if (cleanSummary.length > 3) return sanitizeForFilename(cleanSummary);
287
293
  }
288
294
  return "";
289
295
  }
290
296
  function renameSessionNote(notePath, meaningfulName) {
291
- if (!meaningfulName || !existsSync2(notePath)) {
292
- return notePath;
293
- }
294
- const dir = join2(notePath, "..");
295
- const oldFilename = basename(notePath);
297
+ if (!meaningfulName || !existsSync4(notePath)) return notePath;
298
+ const dir = join4(notePath, "..");
299
+ const oldFilename = basename2(notePath);
296
300
  const correctMatch = oldFilename.match(/^(\d{3,4}) - (\d{4}-\d{2}-\d{2}) - .*\.md$/);
297
301
  const legacyMatch = oldFilename.match(/^(\d{3,4})_(\d{4}-\d{2}-\d{2})_.*\.md$/);
298
302
  const match = correctMatch || legacyMatch;
299
- if (!match) {
300
- return notePath;
301
- }
303
+ if (!match) return notePath;
302
304
  const [, noteNumber, date] = match;
303
305
  const titleCaseName = meaningfulName.split(/[\s_-]+/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ").trim();
304
306
  const paddedNumber = noteNumber.padStart(4, "0");
305
307
  const newFilename = `${paddedNumber} - ${date} - ${titleCaseName}.md`;
306
- const newPath = join2(dir, newFilename);
307
- if (newFilename === oldFilename) {
308
- return notePath;
309
- }
308
+ const newPath = join4(dir, newFilename);
309
+ if (newFilename === oldFilename) return notePath;
310
310
  try {
311
- renameSync(notePath, newPath);
311
+ renameSync2(notePath, newPath);
312
312
  console.error(`Renamed note: ${oldFilename} \u2192 ${newFilename}`);
313
313
  return newPath;
314
314
  } catch (error) {
@@ -317,13 +317,13 @@ function renameSessionNote(notePath, meaningfulName) {
317
317
  }
318
318
  }
319
319
  function finalizeSessionNote(notePath, summary) {
320
- if (!existsSync2(notePath)) {
320
+ if (!existsSync4(notePath)) {
321
321
  console.error(`Note file not found: ${notePath}`);
322
322
  return notePath;
323
323
  }
324
- let content = readFileSync2(notePath, "utf-8");
324
+ let content = readFileSync3(notePath, "utf-8");
325
325
  if (content.includes("**Status:** Completed")) {
326
- console.error(`Note already finalized: ${basename(notePath)}`);
326
+ console.error(`Note already finalized: ${basename2(notePath)}`);
327
327
  return notePath;
328
328
  }
329
329
  content = content.replace("**Status:** In Progress", "**Status:** Completed");
@@ -348,35 +348,22 @@ ${summary || "Session completed."}`
348
348
  );
349
349
  }
350
350
  writeFileSync(notePath, content);
351
- console.error(`Session note finalized: ${basename(notePath)}`);
351
+ console.error(`Session note finalized: ${basename2(notePath)}`);
352
352
  const meaningfulName = extractMeaningfulName(content, summary);
353
353
  if (meaningfulName) {
354
- const newPath = renameSessionNote(notePath, meaningfulName);
355
- return newPath;
354
+ return renameSessionNote(notePath, meaningfulName);
356
355
  }
357
356
  return notePath;
358
357
  }
359
- function findTodoPath(cwd) {
360
- const localPaths = [
361
- join2(cwd, "TODO.md"),
362
- join2(cwd, "notes", "TODO.md"),
363
- join2(cwd, "Notes", "TODO.md"),
364
- join2(cwd, ".claude", "TODO.md")
365
- ];
366
- for (const path of localPaths) {
367
- if (existsSync2(path)) {
368
- return path;
369
- }
370
- }
371
- return join2(getNotesDir(cwd), "TODO.md");
372
- }
358
+
359
+ // src/hooks/ts/lib/project-utils/todo.ts
360
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
361
+ import { join as join5 } from "path";
373
362
  function ensureTodoMd(cwd) {
374
363
  const todoPath = findTodoPath(cwd);
375
- if (!existsSync2(todoPath)) {
376
- const parentDir = join2(todoPath, "..");
377
- if (!existsSync2(parentDir)) {
378
- mkdirSync(parentDir, { recursive: true });
379
- }
364
+ if (!existsSync5(todoPath)) {
365
+ const parentDir = join5(todoPath, "..");
366
+ if (!existsSync5(parentDir)) mkdirSync3(parentDir, { recursive: true });
380
367
  const content = `# TODO
381
368
 
382
369
  ## Current Session
@@ -391,14 +378,14 @@ function ensureTodoMd(cwd) {
391
378
 
392
379
  *Last updated: ${(/* @__PURE__ */ new Date()).toISOString()}*
393
380
  `;
394
- writeFileSync(todoPath, content);
381
+ writeFileSync2(todoPath, content);
395
382
  console.error(`Created TODO.md: ${todoPath}`);
396
383
  }
397
384
  return todoPath;
398
385
  }
399
386
  function updateTodoContinue(cwd, noteFilename, state, tokenDisplay) {
400
387
  const todoPath = ensureTodoMd(cwd);
401
- let content = readFileSync2(todoPath, "utf-8");
388
+ let content = readFileSync4(todoPath, "utf-8");
402
389
  content = content.replace(/## Continue\n[\s\S]*?\n---\n+/, "");
403
390
  const now = (/* @__PURE__ */ new Date()).toISOString();
404
391
  const stateLines = state ? state.split("\n").filter((l) => l.trim()).slice(0, 10).map((l) => `> ${l}`).join("\n") : `> Working directory: ${cwd}. Check the latest session note for details.`;
@@ -426,7 +413,7 @@ ${stateLines}
426
413
 
427
414
  *Last updated: ${now}*
428
415
  `;
429
- writeFileSync(todoPath, content);
416
+ writeFileSync2(todoPath, content);
430
417
  console.error("TODO.md ## Continue section updated");
431
418
  }
432
419
 
@@ -578,7 +565,7 @@ STOP-HOOK TRIGGERED AT ${timestamp}`);
578
565
  }
579
566
  let transcript;
580
567
  try {
581
- transcript = readFileSync3(transcriptPath, "utf-8");
568
+ transcript = readFileSync5(transcriptPath, "utf-8");
582
569
  console.error(`Transcript loaded: ${transcript.split("\n").length} lines`);
583
570
  } catch (e) {
584
571
  console.error(`Error reading transcript: ${e}`);
@@ -681,7 +668,7 @@ STOP-HOOK TRIGGERED AT ${timestamp}`);
681
668
  }
682
669
  const summary = message || "Session completed.";
683
670
  finalizeSessionNote(currentNotePath, summary);
684
- console.error(`Session note finalized: ${basename2(currentNotePath)}`);
671
+ console.error(`Session note finalized: ${basename3(currentNotePath)}`);
685
672
  try {
686
673
  const stateLines = [];
687
674
  stateLines.push(`Working directory: ${cwd}`);
@@ -697,7 +684,7 @@ STOP-HOOK TRIGGERED AT ${timestamp}`);
697
684
  stateLines.push(`Last completed: ${message}`);
698
685
  }
699
686
  const state = stateLines.join("\n");
700
- updateTodoContinue(cwd, basename2(currentNotePath), state, "session-end");
687
+ updateTodoContinue(cwd, basename3(currentNotePath), state, "session-end");
701
688
  } catch (todoError) {
702
689
  console.error(`Could not update TODO.md: ${todoError}`);
703
690
  }