@clauderecallhq/cli 0.12.5 → 0.61.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.
Files changed (218) hide show
  1. package/LICENSE +37 -17
  2. package/README.md +110 -22
  3. package/dist/cli.js +1641 -353
  4. package/dist/daemon/entrypoint.js +1872 -54
  5. package/dist/mcp-server.js +930 -0
  6. package/dist/share/fonts/Inter-Bold.woff +0 -0
  7. package/dist/share/fonts/Inter-Regular.woff +0 -0
  8. package/dist/share/fonts/JetBrainsMono-Regular.woff +0 -0
  9. package/dist/web/assets/_brand-Bw9uSB4O.js +1 -0
  10. package/dist/web/assets/captureNode-9CVj9vYC.js +2 -0
  11. package/dist/web/assets/card-a-minimal-ujNERzX7.js +1 -0
  12. package/dist/web/assets/card-b-terminal-DpJ_tVpg.js +1 -0
  13. package/dist/web/assets/card-c-gradient-CZXVGuNd.js +1 -0
  14. package/dist/web/assets/card-d-dashboard-CHKD-PnB.js +1 -0
  15. package/dist/web/assets/dist-CWaokT35.js +56 -0
  16. package/dist/web/assets/index-B-HrjaDy.css +1 -0
  17. package/dist/web/assets/index-BZYcD76T.js +633 -0
  18. package/dist/web/assets/jetbrains-mono-latin-700-normal-D3wTyLJW.woff +0 -0
  19. package/dist/web/assets/patterns-BPeZb9N0.js +1 -0
  20. package/dist/web/assets/stats-BSwqSiFU.js +1 -0
  21. package/dist/web/assets/thread-D2AXyhOx.js +1 -0
  22. package/dist/web/index.html +8 -2
  23. package/package.json +56 -16
  24. package/scripts/postinstall.mjs +38 -0
  25. package/dist/cli.js.map +0 -1
  26. package/dist/commands/activate.js +0 -69
  27. package/dist/commands/activate.js.map +0 -1
  28. package/dist/commands/audit-secrets.js +0 -103
  29. package/dist/commands/audit-secrets.js.map +0 -1
  30. package/dist/commands/blame.js +0 -35
  31. package/dist/commands/blame.js.map +0 -1
  32. package/dist/commands/config-verification.js +0 -18
  33. package/dist/commands/config-verification.js.map +0 -1
  34. package/dist/commands/context.js +0 -144
  35. package/dist/commands/context.js.map +0 -1
  36. package/dist/commands/correlate.js +0 -70
  37. package/dist/commands/correlate.js.map +0 -1
  38. package/dist/commands/digest.js +0 -78
  39. package/dist/commands/digest.js.map +0 -1
  40. package/dist/commands/health.js +0 -62
  41. package/dist/commands/health.js.map +0 -1
  42. package/dist/commands/index.js +0 -247
  43. package/dist/commands/index.js.map +0 -1
  44. package/dist/commands/install-extension.js +0 -138
  45. package/dist/commands/install-extension.js.map +0 -1
  46. package/dist/commands/license.js +0 -39
  47. package/dist/commands/license.js.map +0 -1
  48. package/dist/commands/list.js +0 -47
  49. package/dist/commands/list.js.map +0 -1
  50. package/dist/commands/mcp.js +0 -29
  51. package/dist/commands/mcp.js.map +0 -1
  52. package/dist/commands/open.js +0 -28
  53. package/dist/commands/open.js.map +0 -1
  54. package/dist/commands/paste.js +0 -154
  55. package/dist/commands/paste.js.map +0 -1
  56. package/dist/commands/projects.js +0 -36
  57. package/dist/commands/projects.js.map +0 -1
  58. package/dist/commands/search.js +0 -67
  59. package/dist/commands/search.js.map +0 -1
  60. package/dist/commands/semantic.js +0 -173
  61. package/dist/commands/semantic.js.map +0 -1
  62. package/dist/commands/show.js +0 -121
  63. package/dist/commands/show.js.map +0 -1
  64. package/dist/commands/start.js +0 -47
  65. package/dist/commands/start.js.map +0 -1
  66. package/dist/commands/stats.js +0 -133
  67. package/dist/commands/stats.js.map +0 -1
  68. package/dist/commands/status.js +0 -45
  69. package/dist/commands/status.js.map +0 -1
  70. package/dist/commands/stop.js +0 -29
  71. package/dist/commands/stop.js.map +0 -1
  72. package/dist/commands/thread.js +0 -396
  73. package/dist/commands/thread.js.map +0 -1
  74. package/dist/context/formatter.js +0 -103
  75. package/dist/context/formatter.js.map +0 -1
  76. package/dist/daemon/auto-tag-config.js +0 -103
  77. package/dist/daemon/auto-tag-config.js.map +0 -1
  78. package/dist/daemon/auto-tag-config.test.js +0 -72
  79. package/dist/daemon/auto-tag-config.test.js.map +0 -1
  80. package/dist/daemon/auto-title-config.js +0 -70
  81. package/dist/daemon/auto-title-config.js.map +0 -1
  82. package/dist/daemon/bulk-title-jobs.js +0 -170
  83. package/dist/daemon/bulk-title-jobs.js.map +0 -1
  84. package/dist/daemon/correlator.js +0 -320
  85. package/dist/daemon/correlator.js.map +0 -1
  86. package/dist/daemon/discover.js +0 -316
  87. package/dist/daemon/discover.js.map +0 -1
  88. package/dist/daemon/editor-detection.js +0 -186
  89. package/dist/daemon/editor-detection.js.map +0 -1
  90. package/dist/daemon/entrypoint.js.map +0 -1
  91. package/dist/daemon/git-correlator.js +0 -256
  92. package/dist/daemon/git-correlator.js.map +0 -1
  93. package/dist/daemon/mcp-installer.js +0 -108
  94. package/dist/daemon/mcp-installer.js.map +0 -1
  95. package/dist/daemon/onboarding-state.js +0 -140
  96. package/dist/daemon/onboarding-state.js.map +0 -1
  97. package/dist/daemon/pidfile.js +0 -57
  98. package/dist/daemon/pidfile.js.map +0 -1
  99. package/dist/daemon/ports.js +0 -48
  100. package/dist/daemon/ports.js.map +0 -1
  101. package/dist/daemon/scanProgressRegistry.js +0 -62
  102. package/dist/daemon/scanProgressRegistry.js.map +0 -1
  103. package/dist/daemon/server.js +0 -2010
  104. package/dist/daemon/server.js.map +0 -1
  105. package/dist/daemon/tag-scanner/anthropic-client.js +0 -40
  106. package/dist/daemon/tag-scanner/anthropic-client.js.map +0 -1
  107. package/dist/daemon/tag-scanner/autopilot.js +0 -131
  108. package/dist/daemon/tag-scanner/autopilot.js.map +0 -1
  109. package/dist/daemon/tag-scanner/claude-cli-driver.js +0 -250
  110. package/dist/daemon/tag-scanner/claude-cli-driver.js.map +0 -1
  111. package/dist/daemon/tag-scanner/orchestrator.js +0 -88
  112. package/dist/daemon/tag-scanner/orchestrator.js.map +0 -1
  113. package/dist/daemon/tag-scanner/prompt.js +0 -46
  114. package/dist/daemon/tag-scanner/prompt.js.map +0 -1
  115. package/dist/daemon/tag-scanner/prompt.test.js +0 -48
  116. package/dist/daemon/tag-scanner/prompt.test.js.map +0 -1
  117. package/dist/daemon/tag-scanner/scan-state.js +0 -49
  118. package/dist/daemon/tag-scanner/scan-state.js.map +0 -1
  119. package/dist/daemon/tag-scanner/session-fetcher.js +0 -82
  120. package/dist/daemon/tag-scanner/session-fetcher.js.map +0 -1
  121. package/dist/daemon/tag-scanner/session-fetcher.test.js +0 -34
  122. package/dist/daemon/tag-scanner/session-fetcher.test.js.map +0 -1
  123. package/dist/daemon/tag-scanner/validator.js +0 -50
  124. package/dist/daemon/tag-scanner/validator.js.map +0 -1
  125. package/dist/daemon/tag-scanner/validator.test.js +0 -41
  126. package/dist/daemon/tag-scanner/validator.test.js.map +0 -1
  127. package/dist/daemon/terminal-registry.js +0 -443
  128. package/dist/daemon/terminal-registry.js.map +0 -1
  129. package/dist/daemon/ui.js +0 -64
  130. package/dist/daemon/ui.js.map +0 -1
  131. package/dist/daemon/watcher.js +0 -256
  132. package/dist/daemon/watcher.js.map +0 -1
  133. package/dist/db/client.js +0 -22
  134. package/dist/db/client.js.map +0 -1
  135. package/dist/db/schema.js +0 -496
  136. package/dist/db/schema.js.map +0 -1
  137. package/dist/license/api-base.js +0 -13
  138. package/dist/license/api-base.js.map +0 -1
  139. package/dist/license/manager.js +0 -43
  140. package/dist/license/manager.js.map +0 -1
  141. package/dist/license/public-key.js +0 -19
  142. package/dist/license/public-key.js.map +0 -1
  143. package/dist/license/storage.js +0 -27
  144. package/dist/license/storage.js.map +0 -1
  145. package/dist/license/verify.js +0 -23
  146. package/dist/license/verify.js.map +0 -1
  147. package/dist/mcp/audit.js +0 -126
  148. package/dist/mcp/audit.js.map +0 -1
  149. package/dist/mcp/prompts.js +0 -180
  150. package/dist/mcp/prompts.js.map +0 -1
  151. package/dist/mcp/server.js +0 -502
  152. package/dist/mcp/server.js.map +0 -1
  153. package/dist/mcp/thread-tools.js +0 -363
  154. package/dist/mcp/thread-tools.js.map +0 -1
  155. package/dist/mcp/write-tools.js +0 -239
  156. package/dist/mcp/write-tools.js.map +0 -1
  157. package/dist/parser/jsonl.js +0 -150
  158. package/dist/parser/jsonl.js.map +0 -1
  159. package/dist/semantic/chunker.js +0 -47
  160. package/dist/semantic/chunker.js.map +0 -1
  161. package/dist/semantic/config.js +0 -74
  162. package/dist/semantic/config.js.map +0 -1
  163. package/dist/semantic/embedder.js +0 -54
  164. package/dist/semantic/embedder.js.map +0 -1
  165. package/dist/semantic/fusion.js +0 -38
  166. package/dist/semantic/fusion.js.map +0 -1
  167. package/dist/semantic/model-download.js +0 -69
  168. package/dist/semantic/model-download.js.map +0 -1
  169. package/dist/semantic/pipeline.js +0 -375
  170. package/dist/semantic/pipeline.js.map +0 -1
  171. package/dist/semantic/query.js +0 -42
  172. package/dist/semantic/query.js.map +0 -1
  173. package/dist/semantic/worker.js +0 -78
  174. package/dist/semantic/worker.js.map +0 -1
  175. package/dist/stats/backfill.js +0 -151
  176. package/dist/stats/backfill.js.map +0 -1
  177. package/dist/stats/health.js +0 -102
  178. package/dist/stats/health.js.map +0 -1
  179. package/dist/stats/query.js +0 -385
  180. package/dist/stats/query.js.map +0 -1
  181. package/dist/utils/aliases.js +0 -107
  182. package/dist/utils/aliases.js.map +0 -1
  183. package/dist/utils/autoCollections.js +0 -635
  184. package/dist/utils/autoCollections.js.map +0 -1
  185. package/dist/utils/autoTitle.js +0 -348
  186. package/dist/utils/autoTitle.js.map +0 -1
  187. package/dist/utils/collections.js +0 -446
  188. package/dist/utils/collections.js.map +0 -1
  189. package/dist/utils/format.js +0 -46
  190. package/dist/utils/format.js.map +0 -1
  191. package/dist/utils/notes.js +0 -270
  192. package/dist/utils/notes.js.map +0 -1
  193. package/dist/utils/paths.js +0 -50
  194. package/dist/utils/paths.js.map +0 -1
  195. package/dist/utils/pricing.js +0 -257
  196. package/dist/utils/pricing.js.map +0 -1
  197. package/dist/utils/secret-scanner.js +0 -166
  198. package/dist/utils/secret-scanner.js.map +0 -1
  199. package/dist/utils/sessionLabel.js +0 -64
  200. package/dist/utils/sessionLabel.js.map +0 -1
  201. package/dist/utils/tags.js +0 -97
  202. package/dist/utils/tags.js.map +0 -1
  203. package/dist/utils/thread-context.js +0 -129
  204. package/dist/utils/thread-context.js.map +0 -1
  205. package/dist/utils/threadFilter.js +0 -18
  206. package/dist/utils/threadFilter.js.map +0 -1
  207. package/dist/utils/threads-titler.js +0 -298
  208. package/dist/utils/threads-titler.js.map +0 -1
  209. package/dist/utils/threads.js +0 -383
  210. package/dist/utils/threads.js.map +0 -1
  211. package/dist/utils/usage.js +0 -76
  212. package/dist/utils/usage.js.map +0 -1
  213. package/dist/verification/compute.js +0 -88
  214. package/dist/verification/compute.js.map +0 -1
  215. package/dist/verification/config.js +0 -34
  216. package/dist/verification/config.js.map +0 -1
  217. package/dist/web/assets/index-CIr6J4Fw.js +0 -1201
  218. package/dist/web/assets/index-Ctc8g9Jw.css +0 -1
@@ -1,88 +0,0 @@
1
- import { allTagsWithCounts, addTag } from '../../utils/tags.js';
2
- import { buildTagPrompt } from './prompt.js';
3
- import { parseScanResponse } from './validator.js';
4
- import { callAnthropic, withRetry } from './anthropic-client.js';
5
- import { emit } from './scan-state.js';
6
- /**
7
- * Run the scan in the background. Safe to call and not await — the scan
8
- * updates its own `rec` object. The caller subscribes via `subscribe()` for
9
- * progress events.
10
- */
11
- export async function runScan(rec, opts) {
12
- rec.status = 'running';
13
- emit(rec, { type: 'status', status: 'running' });
14
- const knownTags = allTagsWithCounts();
15
- for (const session of opts.sessions) {
16
- if (rec.controller.signal.aborted)
17
- break;
18
- const prompt = buildTagPrompt({
19
- session,
20
- knownTags,
21
- minTags: opts.minTags,
22
- maxTags: opts.maxTags,
23
- });
24
- const baseResult = {
25
- sessionId: session.id,
26
- project: session.project,
27
- alias: session.alias,
28
- first_user_message: session.first_user_message,
29
- current_tags: session.current_tags,
30
- suggestion: null,
31
- error: null,
32
- applied: false,
33
- };
34
- try {
35
- const raw = await withRetry(() => callAnthropic({
36
- apiKey: opts.apiKey,
37
- model: opts.model,
38
- prompt,
39
- signal: rec.controller.signal,
40
- }));
41
- const parsed = parseScanResponse(raw, { maxTags: opts.maxTags });
42
- if (parsed.ok) {
43
- baseResult.suggestion = parsed.data;
44
- }
45
- else {
46
- baseResult.error = parsed.reason;
47
- }
48
- }
49
- catch (err) {
50
- baseResult.error = err instanceof Error ? err.message : String(err);
51
- }
52
- rec.results.push(baseResult);
53
- rec.completed += 1;
54
- emit(rec, { type: 'result', result: baseResult });
55
- emit(rec, { type: 'progress', completed: rec.completed, total: rec.total });
56
- }
57
- if (!rec.controller.signal.aborted) {
58
- rec.status = 'completed';
59
- rec.finishedAt = new Date().toISOString();
60
- const ok = rec.results.filter((r) => r.suggestion && !r.error).length;
61
- const failed = rec.results.filter((r) => r.error).length;
62
- emit(rec, { type: 'done', summary: { ok, failed } });
63
- }
64
- }
65
- /** Apply selected tag suggestions from a completed scan. */
66
- export function applyScanSelection(rec, selection) {
67
- let applied = 0;
68
- let failed = 0;
69
- for (const item of selection) {
70
- const result = rec.results.find((r) => r.sessionId === item.sessionId);
71
- if (!result)
72
- continue;
73
- for (const tag of item.tags) {
74
- try {
75
- const { added } = addTag(item.sessionId, tag);
76
- if (added)
77
- applied += 1;
78
- }
79
- catch (err) {
80
- console.error('[scanner] apply failed:', item.sessionId, tag, err);
81
- failed += 1;
82
- }
83
- }
84
- result.applied = true;
85
- }
86
- return { applied, failed };
87
- }
88
- //# sourceMappingURL=orchestrator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../../src/daemon/tag-scanner/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -1,46 +0,0 @@
1
- /**
2
- * Produce a stable prompt. Known-tags list is truncated to 50 entries and
3
- * sorted by count desc (already sorted by `allTagsWithCounts`).
4
- */
5
- export function buildTagPrompt(input) {
6
- const { session, knownTags, minTags, maxTags } = input;
7
- const topTags = knownTags
8
- .slice(0, 50)
9
- .map((t) => t.tag)
10
- .join(', ');
11
- const currentTagsLine = session.current_tags.length > 0
12
- ? `already applied, do not repeat: [${session.current_tags.join(', ')}]`
13
- : 'currently has no tags';
14
- return [
15
- `You are tagging a software engineering session. Produce ${minTags}-${maxTags} concise, lowercase, hyphen-separated tags that describe:`,
16
- ' - the domain or subsystem touched (auth, db, frontend, ...)',
17
- ' - the kind of work (bugfix, feature, refactor, research, ...)',
18
- ' - any specific tool, library, or product if prominent',
19
- '',
20
- 'Prefer tags from the known-tags list below when applicable — consistency over creativity. Never invent marketing-sounding labels. Never tag based on speculation; only on observed work.',
21
- '',
22
- `known tags (most used first, up to 50): ${topTags || '(none yet)'}`,
23
- '',
24
- 'Session:',
25
- ` project: ${session.project}`,
26
- session.alias ? ` alias: ${JSON.stringify(session.alias)}` : ' alias: (none)',
27
- session.git_branch ? ` git_branch: ${session.git_branch}` : '',
28
- ` ${currentTagsLine}`,
29
- ' first_user_message:',
30
- indent(session.first_user_message, ' '),
31
- ' message_sample:',
32
- indent(session.message_sample, ' '),
33
- '',
34
- `Return a single JSON object matching this schema exactly, with no prose before or after:`,
35
- `{"tags": string[] length ${minTags}-${maxTags}, "confidence": number 0-1, "rationale": string one short sentence}`,
36
- ]
37
- .filter(Boolean)
38
- .join('\n');
39
- }
40
- function indent(text, prefix) {
41
- return text
42
- .split('\n')
43
- .map((line) => prefix + line)
44
- .join('\n');
45
- }
46
- //# sourceMappingURL=prompt.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../src/daemon/tag-scanner/prompt.ts"],"names":[],"mappings":"AAuBA;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,KAAkB;IAC/C,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IACvD,MAAM,OAAO,GAAG,SAAS;SACtB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;SACjB,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,eAAe,GACnB,OAAO,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;QAC7B,CAAC,CAAC,oCAAoC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;QACxE,CAAC,CAAC,uBAAuB,CAAC;IAE9B,OAAO;QACL,2DAA2D,OAAO,IAAI,OAAO,2DAA2D;QACxI,+DAA+D;QAC/D,iEAAiE;QACjE,yDAAyD;QACzD,EAAE;QACF,0LAA0L;QAC1L,EAAE;QACF,2CAA2C,OAAO,IAAI,YAAY,EAAE;QACpE,EAAE;QACF,UAAU;QACV,cAAc,OAAO,CAAC,OAAO,EAAE;QAC/B,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB;QAC/E,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,iBAAiB,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE;QAC/D,KAAK,eAAe,EAAE;QACtB,uBAAuB;QACvB,MAAM,CAAC,OAAO,CAAC,kBAAkB,EAAE,MAAM,CAAC;QAC1C,mBAAmB;QACnB,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC;QACtC,EAAE;QACF,0FAA0F;QAC1F,4BAA4B,OAAO,IAAI,OAAO,qEAAqE;KACpH;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,SAAS,MAAM,CAAC,IAAY,EAAE,MAAc;IAC1C,OAAO,IAAI;SACR,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC;SAC5B,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
@@ -1,48 +0,0 @@
1
- import { describe, it } from 'node:test';
2
- import assert from 'node:assert/strict';
3
- describe('buildTagPrompt', () => {
4
- it('includes known tags sorted by popularity', async () => {
5
- const { buildTagPrompt } = await import('./prompt.js');
6
- const out = buildTagPrompt({
7
- session: {
8
- id: 'abc',
9
- alias: null,
10
- project: 'demo',
11
- git_branch: 'main',
12
- first_user_message: 'fix the auth bug',
13
- message_sample: 'system: ...\nuser: fix the auth bug',
14
- current_tags: [],
15
- },
16
- knownTags: [
17
- { tag: 'auth', count: 42 },
18
- { tag: 'feature', count: 10 },
19
- ],
20
- minTags: 2,
21
- maxTags: 4,
22
- });
23
- assert.ok(out.includes('known tags'), 'output should mention known tags');
24
- assert.ok(out.indexOf('auth') < out.indexOf('feature'), 'auth should come before feature');
25
- assert.ok(out.includes('2-4'), 'output should mention 2-4 range');
26
- assert.ok(out.includes('fix the auth bug'), 'output should include first user message');
27
- });
28
- it('mentions current_tags as "already applied, do not repeat"', async () => {
29
- const { buildTagPrompt } = await import('./prompt.js');
30
- const out = buildTagPrompt({
31
- session: {
32
- id: 'x',
33
- alias: 'webhook retry',
34
- project: 'api',
35
- git_branch: null,
36
- first_user_message: 'add exp backoff to webhook delivery',
37
- message_sample: 'user: ...',
38
- current_tags: ['webhook'],
39
- },
40
- knownTags: [],
41
- minTags: 2,
42
- maxTags: 4,
43
- });
44
- assert.match(out, /already applied/i);
45
- assert.ok(out.includes('webhook'), 'output should include the existing tag');
46
- });
47
- });
48
- //# sourceMappingURL=prompt.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prompt.test.js","sourceRoot":"","sources":["../../../src/daemon/tag-scanner/prompt.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACvD,MAAM,GAAG,GAAG,cAAc,CAAC;YACzB,OAAO,EAAE;gBACP,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,IAAI;gBACX,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,MAAM;gBAClB,kBAAkB,EAAE,kBAAkB;gBACtC,cAAc,EAAE,qCAAqC;gBACrD,YAAY,EAAE,EAAE;aACjB;YACD,SAAS,EAAE;gBACT,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;gBAC1B,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE;aAC9B;YACD,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,CAAC;SACX,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,kCAAkC,CAAC,CAAC;QAC1E,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,iCAAiC,CAAC,CAAC;QAC3F,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,iCAAiC,CAAC,CAAC;QAClE,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,0CAA0C,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACvD,MAAM,GAAG,GAAG,cAAc,CAAC;YACzB,OAAO,EAAE;gBACP,EAAE,EAAE,GAAG;gBACP,KAAK,EAAE,eAAe;gBACtB,OAAO,EAAE,KAAK;gBACd,UAAU,EAAE,IAAI;gBAChB,kBAAkB,EAAE,qCAAqC;gBACzD,cAAc,EAAE,WAAW;gBAC3B,YAAY,EAAE,CAAC,SAAS,CAAC;aAC1B;YACD,SAAS,EAAE,EAAE;YACb,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,CAAC;SACX,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;QACtC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,wCAAwC,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,49 +0,0 @@
1
- import { randomUUID } from 'node:crypto';
2
- const scans = new Map();
3
- export function createScan(total) {
4
- const rec = {
5
- id: randomUUID(),
6
- status: 'pending',
7
- createdAt: new Date().toISOString(),
8
- finishedAt: null,
9
- total,
10
- completed: 0,
11
- results: [],
12
- error: null,
13
- controller: new AbortController(),
14
- listeners: new Set(),
15
- };
16
- scans.set(rec.id, rec);
17
- return rec;
18
- }
19
- export function getScan(id) {
20
- return scans.get(id);
21
- }
22
- export function emit(rec, ev) {
23
- for (const l of rec.listeners)
24
- l(ev);
25
- }
26
- export function subscribe(rec, listener) {
27
- rec.listeners.add(listener);
28
- return () => {
29
- rec.listeners.delete(listener);
30
- };
31
- }
32
- export function cancelScan(id) {
33
- const rec = scans.get(id);
34
- if (!rec)
35
- return false;
36
- rec.controller.abort();
37
- rec.status = 'cancelled';
38
- rec.finishedAt = new Date().toISOString();
39
- emit(rec, { type: 'status', status: 'cancelled' });
40
- return true;
41
- }
42
- export function deleteScan(id) {
43
- return scans.delete(id);
44
- }
45
- /** Used in tests — clears all scans. */
46
- export function clearScansForTest() {
47
- scans.clear();
48
- }
49
- //# sourceMappingURL=scan-state.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scan-state.js","sourceRoot":"","sources":["../../../src/daemon/tag-scanner/scan-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAmCzC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;AAE5C,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,MAAM,GAAG,GAAe;QACtB,EAAE,EAAE,UAAU,EAAE;QAChB,MAAM,EAAE,SAAS;QACjB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,UAAU,EAAE,IAAI;QAChB,KAAK;QACL,SAAS,EAAE,CAAC;QACZ,OAAO,EAAE,EAAE;QACX,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,IAAI,eAAe,EAAE;QACjC,SAAS,EAAE,IAAI,GAAG,EAAE;KACrB,CAAC;IACF,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACvB,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,EAAU;IAChC,OAAO,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,GAAe,EAAE,EAAa;IACjD,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,SAAS;QAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAe,EAAE,QAAiC;IAC1E,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC5B,OAAO,GAAG,EAAE;QACV,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAU;IACnC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1B,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACvB,GAAG,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IACvB,GAAG,CAAC,MAAM,GAAG,WAAW,CAAC;IACzB,GAAG,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC1C,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACnD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAU;IACnC,OAAO,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC1B,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,iBAAiB;IAC/B,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC"}
@@ -1,82 +0,0 @@
1
- import { getDb } from '../../db/client.js';
2
- import { tagsForSession } from '../../utils/tags.js';
3
- /**
4
- * Deterministically pick up to `target` messages from `msgs`, skipping any
5
- * with empty content. When the pool is larger than the target, always keep
6
- * the first and last and spread the remainder evenly across the middle.
7
- */
8
- export function sampleMessages(msgs, target) {
9
- const nonEmpty = msgs.filter((m) => m.content_text && m.content_text.trim().length > 0);
10
- if (nonEmpty.length <= target)
11
- return nonEmpty;
12
- const picks = new Set();
13
- picks.add(0);
14
- picks.add(nonEmpty.length - 1);
15
- const stride = (nonEmpty.length - 2) / Math.max(1, target - 2);
16
- for (let i = 1; i < target - 1; i++) {
17
- picks.add(Math.floor(i * stride));
18
- }
19
- return Array.from(picks)
20
- .sort((a, b) => a - b)
21
- .slice(0, target)
22
- .map((i) => nonEmpty[i]);
23
- }
24
- export function listSessionsForScan(filter) {
25
- const db = getDb();
26
- const params = { limit: filter.limit ?? 500 };
27
- // When caller passes explicit sessionIds, skip the message-count gate —
28
- // the user has already decided which session to scan.
29
- const hasExplicitIds = filter.sessionIds && filter.sessionIds.length > 0;
30
- let where = hasExplicitIds ? '1=1' : 's.message_count > 2';
31
- if (hasExplicitIds) {
32
- const placeholders = filter.sessionIds.map((_, i) => `@sid_${i}`).join(', ');
33
- where += ` AND s.id IN (${placeholders})`;
34
- filter.sessionIds.forEach((id, i) => {
35
- params[`sid_${i}`] = id;
36
- });
37
- }
38
- if (filter.untaggedOnly) {
39
- where += ' AND NOT EXISTS (SELECT 1 FROM session_tags st WHERE st.session_id = s.id)';
40
- }
41
- if (filter.project) {
42
- where += ' AND p.name = @project';
43
- params.project = filter.project;
44
- }
45
- if (filter.collectionId) {
46
- where +=
47
- ' AND s.id IN (SELECT session_id FROM collection_sessions WHERE collection_id = @col)';
48
- params.col = filter.collectionId;
49
- }
50
- const sessions = db
51
- .prepare(`SELECT s.id, p.name AS project, s.git_branch,
52
- NULLIF(sa.alias, '') AS alias,
53
- COALESCE(s.first_user_message, '') AS first_user_message
54
- FROM sessions s
55
- JOIN projects p ON p.id = s.project_id
56
- LEFT JOIN session_aliases sa ON sa.session_id = s.id
57
- WHERE ${where}
58
- ORDER BY COALESCE(s.started_at, '') DESC
59
- LIMIT @limit`)
60
- .all(params);
61
- return sessions.map((s) => {
62
- const msgs = db
63
- .prepare(`SELECT role, COALESCE(content_text, '') AS content_text
64
- FROM messages WHERE session_id = ?
65
- ORDER BY COALESCE(timestamp, ''), rowid`)
66
- .all(s.id);
67
- const sampled = sampleMessages(msgs, 5);
68
- const messageSample = sampled
69
- .map((m) => `${m.role}: ${m.content_text.slice(0, 400)}`)
70
- .join('\n---\n');
71
- return {
72
- id: s.id,
73
- project: s.project,
74
- git_branch: s.git_branch,
75
- alias: s.alias,
76
- first_user_message: s.first_user_message,
77
- message_sample: messageSample,
78
- current_tags: tagsForSession(s.id),
79
- };
80
- });
81
- }
82
- //# sourceMappingURL=session-fetcher.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"session-fetcher.js","sourceRoot":"","sources":["../../../src/daemon/tag-scanner/session-fetcher.ts"],"names":[],"mappings":"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"}
@@ -1,34 +0,0 @@
1
- import { describe, it } from 'node:test';
2
- import assert from 'node:assert/strict';
3
- describe('sampleMessages', () => {
4
- it('returns all messages if there are fewer than targetCount', async () => {
5
- const { sampleMessages } = await import('./session-fetcher.js');
6
- const msgs = [
7
- { role: 'user', content_text: 'one' },
8
- { role: 'assistant', content_text: 'two' },
9
- ];
10
- const out = sampleMessages(msgs, 5);
11
- assert.equal(out.length, 2);
12
- });
13
- it('picks first, middle, last when count exceeds target', async () => {
14
- const { sampleMessages } = await import('./session-fetcher.js');
15
- const msgs = Array.from({ length: 20 }, (_, i) => ({
16
- role: 'user',
17
- content_text: `msg-${i}`,
18
- }));
19
- const out = sampleMessages(msgs, 3);
20
- assert.equal(out[0].content_text, 'msg-0');
21
- assert.equal(out[out.length - 1].content_text, 'msg-19');
22
- assert.equal(out.length, 3);
23
- });
24
- it('skips empty content', async () => {
25
- const { sampleMessages } = await import('./session-fetcher.js');
26
- const msgs = [
27
- { role: 'user', content_text: '' },
28
- { role: 'user', content_text: 'real' },
29
- ];
30
- const out = sampleMessages(msgs, 5);
31
- assert.equal(out.length, 1);
32
- });
33
- });
34
- //# sourceMappingURL=session-fetcher.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"session-fetcher.test.js","sourceRoot":"","sources":["../../../src/daemon/tag-scanner/session-fetcher.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG;YACX,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE;YACrC,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,EAAE;SAC3C,CAAC;QACF,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YACjD,IAAI,EAAE,MAAe;YACrB,YAAY,EAAE,OAAO,CAAC,EAAE;SACzB,CAAC,CAAC,CAAC;QACJ,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QACzD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,KAAK,IAAI,EAAE;QACnC,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG;YACX,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE;YAClC,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE;SACvC,CAAC;QACF,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,50 +0,0 @@
1
- import { z } from 'zod';
2
- import { normalizeTag } from '../../utils/tags.js';
3
- const RawSchema = z.object({
4
- tags: z.array(z.string()).min(1),
5
- confidence: z.number().min(0).max(1),
6
- rationale: z.string().min(1).max(500),
7
- });
8
- /** Strip common wrappers LLMs like to add around JSON. */
9
- function stripFences(raw) {
10
- const trimmed = raw.trim();
11
- if (!trimmed.startsWith('```'))
12
- return trimmed;
13
- return trimmed
14
- .replace(/^```(?:json)?\s*/i, '')
15
- .replace(/```$/i, '')
16
- .trim();
17
- }
18
- export function parseScanResponse(raw, opts = {}) {
19
- const maxTags = opts.maxTags ?? 10;
20
- let obj;
21
- try {
22
- obj = JSON.parse(stripFences(raw));
23
- }
24
- catch {
25
- return { ok: false, reason: 'not valid JSON' };
26
- }
27
- const parsed = RawSchema.safeParse(obj);
28
- if (!parsed.success) {
29
- return {
30
- ok: false,
31
- reason: parsed.error.issues.map((i) => i.message).join('; '),
32
- };
33
- }
34
- const normalized = parsed.data.tags
35
- .map((t) => normalizeTag(t))
36
- .filter((t) => t.length > 0);
37
- const unique = Array.from(new Set(normalized)).slice(0, maxTags);
38
- if (unique.length === 0) {
39
- return { ok: false, reason: 'no usable tags after normalization' };
40
- }
41
- return {
42
- ok: true,
43
- data: {
44
- tags: unique,
45
- confidence: parsed.data.confidence,
46
- rationale: parsed.data.rationale,
47
- },
48
- };
49
- }
50
- //# sourceMappingURL=validator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../../src/daemon/tag-scanner/validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC;IACzB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;CACtC,CAAC,CAAC;AAYH,0DAA0D;AAC1D,SAAS,WAAW,CAAC,GAAW;IAC9B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IAC/C,OAAO,OAAO;SACX,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC;SAChC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,GAAW,EACX,OAA6B,EAAE;IAE/B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IACnC,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACjD,CAAC;IACD,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;SAC7D,CAAC;IACJ,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI;SAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;SAC3B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACjE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,oCAAoC,EAAE,CAAC;IACrE,CAAC;IACD,OAAO;QACL,EAAE,EAAE,IAAI;QACR,IAAI,EAAE;YACJ,IAAI,EAAE,MAAM;YACZ,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU;YAClC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS;SACjC;KACF,CAAC;AACJ,CAAC"}
@@ -1,41 +0,0 @@
1
- import { describe, it } from 'node:test';
2
- import assert from 'node:assert/strict';
3
- describe('parseScanResponse', () => {
4
- it('accepts valid JSON payload', async () => {
5
- const { parseScanResponse } = await import('./validator.js');
6
- const r = parseScanResponse('{"tags":["auth","bugfix"],"confidence":0.9,"rationale":"middleware fix"}');
7
- assert.equal(r.ok, true);
8
- if (r.ok)
9
- assert.deepEqual(r.data.tags, ['auth', 'bugfix']);
10
- });
11
- it('strips markdown code fences', async () => {
12
- const { parseScanResponse } = await import('./validator.js');
13
- const r = parseScanResponse('```json\n{"tags":["x","y"],"confidence":0.5,"rationale":"test"}\n```');
14
- assert.equal(r.ok, true);
15
- });
16
- it('normalizes tags via normalizeTag', async () => {
17
- const { parseScanResponse } = await import('./validator.js');
18
- const r = parseScanResponse('{"tags":["#Auth/Flow"," bug FIX "],"confidence":0.8,"rationale":"x"}');
19
- assert.equal(r.ok, true);
20
- if (r.ok)
21
- assert.deepEqual(r.data.tags, ['auth-flow', 'bug-fix']);
22
- });
23
- it('rejects empty tags array', async () => {
24
- const { parseScanResponse } = await import('./validator.js');
25
- const r = parseScanResponse('{"tags":[],"confidence":0.5,"rationale":"x"}');
26
- assert.equal(r.ok, false);
27
- });
28
- it('rejects malformed JSON', async () => {
29
- const { parseScanResponse } = await import('./validator.js');
30
- const r = parseScanResponse('not json at all');
31
- assert.equal(r.ok, false);
32
- });
33
- it('caps tags at maxTags', async () => {
34
- const { parseScanResponse } = await import('./validator.js');
35
- const r = parseScanResponse('{"tags":["a","b","c","d","e","f"],"confidence":0.9,"rationale":"x"}', { maxTags: 3 });
36
- assert.equal(r.ok, true);
37
- if (r.ok)
38
- assert.equal(r.data.tags.length, 3);
39
- });
40
- });
41
- //# sourceMappingURL=validator.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validator.test.js","sourceRoot":"","sources":["../../../src/daemon/tag-scanner/validator.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;QAC1C,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,iBAAiB,CACzB,0EAA0E,CAC3E,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACzB,IAAI,CAAC,CAAC,EAAE;YAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,KAAK,IAAI,EAAE;QAC3C,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,iBAAiB,CACzB,sEAAsE,CACvE,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,iBAAiB,CACzB,wEAAwE,CACzE,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACzB,IAAI,CAAC,CAAC,EAAE;YAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;QACxC,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,iBAAiB,CAAC,8CAA8C,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;QACtC,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;QAC/C,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;QACpC,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,iBAAiB,CACzB,qEAAqE,EACrE,EAAE,OAAO,EAAE,CAAC,EAAE,CACf,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACzB,IAAI,CAAC,CAAC,EAAE;YAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}