@goondocks/myco 0.6.1 → 0.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.
Files changed (111) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/dist/{chunk-2YBUL3IL.js → chunk-25DJSF2K.js} +3 -3
  4. package/dist/{chunk-24DOZEUJ.js → chunk-ALBVNGCF.js} +591 -27
  5. package/dist/chunk-ALBVNGCF.js.map +1 -0
  6. package/dist/{chunk-E7OBRBCQ.js → chunk-CK24O5YQ.js} +12 -2
  7. package/dist/chunk-CK24O5YQ.js.map +1 -0
  8. package/dist/{chunk-2GSX3BK2.js → chunk-CPVXNRGW.js} +4 -4
  9. package/dist/{chunk-L25U7PIG.js → chunk-CQ4RKK67.js} +2 -2
  10. package/dist/{chunk-ZMYNRTTD.js → chunk-HRGHDMYI.js} +4 -3
  11. package/dist/chunk-HRGHDMYI.js.map +1 -0
  12. package/dist/{chunk-5FNZ7AMX.js → chunk-IWBWZQK6.js} +2 -2
  13. package/dist/{chunk-MQSYSQ6T.js → chunk-JSK7L46L.js} +11 -6
  14. package/dist/{chunk-MQSYSQ6T.js.map → chunk-JSK7L46L.js.map} +1 -1
  15. package/dist/{chunk-KUMVJIJW.js → chunk-LDKXXKF6.js} +6 -10
  16. package/dist/{chunk-KUMVJIJW.js.map → chunk-LDKXXKF6.js.map} +1 -1
  17. package/dist/{chunk-QGJ2ZIUZ.js → chunk-MWW62YZP.js} +37 -5
  18. package/dist/chunk-MWW62YZP.js.map +1 -0
  19. package/dist/{chunk-2ZBB3MQT.js → chunk-PQWQC3RF.js} +444 -21
  20. package/dist/chunk-PQWQC3RF.js.map +1 -0
  21. package/dist/{chunk-5QWZT4AB.js → chunk-RNWALAFP.js} +2 -2
  22. package/dist/{chunk-3EM23DMD.js → chunk-RXJHB7W4.js} +2 -2
  23. package/dist/{chunk-GNR3QAER.js → chunk-RY76WEN3.js} +2 -2
  24. package/dist/{chunk-GDYYJTTT.js → chunk-V5R6O6RP.js} +3 -3
  25. package/dist/{chunk-6BSDCZ5Q.js → chunk-WBLTISAK.js} +8 -3
  26. package/dist/chunk-WBLTISAK.js.map +1 -0
  27. package/dist/{chunk-YTANWAGE.js → chunk-XNAM6Z4O.js} +2 -2
  28. package/dist/{chunk-P3WO3N3I.js → chunk-YG6MLLGL.js} +19 -3
  29. package/dist/{chunk-P3WO3N3I.js.map → chunk-YG6MLLGL.js.map} +1 -1
  30. package/dist/{cli-K7SUTP7A.js → cli-LMBBPV2D.js} +20 -20
  31. package/dist/{client-YJMNTITQ.js → client-FDKJ4BY7.js} +5 -5
  32. package/dist/{config-G5GGT5A6.js → config-HDUFDOQN.js} +3 -3
  33. package/dist/{curate-6T5NKVXK.js → curate-DYE4VCBJ.js} +10 -11
  34. package/dist/{curate-6T5NKVXK.js.map → curate-DYE4VCBJ.js.map} +1 -1
  35. package/dist/{detect-providers-S3M5TAMW.js → detect-providers-I2QQFDJW.js} +3 -3
  36. package/dist/{digest-O35VHYFP.js → digest-PNHFM7JJ.js} +11 -13
  37. package/dist/{digest-O35VHYFP.js.map → digest-PNHFM7JJ.js.map} +1 -1
  38. package/dist/{init-TFLSATB3.js → init-7N7F6W6U.js} +8 -8
  39. package/dist/{main-JEUQS3BY.js → main-3JZDUJLU.js} +177 -40
  40. package/dist/main-3JZDUJLU.js.map +1 -0
  41. package/dist/{rebuild-7SH5GSNX.js → rebuild-WXKQ5HZO.js} +10 -11
  42. package/dist/{rebuild-7SH5GSNX.js.map → rebuild-WXKQ5HZO.js.map} +1 -1
  43. package/dist/reprocess-PKRDV67L.js +79 -0
  44. package/dist/reprocess-PKRDV67L.js.map +1 -0
  45. package/dist/{restart-NLJLB52D.js → restart-WSJRHRHI.js} +6 -6
  46. package/dist/{search-2BVRF54H.js → search-SWMJ4MZ3.js} +6 -6
  47. package/dist/{server-4AMZNP4F.js → server-NTRVB5ZM.js} +14 -18
  48. package/dist/{server-4AMZNP4F.js.map → server-NTRVB5ZM.js.map} +1 -1
  49. package/dist/{session-start-AZAF3DTE.js → session-start-KQ4KCQMZ.js} +9 -9
  50. package/dist/setup-digest-BOYOSM4B.js +15 -0
  51. package/dist/setup-llm-PCZ64ALK.js +15 -0
  52. package/dist/src/cli.js +4 -4
  53. package/dist/src/daemon/main.js +4 -4
  54. package/dist/src/hooks/post-tool-use.js +5 -5
  55. package/dist/src/hooks/session-end.js +5 -5
  56. package/dist/src/hooks/session-start.js +4 -4
  57. package/dist/src/hooks/stop.js +7 -7
  58. package/dist/src/hooks/user-prompt-submit.js +5 -5
  59. package/dist/src/mcp/server.js +4 -4
  60. package/dist/src/prompts/consolidation.md +2 -0
  61. package/dist/src/prompts/digest-7500.md +68 -0
  62. package/dist/{stats-MKDIZFIQ.js → stats-2OUQSEZO.js} +6 -6
  63. package/dist/ui/assets/index-Bk4X_8-Z.css +1 -0
  64. package/dist/ui/assets/index-D3SY7ZHY.js +299 -0
  65. package/dist/ui/index.html +2 -2
  66. package/dist/{verify-7DW7LAND.js → verify-MG5O7SBU.js} +6 -6
  67. package/dist/{version-RQLD7VBP.js → version-NKOECSVH.js} +4 -4
  68. package/package.json +1 -1
  69. package/dist/chunk-24DOZEUJ.js.map +0 -1
  70. package/dist/chunk-2ZBB3MQT.js.map +0 -1
  71. package/dist/chunk-3JCXYLHD.js +0 -33
  72. package/dist/chunk-3JCXYLHD.js.map +0 -1
  73. package/dist/chunk-6BSDCZ5Q.js.map +0 -1
  74. package/dist/chunk-B5UZSHQV.js +0 -250
  75. package/dist/chunk-B5UZSHQV.js.map +0 -1
  76. package/dist/chunk-E7OBRBCQ.js.map +0 -1
  77. package/dist/chunk-KC7ENQTN.js +0 -436
  78. package/dist/chunk-KC7ENQTN.js.map +0 -1
  79. package/dist/chunk-QGJ2ZIUZ.js.map +0 -1
  80. package/dist/chunk-UVGAVYWZ.js +0 -157
  81. package/dist/chunk-UVGAVYWZ.js.map +0 -1
  82. package/dist/chunk-ZMYNRTTD.js.map +0 -1
  83. package/dist/main-JEUQS3BY.js.map +0 -1
  84. package/dist/reprocess-Q4YH2ZBK.js +0 -268
  85. package/dist/reprocess-Q4YH2ZBK.js.map +0 -1
  86. package/dist/setup-digest-YLZZGSSR.js +0 -15
  87. package/dist/setup-llm-JOXBSLXC.js +0 -15
  88. package/dist/ui/assets/index-D37IoDXS.css +0 -1
  89. package/dist/ui/assets/index-DA61Ial2.js +0 -289
  90. /package/dist/{chunk-2YBUL3IL.js.map → chunk-25DJSF2K.js.map} +0 -0
  91. /package/dist/{chunk-2GSX3BK2.js.map → chunk-CPVXNRGW.js.map} +0 -0
  92. /package/dist/{chunk-L25U7PIG.js.map → chunk-CQ4RKK67.js.map} +0 -0
  93. /package/dist/{chunk-5FNZ7AMX.js.map → chunk-IWBWZQK6.js.map} +0 -0
  94. /package/dist/{chunk-5QWZT4AB.js.map → chunk-RNWALAFP.js.map} +0 -0
  95. /package/dist/{chunk-3EM23DMD.js.map → chunk-RXJHB7W4.js.map} +0 -0
  96. /package/dist/{chunk-GNR3QAER.js.map → chunk-RY76WEN3.js.map} +0 -0
  97. /package/dist/{chunk-GDYYJTTT.js.map → chunk-V5R6O6RP.js.map} +0 -0
  98. /package/dist/{chunk-YTANWAGE.js.map → chunk-XNAM6Z4O.js.map} +0 -0
  99. /package/dist/{cli-K7SUTP7A.js.map → cli-LMBBPV2D.js.map} +0 -0
  100. /package/dist/{client-YJMNTITQ.js.map → client-FDKJ4BY7.js.map} +0 -0
  101. /package/dist/{config-G5GGT5A6.js.map → config-HDUFDOQN.js.map} +0 -0
  102. /package/dist/{detect-providers-S3M5TAMW.js.map → detect-providers-I2QQFDJW.js.map} +0 -0
  103. /package/dist/{init-TFLSATB3.js.map → init-7N7F6W6U.js.map} +0 -0
  104. /package/dist/{restart-NLJLB52D.js.map → restart-WSJRHRHI.js.map} +0 -0
  105. /package/dist/{search-2BVRF54H.js.map → search-SWMJ4MZ3.js.map} +0 -0
  106. /package/dist/{session-start-AZAF3DTE.js.map → session-start-KQ4KCQMZ.js.map} +0 -0
  107. /package/dist/{setup-digest-YLZZGSSR.js.map → setup-digest-BOYOSM4B.js.map} +0 -0
  108. /package/dist/{setup-llm-JOXBSLXC.js.map → setup-llm-PCZ64ALK.js.map} +0 -0
  109. /package/dist/{stats-MKDIZFIQ.js.map → stats-2OUQSEZO.js.map} +0 -0
  110. /package/dist/{verify-7DW7LAND.js.map → verify-MG5O7SBU.js.map} +0 -0
  111. /package/dist/{version-RQLD7VBP.js.map → version-NKOECSVH.js.map} +0 -0
@@ -1,43 +1,61 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
- EMBEDDING_BATCH_CONCURRENCY,
4
- batchExecute
5
- } from "./chunk-3JCXYLHD.js";
6
- import {
7
- isActiveSpore,
8
- supersedeSpore,
9
- supersededIdsSchema
10
- } from "./chunk-UVGAVYWZ.js";
11
- import {
3
+ ARTIFACT_TYPES,
4
+ CONVERSATION_HEADING,
5
+ VaultWriter,
6
+ bareSessionId,
7
+ buildClassificationPrompt,
8
+ buildExtractionPrompt,
9
+ buildSummaryPrompt,
10
+ buildTitlePrompt,
11
+ callout,
12
+ extractJson,
13
+ extractSection,
12
14
  formatNoteForPrompt,
13
15
  formatNotesForPrompt,
16
+ formatSporeBody,
17
+ indexNote,
18
+ isActiveSpore,
14
19
  loadPrompt,
15
20
  rebuildIndex,
16
- stripReasoningTokens
17
- } from "./chunk-24DOZEUJ.js";
21
+ require_gray_matter,
22
+ sessionNoteId,
23
+ stripReasoningTokens,
24
+ supersedeSpore,
25
+ supersededIdsSchema
26
+ } from "./chunk-ALBVNGCF.js";
18
27
  import {
19
28
  generateEmbedding
20
29
  } from "./chunk-RGVBGTD6.js";
21
30
  import {
22
31
  stripFrontmatter
23
- } from "./chunk-GNR3QAER.js";
32
+ } from "./chunk-RY76WEN3.js";
24
33
  import {
25
34
  initFts
26
35
  } from "./chunk-6FQISQNA.js";
27
36
  import {
37
+ external_exports,
28
38
  require_dist
29
- } from "./chunk-MQSYSQ6T.js";
39
+ } from "./chunk-JSK7L46L.js";
40
+ import {
41
+ AgentRegistry,
42
+ claudeCodeAdapter,
43
+ createPerProjectAdapter
44
+ } from "./chunk-RNWALAFP.js";
30
45
  import {
46
+ AI_RESPONSE_PREVIEW_CHARS,
31
47
  CHARS_PER_TOKEN,
48
+ COMMAND_PREVIEW_CHARS,
32
49
  CURATION_CLUSTER_SIMILARITY,
33
50
  DIGEST_LLM_REQUEST_TIMEOUT_MS,
34
51
  DIGEST_SUBSTRATE_TYPE_WEIGHTS,
35
52
  DIGEST_TIER_MIN_CONTEXT,
36
53
  EMBEDDING_INPUT_LIMIT,
37
54
  LLM_REASONING_MODE,
55
+ PROMPT_PREVIEW_CHARS,
38
56
  SUPERSESSION_MAX_TOKENS,
39
57
  estimateTokens
40
- } from "./chunk-6BSDCZ5Q.js";
58
+ } from "./chunk-WBLTISAK.js";
41
59
  import {
42
60
  __toESM
43
61
  } from "./chunk-PZUWP5VK.js";
@@ -226,6 +244,11 @@ ${body}
226
244
  }
227
245
  this.cycleInProgress = true;
228
246
  try {
247
+ if (this.llm.ensureLoaded) {
248
+ const { context_window: contextWindow, gpu_kv_cache: gpuKvCache } = this.config.digest.intelligence;
249
+ this.log("debug", "Verifying digest model", { contextWindow, gpuKvCache });
250
+ await this.llm.ensureLoaded(contextWindow, gpuKvCache);
251
+ }
229
252
  for (const hook of this.prePassHooks) {
230
253
  try {
231
254
  await hook.fn();
@@ -239,11 +262,6 @@ ${body}
239
262
  }
240
263
  }
241
264
  async runCycleInternal(opts) {
242
- if (this.llm.ensureLoaded) {
243
- const { context_window: contextWindow, gpu_kv_cache: gpuKvCache } = this.config.digest.intelligence;
244
- this.log("debug", "Verifying digest model", { contextWindow, gpuKvCache });
245
- await this.llm.ensureLoaded(contextWindow, gpuKvCache);
246
- }
247
265
  const startTime = Date.now();
248
266
  const fullReprocess = opts?.fullReprocess ?? false;
249
267
  const lastTimestamp = fullReprocess ? null : this.getLastCycleTimestamp();
@@ -431,7 +449,249 @@ var Metabolism = class {
431
449
  }
432
450
  };
433
451
 
452
+ // src/daemon/processor.ts
453
+ var SUMMARIZATION_FAILED_MARKER = "summarization failed";
454
+ var ClassificationResponseSchema = external_exports.object({
455
+ artifacts: external_exports.array(external_exports.object({
456
+ source_path: external_exports.string(),
457
+ artifact_type: external_exports.enum(ARTIFACT_TYPES),
458
+ title: external_exports.string(),
459
+ tags: external_exports.array(external_exports.string()).default([])
460
+ })).default([])
461
+ });
462
+ var BufferProcessor = class {
463
+ constructor(backend, contextWindow = 8192, captureConfig) {
464
+ this.backend = backend;
465
+ this.contextWindow = contextWindow;
466
+ this.extractionMaxTokens = captureConfig?.extraction_max_tokens ?? 2048;
467
+ this.summaryMaxTokens = captureConfig?.summary_max_tokens ?? 512;
468
+ this.titleMaxTokens = captureConfig?.title_max_tokens ?? 32;
469
+ this.classificationMaxTokens = captureConfig?.classification_max_tokens ?? 1024;
470
+ }
471
+ extractionMaxTokens;
472
+ summaryMaxTokens;
473
+ titleMaxTokens;
474
+ classificationMaxTokens;
475
+ truncateForContext(data, maxTokens) {
476
+ const available = this.contextWindow - maxTokens;
477
+ const dataTokens = estimateTokens(data);
478
+ if (dataTokens <= available) return data;
479
+ const charBudget = available * CHARS_PER_TOKEN;
480
+ return data.slice(0, charBudget);
481
+ }
482
+ async process(events, sessionId) {
483
+ const rawPrompt = this.buildPromptForExtraction(events, sessionId);
484
+ const prompt = this.truncateForContext(rawPrompt, this.extractionMaxTokens);
485
+ try {
486
+ const response = await this.backend.summarize(prompt, { maxTokens: this.extractionMaxTokens, reasoning: LLM_REASONING_MODE });
487
+ const parsed = extractJson(response.text);
488
+ return {
489
+ summary: parsed.summary,
490
+ observations: parsed.observations ?? [],
491
+ degraded: false
492
+ };
493
+ } catch (error) {
494
+ return {
495
+ summary: `LLM processing failed for session ${sessionId}. ${events.length} events captured. Error: ${error.message}`,
496
+ observations: [],
497
+ degraded: true
498
+ };
499
+ }
500
+ }
501
+ buildPromptForExtraction(events, sessionId) {
502
+ const toolSummary = this.summarizeEvents(events);
503
+ return buildExtractionPrompt(sessionId, events.length, toolSummary, this.extractionMaxTokens);
504
+ }
505
+ async summarizeSession(conversationMarkdown, sessionId, user) {
506
+ const truncatedContent = this.truncateForContext(conversationMarkdown, this.summaryMaxTokens);
507
+ const summaryPrompt = buildSummaryPrompt(sessionId, user ?? "unknown", truncatedContent, this.summaryMaxTokens);
508
+ let summaryText;
509
+ try {
510
+ const response = await this.backend.summarize(summaryPrompt, { maxTokens: this.summaryMaxTokens, reasoning: LLM_REASONING_MODE });
511
+ summaryText = stripReasoningTokens(response.text);
512
+ } catch (error) {
513
+ summaryText = `Session ${sessionId} \u2014 ${SUMMARIZATION_FAILED_MARKER}: ${error.message}`;
514
+ }
515
+ const titlePrompt = buildTitlePrompt(summaryText, sessionId);
516
+ let title;
517
+ try {
518
+ const response = await this.backend.summarize(titlePrompt, { maxTokens: this.titleMaxTokens, reasoning: LLM_REASONING_MODE });
519
+ title = stripReasoningTokens(response.text).trim();
520
+ } catch {
521
+ title = `Session ${sessionId}`;
522
+ }
523
+ return { summary: summaryText, title };
524
+ }
525
+ async classifyArtifacts(candidates, sessionId) {
526
+ if (candidates.length === 0) return [];
527
+ const prompt = this.buildPromptForClassification(candidates, sessionId);
528
+ const response = await this.backend.summarize(prompt, { maxTokens: this.classificationMaxTokens, reasoning: LLM_REASONING_MODE });
529
+ const raw = extractJson(response.text);
530
+ const parsed = ClassificationResponseSchema.parse(raw);
531
+ return parsed.artifacts;
532
+ }
533
+ buildPromptForClassification(candidates, sessionId) {
534
+ return buildClassificationPrompt(sessionId, candidates, this.classificationMaxTokens);
535
+ }
536
+ summarizeEvents(events) {
537
+ const toolCounts = /* @__PURE__ */ new Map();
538
+ const filesAccessed = /* @__PURE__ */ new Set();
539
+ const prompts = [];
540
+ const aiResponses = [];
541
+ for (const event of events) {
542
+ if (event.type === "user_prompt") {
543
+ const prompt = String(event.prompt ?? "");
544
+ if (prompt) prompts.push(prompt.slice(0, PROMPT_PREVIEW_CHARS));
545
+ continue;
546
+ }
547
+ if (event.type === "ai_response") {
548
+ const content = String(event.content ?? "");
549
+ if (content) aiResponses.push(content.slice(0, AI_RESPONSE_PREVIEW_CHARS));
550
+ continue;
551
+ }
552
+ const tool = String(event.tool_name ?? event.tool ?? "unknown");
553
+ toolCounts.set(tool, (toolCounts.get(tool) ?? 0) + 1);
554
+ const input = event.tool_input ?? event.input;
555
+ if (input?.path) filesAccessed.add(String(input.path));
556
+ if (input?.file_path) filesAccessed.add(String(input.file_path));
557
+ if (input?.command) filesAccessed.add(`[cmd] ${String(input.command).slice(0, COMMAND_PREVIEW_CHARS)}`);
558
+ }
559
+ const lines = [];
560
+ if (prompts.length > 0) {
561
+ lines.push("### User Prompts");
562
+ for (const p of prompts) {
563
+ lines.push(`- "${p}"`);
564
+ }
565
+ }
566
+ lines.push("\n### Tool Usage");
567
+ for (const [tool, count] of toolCounts) {
568
+ lines.push(`- ${tool}: ${count} calls`);
569
+ }
570
+ if (filesAccessed.size > 0) {
571
+ lines.push("\n### Files Accessed");
572
+ for (const file of filesAccessed) {
573
+ lines.push(`- ${file}`);
574
+ }
575
+ }
576
+ if (aiResponses.length > 0) {
577
+ lines.push("\n### AI Responses");
578
+ for (const r of aiResponses) {
579
+ lines.push(`- "${r}"`);
580
+ }
581
+ }
582
+ return lines.join("\n");
583
+ }
584
+ };
585
+
586
+ // src/capture/transcript-miner.ts
587
+ var TranscriptMiner = class {
588
+ registry;
589
+ constructor(config) {
590
+ this.registry = new AgentRegistry(config?.additionalAdapters);
591
+ }
592
+ /**
593
+ * Extract all conversation turns for a session.
594
+ * Convenience wrapper — delegates to getAllTurnsWithSource.
595
+ */
596
+ getAllTurns(sessionId) {
597
+ return this.getAllTurnsWithSource(sessionId).turns;
598
+ }
599
+ /**
600
+ * Extract turns using the hook-provided transcript path first (fast, no scanning),
601
+ * then fall back to adapter registry scanning if the path isn't provided.
602
+ */
603
+ getAllTurnsWithSource(sessionId, transcriptPath) {
604
+ if (transcriptPath) {
605
+ const result2 = this.registry.parseTurnsFromPath(transcriptPath);
606
+ if (result2) return result2;
607
+ }
608
+ const result = this.registry.getTranscriptTurns(sessionId);
609
+ if (result) return result;
610
+ return { turns: [], source: "none" };
611
+ }
612
+ };
613
+ function extractTurnsFromBuffer(events) {
614
+ const turns = [];
615
+ let current = null;
616
+ for (const event of events) {
617
+ const type = event.type;
618
+ if (type === "user_prompt") {
619
+ if (current) turns.push(current);
620
+ current = {
621
+ prompt: String(event.prompt ?? "").slice(0, PROMPT_PREVIEW_CHARS),
622
+ toolCount: 0,
623
+ timestamp: String(event.timestamp ?? (/* @__PURE__ */ new Date()).toISOString())
624
+ };
625
+ } else if (type === "tool_use") {
626
+ if (current) current.toolCount++;
627
+ }
628
+ }
629
+ if (current) turns.push(current);
630
+ return turns;
631
+ }
632
+
633
+ // src/vault/observations.ts
634
+ function writeObservationNotes(observations, sessionId, writer, index, vaultDir) {
635
+ const results = [];
636
+ for (const obs of observations) {
637
+ const obsId = `${obs.type}-${sessionId.slice(-6)}-${Date.now()}`;
638
+ const body = formatSporeBody({
639
+ title: obs.title,
640
+ observationType: obs.type,
641
+ content: obs.content,
642
+ sessionId,
643
+ root_cause: obs.root_cause,
644
+ fix: obs.fix,
645
+ rationale: obs.rationale,
646
+ alternatives_rejected: obs.alternatives_rejected,
647
+ gained: obs.gained,
648
+ sacrificed: obs.sacrificed,
649
+ tags: obs.tags
650
+ });
651
+ const relativePath = writer.writeSpore({
652
+ id: obsId,
653
+ observation_type: obs.type,
654
+ session: sessionNoteId(sessionId),
655
+ tags: obs.tags,
656
+ content: body
657
+ });
658
+ indexNote(index, vaultDir, relativePath);
659
+ results.push({ id: obsId, path: relativePath, observation: obs });
660
+ }
661
+ return results;
662
+ }
663
+
664
+ // src/services/vault-ops.ts
665
+ import fs3 from "fs";
666
+ import path3 from "path";
667
+
668
+ // src/intelligence/batch.ts
669
+ var LLM_BATCH_CONCURRENCY = 3;
670
+ var EMBEDDING_BATCH_CONCURRENCY = 4;
671
+ async function batchExecute(items, fn, options) {
672
+ const { concurrency, onProgress } = options;
673
+ let succeeded = 0;
674
+ let failed = 0;
675
+ const results = [];
676
+ for (let i = 0; i < items.length; i += concurrency) {
677
+ const batch = items.slice(i, i + concurrency);
678
+ const settled = await Promise.allSettled(batch.map(fn));
679
+ for (const result of settled) {
680
+ if (result.status === "fulfilled") {
681
+ succeeded++;
682
+ results.push({ status: "fulfilled", value: result.value });
683
+ } else {
684
+ failed++;
685
+ results.push({ status: "rejected", reason: result.reason?.message ?? String(result.reason) });
686
+ }
687
+ }
688
+ onProgress?.(succeeded + failed, items.length);
689
+ }
690
+ return { succeeded, failed, results };
691
+ }
692
+
434
693
  // src/services/vault-ops.ts
694
+ var import_gray_matter = __toESM(require_gray_matter(), 1);
435
695
  async function runRebuild(ctx, embeddingProvider, onProgress) {
436
696
  const { index, vaultDir } = ctx;
437
697
  initFts(index);
@@ -651,14 +911,177 @@ async function runCuration(deps, dryRun) {
651
911
  superseded: totalSuperseded
652
912
  };
653
913
  }
914
+ function updateTitleAndSummary(body, newTitle, newNarrative) {
915
+ let updated = body.replace(/^# .*/m, `# ${newTitle}`);
916
+ const summaryCallout = callout("abstract", "Summary", newNarrative);
917
+ updated = updated.replace(/> \[!abstract\] Summary\n(?:> .*\n?)*/m, summaryCallout + "\n");
918
+ return updated;
919
+ }
920
+ async function runReprocess(ctx, llmProvider, embeddingProvider, options, onProgress) {
921
+ const { vaultDir, config, index } = ctx;
922
+ const log = ctx.log ?? (() => {
923
+ });
924
+ const sessionFilter = options?.session;
925
+ const dateFilter = options?.date;
926
+ const failedOnly = options?.failed ?? false;
927
+ const skipLlm = options?.indexOnly ?? false;
928
+ const effectiveLlm = skipLlm ? null : llmProvider;
929
+ const processor = effectiveLlm ? new BufferProcessor(effectiveLlm, config.intelligence.llm.context_window, config.capture) : null;
930
+ const writer = new VaultWriter(vaultDir);
931
+ const miner = new TranscriptMiner({
932
+ additionalAdapters: config.capture.transcript_paths.map(
933
+ (p) => createPerProjectAdapter(p, claudeCodeAdapter.parseTurns)
934
+ )
935
+ });
936
+ const sessionsDir = path3.join(vaultDir, "sessions");
937
+ if (!fs3.existsSync(sessionsDir)) {
938
+ return { sessionsFound: 0, sessionsProcessed: 0, observationsExtracted: 0, summariesRegenerated: 0, embeddingsQueued: 0 };
939
+ }
940
+ const sessionFiles = [];
941
+ for (const dateDir of fs3.readdirSync(sessionsDir)) {
942
+ if (dateFilter && dateDir !== dateFilter) continue;
943
+ const datePath = path3.join(sessionsDir, dateDir);
944
+ if (!fs3.statSync(datePath).isDirectory()) continue;
945
+ for (const file of fs3.readdirSync(datePath)) {
946
+ if (!file.startsWith("session-") || !file.endsWith(".md")) continue;
947
+ const sessionId = file.replace("session-", "").replace(".md", "");
948
+ if (sessionFilter && !sessionId.includes(sessionFilter)) continue;
949
+ sessionFiles.push({ relativePath: path3.join("sessions", dateDir, file), sessionId });
950
+ }
951
+ }
952
+ if (sessionFiles.length === 0) {
953
+ return { sessionsFound: 0, sessionsProcessed: 0, observationsExtracted: 0, summariesRegenerated: 0, embeddingsQueued: 0 };
954
+ }
955
+ const tasks = [];
956
+ for (const { relativePath, sessionId } of sessionFiles) {
957
+ const rawContent = fs3.readFileSync(path3.join(vaultDir, relativePath), "utf-8");
958
+ const hasFailed = rawContent.includes(SUMMARIZATION_FAILED_MARKER);
959
+ if (failedOnly && !hasFailed) continue;
960
+ const { data: frontmatter, content: body } = (0, import_gray_matter.default)(rawContent);
961
+ const bare = bareSessionId(sessionId);
962
+ const turnsResult = miner.getAllTurnsWithSource(bare);
963
+ const conversationSection = extractSection(body, CONVERSATION_HEADING);
964
+ const fmEnd = rawContent.indexOf("---", 4);
965
+ const frontmatterBlock = rawContent.slice(0, fmEnd + 3);
966
+ const batchEvents = turnsResult && turnsResult.turns.length > 0 ? turnsResult.turns.map((t) => ({
967
+ type: "turn",
968
+ prompt: t.prompt,
969
+ tool_count: t.toolCount,
970
+ response: t.aiResponse ?? "",
971
+ timestamp: t.timestamp
972
+ })) : null;
973
+ tasks.push({ relativePath, sessionId, bare, frontmatter, frontmatterBlock, body, conversationSection, batchEvents, turnCount: turnsResult?.turns.length ?? 0, hasFailed });
974
+ }
975
+ if (tasks.length === 0) {
976
+ return { sessionsFound: sessionFiles.length, sessionsProcessed: 0, observationsExtracted: 0, summariesRegenerated: 0, embeddingsQueued: 0 };
977
+ }
978
+ log("info", `Reprocessing ${tasks.length} session(s)`, { filters: { session: sessionFilter, date: dateFilter, failed: failedOnly, indexOnly: skipLlm } });
979
+ let embeddingsQueued = 0;
980
+ const embedPending = [];
981
+ const fireEmbed = (id, text, metadata) => {
982
+ if (!ctx.vectorIndex) return;
983
+ embeddingsQueued++;
984
+ const vec = ctx.vectorIndex;
985
+ const p = generateEmbedding(embeddingProvider, text).then((emb) => {
986
+ vec.upsert(id, emb.embedding, metadata);
987
+ }).catch((err) => {
988
+ log("warn", `Embedding failed for ${id}`, { error: err.message });
989
+ });
990
+ embedPending.push(p);
991
+ };
992
+ let totalObservations = 0;
993
+ const extractionResult = await batchExecute(
994
+ tasks,
995
+ async (task) => {
996
+ let obs = 0;
997
+ if (processor && task.batchEvents) {
998
+ const result = await processor.process(task.batchEvents, task.bare);
999
+ if (result.observations.length > 0) {
1000
+ writeObservationNotes(result.observations, task.bare, writer, index, vaultDir);
1001
+ obs = result.observations.length;
1002
+ for (const o of result.observations) {
1003
+ fireEmbed(
1004
+ `${o.type}-${task.bare.slice(-6)}-${Date.now()}`,
1005
+ `${o.title}
1006
+ ${o.content}`.slice(0, EMBEDDING_INPUT_LIMIT),
1007
+ { type: "spore", session_id: task.bare }
1008
+ );
1009
+ }
1010
+ }
1011
+ }
1012
+ indexNote(index, vaultDir, task.relativePath);
1013
+ const embText = `${task.frontmatter.title ?? ""}
1014
+ ${task.frontmatter.summary ?? ""}`.slice(0, EMBEDDING_INPUT_LIMIT);
1015
+ if (embText.trim()) {
1016
+ fireEmbed(sessionNoteId(task.bare), embText, { type: "session", session_id: task.bare });
1017
+ }
1018
+ return obs;
1019
+ },
1020
+ {
1021
+ concurrency: LLM_BATCH_CONCURRENCY,
1022
+ onProgress: (done, total) => onProgress?.("extraction", done, total)
1023
+ }
1024
+ );
1025
+ for (const r of extractionResult.results) {
1026
+ if (r.status === "fulfilled") totalObservations += r.value;
1027
+ }
1028
+ let summarized = 0;
1029
+ if (processor) {
1030
+ const summarizableTasks = tasks.filter((t) => t.conversationSection);
1031
+ if (summarizableTasks.length > 0) {
1032
+ const summaryResult = await batchExecute(
1033
+ summarizableTasks,
1034
+ async (task) => {
1035
+ const user = typeof task.frontmatter.user === "string" ? task.frontmatter.user : void 0;
1036
+ const result = await processor.summarizeSession(task.conversationSection, task.bare, user);
1037
+ if (result.summary.includes(SUMMARIZATION_FAILED_MARKER)) {
1038
+ log("warn", `Summarization failed for ${task.sessionId.slice(0, 12)}`);
1039
+ return false;
1040
+ }
1041
+ const updatedBody = updateTitleAndSummary(task.body, result.title, result.summary);
1042
+ fs3.writeFileSync(path3.join(vaultDir, task.relativePath), task.frontmatterBlock + updatedBody);
1043
+ indexNote(index, vaultDir, task.relativePath);
1044
+ return true;
1045
+ },
1046
+ {
1047
+ concurrency: LLM_BATCH_CONCURRENCY,
1048
+ onProgress: (done, total) => onProgress?.("summarization", done, total)
1049
+ }
1050
+ );
1051
+ for (const r of summaryResult.results) {
1052
+ if (r.status === "fulfilled" && r.value) summarized++;
1053
+ }
1054
+ }
1055
+ }
1056
+ await Promise.allSettled(embedPending);
1057
+ log("info", "Reprocess completed", {
1058
+ sessions: tasks.length,
1059
+ observations: totalObservations,
1060
+ summaries: summarized,
1061
+ embeddings: embeddingsQueued
1062
+ });
1063
+ return {
1064
+ sessionsFound: sessionFiles.length,
1065
+ sessionsProcessed: tasks.length,
1066
+ observationsExtracted: totalObservations,
1067
+ summariesRegenerated: summarized,
1068
+ embeddingsQueued
1069
+ };
1070
+ }
654
1071
 
655
1072
  export {
656
1073
  readLastTimestamp,
657
1074
  appendTraceRecord,
658
1075
  DigestEngine,
659
1076
  Metabolism,
1077
+ SUMMARIZATION_FAILED_MARKER,
1078
+ BufferProcessor,
1079
+ TranscriptMiner,
1080
+ extractTurnsFromBuffer,
1081
+ writeObservationNotes,
660
1082
  runRebuild,
661
1083
  runDigest,
662
- runCuration
1084
+ runCuration,
1085
+ runReprocess
663
1086
  };
664
- //# sourceMappingURL=chunk-2ZBB3MQT.js.map
1087
+ //# sourceMappingURL=chunk-PQWQC3RF.js.map