@cortexkit/pi-magic-context 0.48.0 → 0.49.0

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 (40) hide show
  1. package/dist/auto-search-worker.js +3 -3
  2. package/dist/embedding-backfill-b71dvfs8.js +20 -0
  3. package/dist/embedding-worker.js +4 -4
  4. package/dist/historian-calibration-extension.js +30 -5
  5. package/dist/{index-dkx0b1kt.js → index-041ex0cj.js} +7 -2
  6. package/dist/{index-fp37he9a.js → index-0vrkp1jq.js} +1 -1
  7. package/dist/{index-6pgq5ns2.js → index-1evzceyw.js} +2 -2
  8. package/dist/{index-419bndtm.js → index-21v1kfs7.js} +2 -2
  9. package/dist/{index-wrm4nbj7.js → index-290tzwp1.js} +1 -1
  10. package/dist/{index-72bdc1bd.js → index-3mgf68pn.js} +4 -4
  11. package/dist/{index-hrf13mn3.js → index-3rea6zd9.js} +16 -8
  12. package/dist/{index-0am8a7k1.js → index-904reqtg.js} +4 -4
  13. package/dist/{index-fm3ksh5e.js → index-bejpsj10.js} +4 -4
  14. package/dist/{index-98z1c1r0.js → index-ehybv5nr.js} +109 -35
  15. package/dist/{index-pvm4pd5d.js → index-hwqb3s7f.js} +811 -76
  16. package/dist/{index-5hd7h4rr.js → index-kjd1fj55.js} +39 -31
  17. package/dist/{index-8y5knskr.js → index-mcgehvgw.js} +93 -9
  18. package/dist/{index-603mt6nm.js → index-r024r8da.js} +1 -1
  19. package/dist/{index-9xb0axhc.js → index-r56xgha8.js} +1 -1
  20. package/dist/{index-r7xg4hvw.js → index-t7xfqtg6.js} +8 -8
  21. package/dist/{index-rt5jgzp1.js → index-vakawmbc.js} +160 -25
  22. package/dist/{index-f956htf3.js → index-x3dcnxh0.js} +6 -2
  23. package/dist/{index-544c0e0x.js → index-yarjn32j.js} +7 -7
  24. package/dist/{index-5jp1h0bz.js → index-yzcjxnt2.js} +48 -11
  25. package/dist/{index-zrr5t5a7.js → index-zh1jw8qp.js} +106 -1
  26. package/dist/index.js +1149 -680
  27. package/dist/{logger-v3dsxdnm.js → logger-j6tecd1h.js} +1 -1
  28. package/dist/{message-index-bounded-t7vvty76.js → message-index-bounded-qz5dz2se.js} +11 -11
  29. package/dist/{message-time-backfill-4ndf7hrq.js → message-time-backfill-05ppypkz.js} +2 -2
  30. package/dist/migration-worker.js +8 -8
  31. package/dist/{project-embedding-registry-jy2hmq28.js → project-embedding-registry-ky7wrkr1.js} +9 -9
  32. package/dist/raw-ordinal-warmup-worker.js +4 -4
  33. package/dist/{read-session-chunk-47pjn7fz.js → read-session-chunk-24sd89tf.js} +8 -6
  34. package/dist/{read-session-raw-yn8nawav.js → read-session-raw-npx3920c.js} +5 -3
  35. package/dist/{safe-notification-target-3c1ns931.js → safe-notification-target-vn9kpmv4.js} +2 -2
  36. package/dist/{search-42szfhwp.js → search-jbh28nwy.js} +17 -17
  37. package/dist/{storage-tags-jym5z6yk.js → storage-tags-kjnsqbdb.js} +6 -6
  38. package/dist/subagent-entry.js +20 -19
  39. package/package.json +1 -1
  40. package/dist/embedding-backfill-bnnytehy.js +0 -20
@@ -9,9 +9,11 @@ import {
9
9
  CATEGORY_DEFAULT_TTL
10
10
  } from "./index-135e8hvg.js";
11
11
  import {
12
+ getDataDir,
13
+ sanitizeDiagnosticText,
12
14
  log2,
13
15
  sessionLog2
14
- } from "./index-f956htf3.js";
16
+ } from "./index-x3dcnxh0.js";
15
17
  import {
16
18
  resolveWorkspaceShareCategories,
17
19
  resolveWorkspaceIdentitySet,
@@ -19,13 +21,17 @@ import {
19
21
  resolveStoredPathWorkspaceIdentity,
20
22
  sourceNameForMemory,
21
23
  managedAuthorityNoteRow
22
- } from "./index-72bdc1bd.js";
24
+ } from "./index-3mgf68pn.js";
23
25
  import {
24
26
  isKnownAutocommit
25
- } from "./index-8y5knskr.js";
27
+ } from "./index-mcgehvgw.js";
26
28
  import {
29
+ SubcClient
30
+ } from "./index-21v1kfs7.js";
31
+ import {
32
+ buildCanonicalChunkTextFromFts,
27
33
  loadCompartmentChunkEmbeddingsForSearch
28
- } from "./index-fm3ksh5e.js";
34
+ } from "./index-bejpsj10.js";
29
35
  import {
30
36
  recordEmbeddingMeasurement,
31
37
  saveCommitEmbedding,
@@ -43,7 +49,7 @@ import {
43
49
  getProjectEmbeddingSnapshot2,
44
50
  embedTextForProject2,
45
51
  embedItemsForProject2
46
- } from "./index-544c0e0x.js";
52
+ } from "./index-yarjn32j.js";
47
53
  import {
48
54
  saveEmbeddingIfHashMatches,
49
55
  getProjectEmbeddings2
@@ -53,7 +59,7 @@ import {
53
59
  isEmbeddingEnabled,
54
60
  embedText,
55
61
  ensureMemoryEmbeddings2
56
- } from "./index-0am8a7k1.js";
62
+ } from "./index-904reqtg.js";
57
63
  import {
58
64
  getMemorySelectColumns2,
59
65
  isMemoryRow2,
@@ -70,7 +76,7 @@ import {
70
76
  } from "./index-xjqheg7a.js";
71
77
  import {
72
78
  getIndexedMessageCorpusSize
73
- } from "./index-5jp1h0bz.js";
79
+ } from "./index-yzcjxnt2.js";
74
80
  import {
75
81
  computeNormalizedHash
76
82
  } from "./index-9x1f96r8.js";
@@ -591,6 +597,351 @@ function updatePrimerSupport(db, input) {
591
597
  function updatePrimerAnswer(db, primerId, answer, refreshedAt = Date.now()) {
592
598
  db.prepare("UPDATE primers SET answer = ?, answer_refreshed_at = ?, updated_at = ? WHERE id = ?").run(answer, refreshedAt, refreshedAt, primerId);
593
599
  }
600
+
601
+ // ../plugin/src/shared/user-facing-codes.ts
602
+ var USER_FACING_FAILURES = {
603
+ historian_unavailable: {
604
+ code: "MC-H01",
605
+ sentence: "History compression could not finish this turn.",
606
+ action: "It will retry automatically."
607
+ },
608
+ historian_saved_history_misaligned: {
609
+ code: "MC-H03",
610
+ sentence: "History compression is paused because this session's saved summaries no longer line up with its messages.",
611
+ action: "Run /ctx-recomp to rebuild them."
612
+ },
613
+ history_boundary_unresolved: {
614
+ code: "MC-H04",
615
+ sentence: "This request was not sent: the message that marks where this session's history summary ends is missing from the OpenCode store, and without it the request is larger than the model's context window.",
616
+ action: "Run /ctx-recomp to rebuild the history summary."
617
+ },
618
+ history_over_window_unmanaged: {
619
+ code: "MC-H06",
620
+ sentence: "This request was not sent: this session's history is larger than the model's context window, and Magic Context does not have a summary of it yet to send in its place.",
621
+ action: "Send your message again once history compression has caught up, or switch to a model with a larger context window."
622
+ },
623
+ frozen_history_over_window: {
624
+ code: "MC-H07",
625
+ sentence: "This request was not sent: the conversation is larger than the context window the provider reported, and the compressed history Magic Context has ready does not fit either.",
626
+ action: "Run /ctx-flush to compress it now, then send your message again."
627
+ },
628
+ historian_window_too_small: {
629
+ code: "MC-H05",
630
+ sentence: "History compression is paused because the history model's context window is too small for its instructions.",
631
+ action: "Set historian.model in magic-context.jsonc to a model with a larger context window."
632
+ },
633
+ recomp_unavailable: {
634
+ code: "MC-R01",
635
+ sentence: "History compression could not be rebuilt.",
636
+ action: "Run /ctx-recomp again."
637
+ },
638
+ dream_provider_timeout: {
639
+ code: "MC-D01",
640
+ sentence: "Memory maintenance took too long to respond.",
641
+ action: "Run /ctx-dream again."
642
+ },
643
+ dream_provider_error: {
644
+ code: "MC-D02",
645
+ sentence: "Memory maintenance could not reach its model.",
646
+ action: "Check the model connection, then run /ctx-dream again."
647
+ },
648
+ dream_local_refusal: {
649
+ code: "MC-D12",
650
+ sentence: "Memory maintenance was refused before reaching the model.",
651
+ action: "Check the hidden-request diagnostic in the Magic Context log before retrying."
652
+ },
653
+ dream_step_limit: {
654
+ code: "MC-D10",
655
+ sentence: "Memory maintenance stopped at its hidden agent step limit.",
656
+ action: "This task needs less work per run; changing the model connection will not help."
657
+ },
658
+ dream_token_budget: {
659
+ code: "MC-D11",
660
+ sentence: "Memory maintenance reached its prompt-token budget.",
661
+ action: "The unfinished items will be retried on the next run."
662
+ },
663
+ dream_empty_completion: {
664
+ code: "MC-D03",
665
+ sentence: "Memory maintenance received no usable response.",
666
+ action: "Run /ctx-dream again."
667
+ },
668
+ dream_no_models: {
669
+ code: "MC-D04",
670
+ sentence: "Memory maintenance has no model available.",
671
+ action: "Check the model settings, then run /ctx-dream again."
672
+ },
673
+ dream_child_aborted: {
674
+ code: "MC-D05",
675
+ sentence: "Memory maintenance was interrupted.",
676
+ action: "Run /ctx-dream again."
677
+ },
678
+ dream_parse_failed: {
679
+ code: "MC-D06",
680
+ sentence: "Memory maintenance could not use the model response.",
681
+ action: "Run /ctx-dream again."
682
+ },
683
+ dream_unknown: {
684
+ code: "MC-D07",
685
+ sentence: "Memory maintenance could not finish.",
686
+ action: "Run /ctx-dream again."
687
+ },
688
+ dreamer_tick_blocked: {
689
+ code: "MC-D09",
690
+ sentence: "Background maintenance is not running: its last pass stopped before it reached the scheduled tasks.",
691
+ action: "It is retried automatically; if it keeps happening, check the Magic Context log for the stage that stopped and run `npx @cortexkit/magic-context doctor`."
692
+ },
693
+ dream_task_needs_tool_loop: {
694
+ code: "MC-D08",
695
+ sentence: "Some memory maintenance tasks need a tool loop this host does not provide.",
696
+ action: "The remaining tasks still run; the listed ones are skipped on this host."
697
+ },
698
+ embedding_substitution_rejected: {
699
+ code: "MC-E01",
700
+ sentence: "Search indexing could not use the selected model.",
701
+ action: "Check the embedding model setting, then run /ctx-embed start again."
702
+ },
703
+ embedding_http_error: {
704
+ code: "MC-E02",
705
+ sentence: "The search indexing provider refused the request.",
706
+ action: "Check the provider connection and credentials, then run /ctx-embed start again."
707
+ },
708
+ embedding_transport_error: {
709
+ code: "MC-E03",
710
+ sentence: "Search indexing could not reach its provider.",
711
+ action: "Check the connection, then run /ctx-embed start again."
712
+ },
713
+ embedding_invalid_envelope: {
714
+ code: "MC-E04",
715
+ sentence: "Search indexing received an unsupported response.",
716
+ action: "Check the embedding endpoint, then run /ctx-embed start again."
717
+ },
718
+ embedding_empty_result: {
719
+ code: "MC-E05",
720
+ sentence: "Search indexing received no usable result.",
721
+ action: "Run /ctx-embed start again."
722
+ },
723
+ embedding_certification_refusal: {
724
+ code: "MC-E06",
725
+ sentence: "Search indexing is not ready for this provider.",
726
+ action: "Finish the provider setup, or set a fallback provider in the embedding settings, then run /ctx-embed start again."
727
+ },
728
+ embedding_credential_required: {
729
+ code: "MC-E07",
730
+ sentence: "Search indexing needs provider credentials.",
731
+ action: "Sign in to the provider, then run /ctx-embed start again."
732
+ },
733
+ embedding_local_binding_missing: {
734
+ code: "MC-E08",
735
+ sentence: "Local search indexing is unavailable on this system.",
736
+ action: "Run `npx @cortexkit/magic-context doctor`, then retry."
737
+ },
738
+ embedding_local_fs_unavailable: {
739
+ code: "MC-E09",
740
+ sentence: "Local search indexing cannot save its model files.",
741
+ action: "Update or reinstall Magic Context, then retry."
742
+ },
743
+ embedding_local_download_failure: {
744
+ code: "MC-E10",
745
+ sentence: "Local search indexing could not download its model.",
746
+ action: "Check the network connection, then retry."
747
+ },
748
+ embedding_local_runtime_error: {
749
+ code: "MC-E11",
750
+ sentence: "Local search indexing could not start.",
751
+ action: "Run `npx @cortexkit/magic-context doctor`, then retry."
752
+ },
753
+ embedding_unavailable: {
754
+ code: "MC-E12",
755
+ sentence: "Search indexing could not finish.",
756
+ action: "Run /ctx-embed start again."
757
+ },
758
+ status_unavailable: {
759
+ code: "MC-S01",
760
+ sentence: "Magic Context status is temporarily unavailable.",
761
+ action: "Retry /ctx-status in a moment."
762
+ },
763
+ transform_update_failed: {
764
+ code: "MC-S02",
765
+ sentence: "The last context update did not finish.",
766
+ action: "Send another message to retry."
767
+ },
768
+ transform_pass_degraded: {
769
+ code: "MC-S06",
770
+ sentence: "This request was not sent: Magic Context could not finish preparing it, and without that preparation it could be far larger than the previous request.",
771
+ action: "Send your message again."
772
+ },
773
+ configuration_warning: {
774
+ code: "MC-S03",
775
+ sentence: "Some configuration settings could not be applied.",
776
+ action: "Fix the configuration warning shown in /ctx-status, then restart."
777
+ },
778
+ status_log_unavailable: {
779
+ code: "MC-S04",
780
+ sentence: "Some diagnostic details could not be saved.",
781
+ action: "Retry /ctx-status in a moment."
782
+ },
783
+ memory_writes_paused: {
784
+ code: "MC-C01",
785
+ sentence: "Memory writes are paused while the engine syncs.",
786
+ action: "Retry in a moment."
787
+ },
788
+ memory_access_unavailable: {
789
+ code: "MC-C02",
790
+ sentence: "Memory access is temporarily unavailable.",
791
+ action: "Retry in a moment."
792
+ },
793
+ note_changes_paused: {
794
+ code: "MC-C03",
795
+ sentence: "Note changes are paused while the engine syncs.",
796
+ action: "Retry in a moment."
797
+ },
798
+ note_access_unavailable: {
799
+ code: "MC-C04",
800
+ sentence: "Notes are temporarily unavailable.",
801
+ action: "Retry in a moment."
802
+ },
803
+ context_cleanup_paused: {
804
+ code: "MC-C05",
805
+ sentence: "Context cleanup is paused while the engine syncs.",
806
+ action: "Retry in a moment."
807
+ },
808
+ partial_history_unavailable: {
809
+ code: "MC-C06",
810
+ sentence: "Partial history compression is not available in the current mode.",
811
+ action: "Run /ctx-recomp without a range."
812
+ },
813
+ smart_note_conditions_unavailable: {
814
+ code: "MC-C08",
815
+ sentence: "Conditional notes are not available in the current mode.",
816
+ action: "Save a regular note without a condition."
817
+ },
818
+ history_compression_paused: {
819
+ code: "MC-C09",
820
+ sentence: "History compression is paused while the engine syncs.",
821
+ action: "Retry in a moment."
822
+ },
823
+ history_compression_needs_message: {
824
+ code: "MC-C12",
825
+ sentence: "History compression has not seen this session since Magic Context reconnected.",
826
+ action: "Send a message in this session first, then run /ctx-wrapup again."
827
+ },
828
+ context_service_unavailable: {
829
+ code: "MC-C10",
830
+ sentence: "Magic Context is temporarily unavailable.",
831
+ action: "Retry in a moment."
832
+ },
833
+ context_db_missing: {
834
+ code: "MC-C15",
835
+ sentence: "Magic Context has no context.db.",
836
+ action: "Run `npx @cortexkit/magic-context doctor store init`, then restart ck-mc."
837
+ },
838
+ single_store_migration_required: {
839
+ code: "MC-C14",
840
+ sentence: "Magic Context's Rust mode needs a one-time migration of its store.",
841
+ action: "Quit OpenCode and every ck-mc process, then run `magic-context doctor single-store migrate`."
842
+ },
843
+ store_ahead_of_binary: {
844
+ code: "MC-C13",
845
+ sentence: "Magic Context refused to start: its store (store.db) was migrated by a newer ck-mc build than the one running.",
846
+ action: "Update ck-mc, or roll back by restoring ck-mc together with context.db and store.db from the same backup."
847
+ },
848
+ compaction_marker_missing: {
849
+ code: "MC-C11",
850
+ sentence: "The history boundary marker is missing from the OpenCode store, so requests carry the full session.",
851
+ action: "It is retried on every message; if this persists, run `/ctx-flush`."
852
+ },
853
+ memory_mirror_stalled: {
854
+ code: "MC-M01",
855
+ sentence: "Memory synchronization stopped before the host mirror caught up.",
856
+ action: "Send another message to resume it, or run `ck doctor drain-authority`."
857
+ },
858
+ memory_authority_mismatch: {
859
+ code: "MC-M02",
860
+ sentence: "Memory authority is inconsistent between the host and module.",
861
+ action: "Run `ck doctor drain-authority` before changing Rust mode."
862
+ },
863
+ dreamer_task_failing: {
864
+ code: "MC-S05",
865
+ sentence: "A background maintenance task keeps failing on its schedule.",
866
+ action: "Check the Magic Context log for the failing task and its error."
867
+ }
868
+ };
869
+ function renderUserFacingFailure(key, style = "markdown") {
870
+ const failure = USER_FACING_FAILURES[key];
871
+ const action = style === "plain" ? failure.action.replaceAll("`", "") : failure.action;
872
+ return `${failure.sentence} ${action} (${failure.code})`;
873
+ }
874
+ function userFacingFailureCode(key) {
875
+ return USER_FACING_FAILURES[key].code;
876
+ }
877
+ var CAPABILITY_FAILURES = {
878
+ memory_write: "memory_writes_paused",
879
+ memory_access: "memory_access_unavailable",
880
+ note_change: "note_changes_paused",
881
+ note_access: "note_access_unavailable",
882
+ context_cleanup: "context_cleanup_paused",
883
+ partial_history: "partial_history_unavailable",
884
+ smart_note_condition: "smart_note_conditions_unavailable",
885
+ history_compression: "history_compression_paused",
886
+ context_service: "context_service_unavailable"
887
+ };
888
+ function renderCapabilityRefusal(capability) {
889
+ return renderUserFacingFailure(CAPABILITY_FAILURES[capability]);
890
+ }
891
+ var DREAM_FAILURE_KEYS = {
892
+ provider_timeout: "dream_provider_timeout",
893
+ provider_error: "dream_provider_error",
894
+ local_refusal: "dream_local_refusal",
895
+ step_limit: "dream_step_limit",
896
+ token_budget: "dream_token_budget",
897
+ empty_completion: "dream_empty_completion",
898
+ no_models: "dream_no_models",
899
+ child_aborted: "dream_child_aborted",
900
+ parse_failed: "dream_parse_failed",
901
+ unknown: "dream_unknown"
902
+ };
903
+ var EMBEDDING_FAILURE_KEYS = {
904
+ substitution_rejected: "embedding_substitution_rejected",
905
+ http_error: "embedding_http_error",
906
+ transport_error: "embedding_transport_error",
907
+ invalid_envelope: "embedding_invalid_envelope",
908
+ empty_result: "embedding_empty_result",
909
+ certification_refusal: "embedding_certification_refusal",
910
+ credential_required: "embedding_credential_required",
911
+ local_binding_missing: "embedding_local_binding_missing",
912
+ local_fs_unavailable: "embedding_local_fs_unavailable",
913
+ local_download_failure: "embedding_local_download_failure",
914
+ local_runtime_error: "embedding_local_runtime_error"
915
+ };
916
+ function renderDreamFailure(failureClass, style = "markdown", refusalReason) {
917
+ const rendered = renderUserFacingFailure(DREAM_FAILURE_KEYS[failureClass], style);
918
+ return failureClass === "local_refusal" && refusalReason ? `${rendered} Reason: ${sanitizeDiagnosticText(refusalReason).slice(0, 500)}` : rendered;
919
+ }
920
+ function dreamFailureCode(failureClass) {
921
+ return userFacingFailureCode(DREAM_FAILURE_KEYS[failureClass]);
922
+ }
923
+ function renderEmbeddingFailure(failureClass, style = "markdown") {
924
+ return renderUserFacingFailure(EMBEDDING_FAILURE_KEYS[failureClass], style);
925
+ }
926
+
927
+ // ../plugin/src/hooks/magic-context/single-store-refusal.ts
928
+ var SINGLE_STORE_MIGRATION_REQUIRED_CODE = "single_store_migration_required";
929
+ function renderSingleStoreMigrationRequiredRefusal() {
930
+ const failure = USER_FACING_FAILURES.single_store_migration_required;
931
+ return `${failure.sentence} ${failure.action} (${failure.code})`;
932
+ }
933
+
934
+ class SingleStoreMigrationRequiredError extends Error {
935
+ code = SINGLE_STORE_MIGRATION_REQUIRED_CODE;
936
+ constructor(options) {
937
+ super(renderSingleStoreMigrationRequiredRefusal(), options);
938
+ this.name = "SingleStoreMigrationRequiredError";
939
+ }
940
+ }
941
+ function projectNeedsSingleStoreMigration(db, projectPath) {
942
+ const table = db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'authority_managed'").get();
943
+ return Boolean(table && db.prepare("SELECT 1 FROM authority_managed WHERE project_path = ?").get(projectPath));
944
+ }
594
945
  // ../plugin/src/features/magic-context/memory/promotion.ts
595
946
  function isPromotableCategory(category) {
596
947
  return PROMOTABLE_CATEGORIES.some((promotableCategory) => promotableCategory === category);
@@ -1401,6 +1752,19 @@ function searchGitCommitsSync(db, projectPath, query, options) {
1401
1752
  for (const row of rows)
1402
1753
  bySha.set(row.sha, rowToCommit(row));
1403
1754
  }
1755
+ if (options.captureLanes) {
1756
+ const fts = [...bySha.values()].filter((commit) => ftsScores.has(commit.sha)).map((commit) => ({
1757
+ commit,
1758
+ matchType: "fts",
1759
+ score: (ftsScores.get(commit.sha) ?? 0) * singleSourcePenalty
1760
+ })).sort((a, b) => b.score - a.score || b.commit.committedAtMs - a.commit.committedAtMs).slice(0, 25);
1761
+ const vector = [...bySha.values()].filter((commit) => (semanticScores.get(commit.sha) ?? 0) > 0).map((commit) => ({
1762
+ commit,
1763
+ matchType: "semantic",
1764
+ score: semanticScores.get(commit.sha) ?? 0
1765
+ })).sort((a, b) => b.score - a.score || b.commit.committedAtMs - a.commit.committedAtMs).slice(0, 25);
1766
+ options.captureLanes(fts, vector);
1767
+ }
1404
1768
  const results = [];
1405
1769
  for (const [sha, commit] of bySha.entries()) {
1406
1770
  const sem = semanticScores.get(sha);
@@ -1630,6 +1994,280 @@ function sha256(value) {
1630
1994
  return createHash("sha256").update(value).digest("hex");
1631
1995
  }
1632
1996
 
1997
+ // ../plugin/src/hooks/magic-context/module-transport.ts
1998
+ import { join } from "node:path";
1999
+
2000
+ // ../plugin/src/hooks/magic-context/reply-pages.ts
2001
+ var MAX_REPLY_BYTES = 128 * 1024 * 1024;
2002
+ var MAX_PAGE_BYTES = 512 * 1024;
2003
+
2004
+ // ../plugin/src/hooks/magic-context/module-transport.ts
2005
+ function getDefaultSubcConnectionFile() {
2006
+ return join(getDataDir(), "cortexkit", "run", "subc-connection.json");
2007
+ }
2008
+
2009
+ // ../plugin/src/features/magic-context/search-rerank.ts
2010
+ var RERANK_MODEL = "gte-reranker-modernbert-base-f32";
2011
+ var RERANK_LANE_LIMIT = 25;
2012
+ var DEADLINE_MS = 1500;
2013
+ function isProseQuery(query) {
2014
+ const text = query.trim();
2015
+ if (!text || /[\n;]|^["'`]|["'`]$/.test(text))
2016
+ return false;
2017
+ if (/^(?:error\b|cannot\b|failed\b|panic\b|traceback\b|assertion\b|SQLITE_|TypeError\b|ReferenceError\b|SyntaxError\b)/i.test(text))
2018
+ return false;
2019
+ if (/\b(?:[A-Z][A-Z_]+:|\w*(?:Error|Exception):)|\bat\s+\S+\s*\(/.test(text))
2020
+ return false;
2021
+ const words = text.replace(/[?!.]$/, "").split(/\s+/);
2022
+ if (words.length < 3)
2023
+ return false;
2024
+ const plain = words.filter((word) => /^[a-zA-Z]+(?:['’-][a-zA-Z]+)*$/.test(word));
2025
+ if (/^(?:how|why|what|where|when|which|who)\b/i.test(text))
2026
+ return plain.length >= 3;
2027
+ return words.length >= 4 && plain.length >= 3 && !/[\\/]|::|=/.test(text);
2028
+ }
2029
+ function emptySearchLanes() {
2030
+ return {
2031
+ memory_fts: [],
2032
+ memory_vector: [],
2033
+ primer_fts: [],
2034
+ primer_vector: [],
2035
+ message_fts: [],
2036
+ chunk_vector: [],
2037
+ git_fts: [],
2038
+ git_vector: [],
2039
+ notes: []
2040
+ };
2041
+ }
2042
+ function searchResultKey(hit) {
2043
+ switch (hit.source) {
2044
+ case "memory":
2045
+ return `memory:${hit.memoryId}`;
2046
+ case "primer":
2047
+ return `primer:${hit.primerId}`;
2048
+ case "message":
2049
+ return `message:${hit.messageId}`;
2050
+ case "compartment":
2051
+ return `compartment:${hit.compartmentId}`;
2052
+ case "git_commit":
2053
+ return `git_commit:${hit.sha}`;
2054
+ case "note":
2055
+ return `note:${hit.noteId}`;
2056
+ }
2057
+ }
2058
+ function fuseSearchLanes(lanes) {
2059
+ const compartments = lanes.chunk_vector.filter((hit) => hit.source === "compartment");
2060
+ const fused = new Map;
2061
+ for (const [name, lane] of Object.entries(lanes)) {
2062
+ const seen = new Set;
2063
+ lane.slice(0, RERANK_LANE_LIMIT).forEach((original, index) => {
2064
+ const hit = name === "message_fts" && original.source === "message" ? compartments.find((chunk) => original.messageOrdinal >= chunk.startOrdinal && original.messageOrdinal <= chunk.endOrdinal) ?? original : original;
2065
+ const key = searchResultKey(hit);
2066
+ if (seen.has(key))
2067
+ return;
2068
+ seen.add(key);
2069
+ const prior = fused.get(key);
2070
+ const score = 1 / (60 + index + 1);
2071
+ if (prior)
2072
+ prior.score += score;
2073
+ else
2074
+ fused.set(key, { hit, score, order: fused.size });
2075
+ });
2076
+ }
2077
+ return [...fused.values()].sort((a, b) => b.score - a.score || a.order - b.order).slice(0, 20).map((row) => row.hit);
2078
+ }
2079
+ function truncateUtf8(text, bytes) {
2080
+ const buffer = Buffer.from(text);
2081
+ let end = Math.min(buffer.length, bytes);
2082
+ while (end > 0 && end < buffer.length && (buffer[end] & 192) === 128)
2083
+ end--;
2084
+ return buffer.subarray(0, end).toString("utf8");
2085
+ }
2086
+ function candidateText(location, title, body) {
2087
+ const header = `${truncateUtf8(location.replaceAll(`
2088
+ `, " "), 200)}
2089
+ ${truncateUtf8(title.replaceAll(`
2090
+ `, " "), 120)}
2091
+ `;
2092
+ return header + truncateUtf8(body, 1024 - Buffer.byteLength(header));
2093
+ }
2094
+
2095
+ class RerankFailure extends Error {
2096
+ reason;
2097
+ constructor(reason) {
2098
+ super(reason);
2099
+ this.reason = reason;
2100
+ }
2101
+ }
2102
+ function unwrap(value) {
2103
+ if (!value || typeof value !== "object")
2104
+ throw new RerankFailure("validation");
2105
+ const outer = value;
2106
+ const body = outer.result ?? outer;
2107
+ if (!body || typeof body !== "object")
2108
+ throw new RerankFailure("validation");
2109
+ if (body.error) {
2110
+ const error = body.error;
2111
+ throw new RerankFailure(error.code ?? "synapse_error");
2112
+ }
2113
+ return body;
2114
+ }
2115
+ function pinReranker(value) {
2116
+ const body = unwrap(value);
2117
+ const models = body.models;
2118
+ const model = Array.isArray(models) ? models.find((row) => row?.model_id === RERANK_MODEL) : null;
2119
+ if (model?.certified !== true || model.fingerprints?.length !== 1 || typeof model.fingerprints[0] !== "string" || !/^[a-f0-9]{64}$/.test(model.fingerprints[0]) || !Number.isSafeInteger(body.table_epoch))
2120
+ throw new RerankFailure("catalog_validation");
2121
+ return { fingerprint: model.fingerprints[0], tableEpoch: body.table_epoch };
2122
+ }
2123
+ var loggedReasons = new Set;
2124
+ function logRerankFallback(reason) {
2125
+ if (loggedReasons.has(reason))
2126
+ return;
2127
+ loggedReasons.add(reason);
2128
+ log2(`[ctx_search] rerank fallback (${reason}); retaining original ranking`);
2129
+ }
2130
+ function reasonOf(error) {
2131
+ if (error instanceof RerankFailure)
2132
+ return error.reason;
2133
+ if (error && typeof error === "object" && "code" in error) {
2134
+ const code = String(error.code);
2135
+ return ["ENOENT", "ECONNREFUSED"].includes(code) ? "missing_synapse" : code;
2136
+ }
2137
+ return "synapse_error";
2138
+ }
2139
+ async function bounded(promise) {
2140
+ let timer;
2141
+ try {
2142
+ return await Promise.race([
2143
+ promise,
2144
+ new Promise((_, reject) => {
2145
+ timer = setTimeout(() => reject(new RerankFailure("deadline_exceeded")), DEADLINE_MS);
2146
+ })
2147
+ ]);
2148
+ } finally {
2149
+ clearTimeout(timer);
2150
+ }
2151
+ }
2152
+ var connections = new Map;
2153
+ async function connect(connectionFile) {
2154
+ let connection = connections.get(connectionFile);
2155
+ if (!connection) {
2156
+ connection = SubcClient.connect({ connectionFile });
2157
+ connections.set(connectionFile, connection);
2158
+ connection.catch(() => connections.delete(connectionFile));
2159
+ }
2160
+ return bounded(connection);
2161
+ }
2162
+ async function prepareReranker(projectRoot, sessionId, connectionFile, injectedClient) {
2163
+ try {
2164
+ if (injectedClient === null)
2165
+ throw new RerankFailure("missing_synapse");
2166
+ const client = injectedClient ?? await connect(connectionFile ?? getDefaultSubcConnectionFile());
2167
+ const identity = {
2168
+ project_root: projectRoot,
2169
+ harness: "magic-context",
2170
+ session: sessionId
2171
+ };
2172
+ const lane = pinReranker(await bounded(client.call("synapse", "models.list", {}, { timeoutMs: DEADLINE_MS, targetKind: "management_surface", identity })));
2173
+ return { client, lane, identity };
2174
+ } catch (error) {
2175
+ logRerankFallback(reasonOf(error));
2176
+ return null;
2177
+ }
2178
+ }
2179
+ async function rerankSearchResults(session, query, baseline, pool, texts, limit) {
2180
+ if (!pool.length)
2181
+ return baseline;
2182
+ try {
2183
+ if (pool.length > 20 || texts.length !== pool.length || texts.some((text) => Buffer.byteLength(text) > 1024))
2184
+ throw new RerankFailure("validation");
2185
+ const body = unwrap(await bounded(session.client.call("synapse", "rerank.score", {
2186
+ model: RERANK_MODEL,
2187
+ query,
2188
+ candidates: texts,
2189
+ required_fingerprint: session.lane.fingerprint,
2190
+ allow_equivalent: false,
2191
+ accept_declared: false,
2192
+ max_queue_ms: 100,
2193
+ deadline_ms: DEADLINE_MS
2194
+ }, {
2195
+ timeoutMs: DEADLINE_MS,
2196
+ targetKind: "management_surface",
2197
+ identity: session.identity
2198
+ })));
2199
+ if (body.fingerprint !== session.lane.fingerprint)
2200
+ throw new RerankFailure("fingerprint_mismatch");
2201
+ if (body.table_epoch !== session.lane.tableEpoch)
2202
+ throw new RerankFailure("epoch_mismatch");
2203
+ if (!Array.isArray(body.scores) || body.scores.length !== pool.length || body.scores.some((score) => typeof score !== "number" || !Number.isFinite(score)))
2204
+ throw new RerankFailure("validation");
2205
+ const scores = body.scores;
2206
+ return pool.map((hit, index) => ({ hit, index, score: scores[index] })).sort((a, b) => b.score - a.score || a.index - b.index).slice(0, limit).map((row) => row.hit);
2207
+ } catch (error) {
2208
+ logRerankFallback(reasonOf(error));
2209
+ return baseline;
2210
+ }
2211
+ }
2212
+ function candidateTexts(db, sessionId, projectPath, pool) {
2213
+ return pool.map((hit) => {
2214
+ const id = searchResultKey(hit).split(":").slice(1).join(":");
2215
+ let location = `${hit.source} ${id} ${projectPath}`;
2216
+ let title = hit.content.split(`
2217
+ `)[0];
2218
+ let body = hit.content;
2219
+ switch (hit.source) {
2220
+ case "memory": {
2221
+ const row = db.prepare("SELECT content FROM memories WHERE id=?").get(hit.memoryId);
2222
+ body = row.content;
2223
+ title = body.split(`
2224
+ `)[0];
2225
+ break;
2226
+ }
2227
+ case "primer": {
2228
+ const row = db.prepare("SELECT question, answer FROM primers WHERE id=?").get(hit.primerId);
2229
+ title = row.question;
2230
+ body = `Q: ${row.question}
2231
+ A: ${row.answer}`;
2232
+ break;
2233
+ }
2234
+ case "git_commit": {
2235
+ const row = db.prepare("SELECT message FROM git_commits WHERE sha=?").get(hit.sha);
2236
+ body = row.message;
2237
+ title = `${hit.shortSha} ${body.split(`
2238
+ `)[0]}`;
2239
+ break;
2240
+ }
2241
+ case "note": {
2242
+ const row = db.prepare("SELECT content, ready_reason AS reason FROM notes WHERE id=?").get(hit.noteId);
2243
+ body = `${row.content}${row.reason ? `
2244
+ Reason: ${row.reason}` : ""}`;
2245
+ title = body.split(`
2246
+ `)[0];
2247
+ break;
2248
+ }
2249
+ case "message": {
2250
+ const mapped = db.prepare(`SELECT f.content FROM message_fts_rowid_map m
2251
+ JOIN message_history_fts f ON f.rowid=m.fts_rowid
2252
+ WHERE m.session_id=? AND m.message_ordinal=? AND f.message_id=?`).get(sessionId, hit.messageOrdinal, hit.messageId);
2253
+ const row = mapped ?? db.prepare("SELECT content FROM message_history_fts WHERE session_id=? AND message_id=? ORDER BY CAST(message_ordinal AS INTEGER) LIMIT 1").get(sessionId, hit.messageId);
2254
+ body = row.content;
2255
+ title = `${hit.role}: ${body.split(`
2256
+ `)[0]}`;
2257
+ location = `message ${hit.messageId} ${sessionId} @${hit.messageOrdinal}`;
2258
+ break;
2259
+ }
2260
+ case "compartment": {
2261
+ title = hit.title;
2262
+ location = `compartment ${hit.compartmentId} ${hit.sessionId} @${hit.startOrdinal}-${hit.endOrdinal}`;
2263
+ body = buildCanonicalChunkTextFromFts(db, hit.sessionId, hit.startOrdinal, hit.endOrdinal) ?? "";
2264
+ break;
2265
+ }
2266
+ }
2267
+ return candidateText(location, title, body);
2268
+ });
2269
+ }
2270
+
1633
2271
  // ../plugin/src/features/magic-context/search.ts
1634
2272
  var DEFAULT_UNIFIED_SEARCH_LIMIT = 10;
1635
2273
  var MAX_UNIFIED_SEARCH_LIMIT = 25;
@@ -1661,6 +2299,7 @@ function createUnifiedSearchDiagnostics2() {
1661
2299
  }
1662
2300
  function searchMessageHistory2(db, request) {
1663
2301
  const diagnostics = request.collectDiagnostics ? createUnifiedSearchDiagnostics2() : undefined;
2302
+ const capture = request.captureLimit ? { limit: request.captureLimit, results: [] } : undefined;
1664
2303
  const results = searchMessages({
1665
2304
  db,
1666
2305
  sessionId: request.sessionId,
@@ -1670,10 +2309,12 @@ function searchMessageHistory2(db, request) {
1670
2309
  probes: request.probes,
1671
2310
  relaxedRecall: request.relaxedRecall,
1672
2311
  diagnostics,
1673
- dateRange: request.dateRange
2312
+ dateRange: request.dateRange,
2313
+ capture
1674
2314
  });
1675
2315
  return {
1676
2316
  results,
2317
+ laneResults: capture?.results,
1677
2318
  suppressedLiveMessageMatches: diagnostics?.suppressedLiveMessageMatches ?? 0
1678
2319
  };
1679
2320
  }
@@ -2066,7 +2707,7 @@ function mergeMemoryResults(args) {
2066
2707
  score = SEMANTIC_WEIGHT * semanticScore + FTS_WEIGHT * ftsScore;
2067
2708
  matchType = "hybrid";
2068
2709
  } else if (semanticScore !== undefined) {
2069
- score = semanticScore * SINGLE_SOURCE_PENALTY;
2710
+ score = semanticScore * (args.singleSourcePenalty ?? SINGLE_SOURCE_PENALTY);
2070
2711
  matchType = "semantic";
2071
2712
  } else if (ftsScore !== undefined) {
2072
2713
  score = ftsScore * SINGLE_SOURCE_PENALTY;
@@ -2134,25 +2775,45 @@ async function searchMemories(args) {
2134
2775
  queryModelId: args.queryModelId,
2135
2776
  workspace: args.workspace
2136
2777
  });
2778
+ const sourceNameByMemoryId = sourceNamesForSearchMemories({
2779
+ memories,
2780
+ projectPath: args.projectPath,
2781
+ workspace: args.workspace ?? {
2782
+ identities: [args.projectPath],
2783
+ expandedIdentities: [args.projectPath],
2784
+ namesByIdentity: new Map,
2785
+ canonicalIdentityByStoredPath: new Map([[args.projectPath, args.projectPath]]),
2786
+ ownIdentities: [args.projectPath],
2787
+ shareCategories: null,
2788
+ isWorkspaced: false
2789
+ }
2790
+ });
2791
+ if (args.lanes) {
2792
+ args.lanes.memory_fts = mergeMemoryResults({
2793
+ memories,
2794
+ semanticScores: new Map,
2795
+ ftsScores,
2796
+ sourceNameByMemoryId,
2797
+ limit: 25,
2798
+ visibleMemoryIds: args.visibleMemoryIds
2799
+ }).results;
2800
+ args.lanes.memory_vector = mergeMemoryResults({
2801
+ memories,
2802
+ semanticScores,
2803
+ ftsScores: new Map,
2804
+ sourceNameByMemoryId,
2805
+ singleSourcePenalty: 1,
2806
+ limit: 25,
2807
+ visibleMemoryIds: args.visibleMemoryIds
2808
+ }).results;
2809
+ }
2137
2810
  return mergeMemoryResults({
2138
2811
  memories,
2139
2812
  semanticScores,
2140
2813
  ftsScores,
2141
2814
  limit: args.limit,
2142
2815
  visibleMemoryIds: args.visibleMemoryIds,
2143
- sourceNameByMemoryId: sourceNamesForSearchMemories({
2144
- memories,
2145
- projectPath: args.projectPath,
2146
- workspace: args.workspace ?? {
2147
- identities: [args.projectPath],
2148
- expandedIdentities: [args.projectPath],
2149
- namesByIdentity: new Map,
2150
- canonicalIdentityByStoredPath: new Map([[args.projectPath, args.projectPath]]),
2151
- ownIdentities: [args.projectPath],
2152
- shareCategories: null,
2153
- isWorkspaced: false
2154
- }
2155
- })
2816
+ sourceNameByMemoryId
2156
2817
  });
2157
2818
  }
2158
2819
  function linearDecayScore(rank, total) {
@@ -2285,7 +2946,9 @@ function searchMessages(args) {
2285
2946
  }
2286
2947
  function searchMessagesInSnapshot(args, sessionFirst) {
2287
2948
  const cutoff = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.maxOrdinal : null;
2288
- const fetchLimit = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.limit * 3 : args.limit;
2949
+ const baselineFetchLimit = cutoff !== null ? args.limit * 3 : args.limit;
2950
+ const captureFetchLimit = args.capture ? cutoff !== null ? args.capture.limit * 3 : args.capture.limit : 0;
2951
+ const fetchLimit = Math.max(baselineFetchLimit, captureFetchLimit);
2289
2952
  const baseQuery = sanitizeFtsQuery(args.query.trim());
2290
2953
  const probes = args.probes ?? [];
2291
2954
  if (probes.length === 0) {
@@ -2305,15 +2968,20 @@ function searchMessagesInSnapshot(args, sessionFirst) {
2305
2968
  args.diagnostics.suppressedLiveMessageMatches = outcome.suppressedCount;
2306
2969
  }
2307
2970
  const rows = outcome.rows.length > 0 || !args.relaxedRecall ? outcome.rows : runMessageFtsQuery(args.db, args.sessionId, relaxedFtsQuery(args.query), fetchLimit, cutoff, args.dateRange, sessionFirst);
2308
- const filtered = rows.slice(0, args.limit);
2309
- return filtered.map((row, rank) => ({
2310
- source: "message",
2311
- content: previewText(row.content),
2312
- score: linearDecayScore(rank, filtered.length),
2313
- messageOrdinal: row.messageOrdinal,
2314
- messageId: row.messageId,
2315
- role: row.role
2316
- }));
2971
+ const renderRows = (limit) => {
2972
+ const filtered = rows.slice(0, limit);
2973
+ return filtered.map((row, rank) => ({
2974
+ source: "message",
2975
+ content: previewText(row.content),
2976
+ score: linearDecayScore(rank, filtered.length),
2977
+ messageOrdinal: row.messageOrdinal,
2978
+ messageId: row.messageId,
2979
+ role: row.role
2980
+ }));
2981
+ };
2982
+ if (args.capture)
2983
+ args.capture.results = renderRows(args.capture.limit);
2984
+ return renderRows(args.limit);
2317
2985
  }
2318
2986
  const sanitizedProbes = probes.map((probe) => ({ probe, query: sanitizeFtsQuery(probe) })).filter((entry) => entry.query.length > 0);
2319
2987
  const corpusSize = getIndexedMessageCorpusSize(args.db, args.sessionId, cutoff);
@@ -2353,39 +3021,44 @@ function searchMessagesInSnapshot(args, sessionFirst) {
2353
3021
  queryLists.push({ rows: rowsByQuery[queryIndex] ?? [], weight });
2354
3022
  queryIndex += 1;
2355
3023
  });
2356
- const fused = new Map;
2357
- for (const list of queryLists) {
2358
- list.rows.forEach((row, rank) => {
2359
- const rrf = list.weight / (RRF_K + rank);
2360
- const existing = fused.get(row.messageId);
2361
- if (existing) {
2362
- existing.score += rrf;
2363
- } else {
2364
- fused.set(row.messageId, { row, score: rrf });
3024
+ const rankProbeLists = (rowLimit, resultLimit) => {
3025
+ const fused = new Map;
3026
+ for (const list of queryLists) {
3027
+ list.rows.slice(0, rowLimit).forEach((row, rank) => {
3028
+ const rrf = list.weight / (RRF_K + rank);
3029
+ const existing = fused.get(row.messageId);
3030
+ if (existing) {
3031
+ existing.score += rrf;
3032
+ } else {
3033
+ fused.set(row.messageId, { row, score: rrf });
3034
+ }
3035
+ });
3036
+ }
3037
+ for (const entry of fused.values()) {
3038
+ let best = 0;
3039
+ for (const probe of probes) {
3040
+ const weight = probeWeights.get(probe) ?? 0;
3041
+ if (weight > best && containsProbeVerbatim(entry.row.content, [probe])) {
3042
+ best = weight;
3043
+ }
2365
3044
  }
2366
- });
2367
- }
2368
- for (const entry of fused.values()) {
2369
- let best = 0;
2370
- for (const probe of probes) {
2371
- const weight = probeWeights.get(probe) ?? 0;
2372
- if (weight > best && containsProbeVerbatim(entry.row.content, [probe])) {
2373
- best = weight;
3045
+ if (best > 0) {
3046
+ entry.score += best * VERBATIM_RANK_BONUS;
2374
3047
  }
2375
3048
  }
2376
- if (best > 0) {
2377
- entry.score += best * VERBATIM_RANK_BONUS;
2378
- }
2379
- }
2380
- const ranked = [...fused.values()].sort((a, b) => b.score !== a.score ? b.score - a.score : a.row.messageOrdinal - b.row.messageOrdinal).slice(0, args.limit);
2381
- return ranked.map((entry, rank) => ({
2382
- source: "message",
2383
- content: previewText(entry.row.content),
2384
- score: linearDecayScore(rank, ranked.length),
2385
- messageOrdinal: entry.row.messageOrdinal,
2386
- messageId: entry.row.messageId,
2387
- role: entry.row.role
2388
- }));
3049
+ const ranked = [...fused.values()].sort((a, b) => b.score !== a.score ? b.score - a.score : a.row.messageOrdinal - b.row.messageOrdinal).slice(0, resultLimit);
3050
+ return ranked.map((entry, rank) => ({
3051
+ source: "message",
3052
+ content: previewText(entry.row.content),
3053
+ score: linearDecayScore(rank, ranked.length),
3054
+ messageOrdinal: entry.row.messageOrdinal,
3055
+ messageId: entry.row.messageId,
3056
+ role: entry.row.role
3057
+ }));
3058
+ };
3059
+ if (args.capture)
3060
+ args.capture.results = rankProbeLists(captureFetchLimit, args.capture.limit);
3061
+ return rankProbeLists(baselineFetchLimit, args.limit);
2389
3062
  }
2390
3063
  var NOTE_SEARCHABLE_STATUSES = ["active", "pending", "ready"];
2391
3064
  var MAX_NOTE_KEYWORD_SCORE = 3.5;
@@ -2655,12 +3328,17 @@ function toGitCommitResult(hit) {
2655
3328
  function searchGitCommits(args) {
2656
3329
  if (args.limit <= 0)
2657
3330
  return [];
3331
+ const lanes = args.lanes;
2658
3332
  const hits = searchGitCommitsSync(args.db, args.projectPath, args.query, {
2659
3333
  limit: args.limit,
2660
3334
  queryEmbedding: args.queryEmbedding,
2661
3335
  queryModelId: args.queryModelId,
2662
3336
  from: args.dateRange?.from,
2663
- to: args.dateRange?.to
3337
+ to: args.dateRange?.to,
3338
+ captureLanes: lanes ? (fts, vector) => {
3339
+ lanes.git_fts = fts.map(toGitCommitResult);
3340
+ lanes.git_vector = vector.map(toGitCommitResult);
3341
+ } : undefined
2664
3342
  });
2665
3343
  return hits.map(toGitCommitResult);
2666
3344
  }
@@ -2682,13 +3360,44 @@ function searchPrimers(args) {
2682
3360
  WHERE primers_fts MATCH ? AND p.project_path = ? AND p.status = 'active'
2683
3361
  ${args.dateRange === null ? "" : "AND p.created_at BETWEEN ? AND ?"}
2684
3362
  ORDER BY rank ASC
2685
- LIMIT ?`).all(ftsQuery, args.projectPath, ...args.dateRange === null ? [] : [args.dateRange.from, args.dateRange.to], args.limit * 3);
2686
- rows.forEach((row, index) => {
2687
- ftsRanks.set(row.id, linearDecayScore(index, rows.length));
3363
+ LIMIT ?`).all(ftsQuery, args.projectPath, ...args.dateRange === null ? [] : [args.dateRange.from, args.dateRange.to], args.lanes ? Math.max(args.limit * 3, 225) : args.limit * 3);
3364
+ const baselineRows = rows.slice(0, args.limit * 3);
3365
+ baselineRows.forEach((row, index) => {
3366
+ ftsRanks.set(row.id, linearDecayScore(index, baselineRows.length));
2688
3367
  });
3368
+ if (args.lanes) {
3369
+ const byId = new Map(primers.map((primer) => [primer.id, primer]));
3370
+ args.lanes.primer_fts = rows.flatMap((row, index) => {
3371
+ const primer = byId.get(row.id);
3372
+ return primer ? [
3373
+ {
3374
+ source: "primer",
3375
+ primerId: primer.id,
3376
+ content: previewText(primerText(primer)),
3377
+ question: primer.question,
3378
+ support: primer.totalSupport,
3379
+ lastObservedAt: primer.lastObservedAt,
3380
+ matchType: "fts",
3381
+ score: linearDecayScore(index, rows.length)
3382
+ }
3383
+ ] : [];
3384
+ }).slice(0, 25);
3385
+ }
2689
3386
  }
3387
+ const vectorResults = [];
2690
3388
  const scored = primers.map((primer) => {
2691
3389
  const semantic = args.queryEmbedding && primer.questionEmbedding && primer.questionEmbeddingModelId === args.queryModelId ? normalizeCosineScore(cosineSimilarity(args.queryEmbedding, primer.questionEmbedding)) : 0;
3390
+ if (args.lanes && semantic > 0)
3391
+ vectorResults.push({
3392
+ source: "primer",
3393
+ primerId: primer.id,
3394
+ content: previewText(primerText(primer)),
3395
+ question: primer.question,
3396
+ support: primer.totalSupport,
3397
+ lastObservedAt: primer.lastObservedAt,
3398
+ matchType: "semantic",
3399
+ score: semantic
3400
+ });
2692
3401
  const fts = ftsRanks.get(primer.id) ?? 0;
2693
3402
  if (semantic <= 0 && fts <= 0)
2694
3403
  return null;
@@ -2704,6 +3413,8 @@ function searchPrimers(args) {
2704
3413
  matchType: semantic > 0 && fts > 0 ? "hybrid" : semantic > 0 ? "semantic" : "fts"
2705
3414
  };
2706
3415
  }).filter((result) => result !== null).sort((a, b) => b.score - a.score || b.support - a.support || a.primerId - b.primerId).slice(0, args.limit);
3416
+ if (args.lanes)
3417
+ args.lanes.primer_vector = vectorResults.sort((a, b) => b.score - a.score || b.support - a.support || a.primerId - b.primerId).slice(0, 25);
2707
3418
  return scored;
2708
3419
  }
2709
3420
  function resolveSources(sources) {
@@ -2781,6 +3492,8 @@ async function unifiedSearch2(db, sessionId, projectPath, query, options = {}) {
2781
3492
  return [];
2782
3493
  }
2783
3494
  const limit = normalizeLimit(options.limit);
3495
+ const reranker = options.explicitSearch && options.rerank !== false && isProseQuery(trimmedQuery) ? await prepareReranker(projectPath, sessionId, options.rerankConnectionFile, options.rerankClient) : null;
3496
+ const lanes = reranker || options.captureRerankLanes ? emptySearchLanes() : undefined;
2784
3497
  const dateRange = normalizeDateRange(options.from, options.to);
2785
3498
  const tierLimit = Math.max(limit * 3, DEFAULT_UNIFIED_SEARCH_LIMIT);
2786
3499
  if (options.diagnostics) {
@@ -2818,6 +3531,7 @@ async function unifiedSearch2(db, sessionId, projectPath, query, options = {}) {
2818
3531
  sessionId,
2819
3532
  query: trimmedQuery,
2820
3533
  limit: tierLimit,
3534
+ captureLimit: lanes ? 75 : undefined,
2821
3535
  maxOrdinal: options.maxMessageOrdinal,
2822
3536
  probes: messageProbes,
2823
3537
  relaxedRecall: options.explicitSearch,
@@ -2835,6 +3549,8 @@ async function unifiedSearch2(db, sessionId, projectPath, query, options = {}) {
2835
3549
  options.diagnostics.suppressedLiveMessageMatches = outcome.suppressedLiveMessageMatches;
2836
3550
  }
2837
3551
  messageResults = outcome.results;
3552
+ if (lanes)
3553
+ lanes.message_fts = (outcome.laneResults ?? outcome.results).slice(0, 25);
2838
3554
  }
2839
3555
  const capturedQuery = await queryEmbeddingPromise;
2840
3556
  if (options.signal?.aborted)
@@ -2851,14 +3567,16 @@ async function unifiedSearch2(db, sessionId, projectPath, query, options = {}) {
2851
3567
  sessionId,
2852
3568
  projectPath,
2853
3569
  queryEmbedding,
2854
- limit: tierLimit,
3570
+ limit: lanes ? Math.max(tierLimit, 25) : tierLimit,
2855
3571
  maxOrdinal: options.maxMessageOrdinal,
2856
3572
  modelId: chunkModelId && chunkModelId !== "off" ? chunkModelId : null,
2857
3573
  dateRange
2858
3574
  }) : [];
3575
+ if (lanes)
3576
+ lanes.chunk_vector = compartmentResults.slice(0, 25);
2859
3577
  const messageLikeResults = mergeMessageAndCompartmentResults({
2860
3578
  messages: messageResults,
2861
- compartments: compartmentResults,
3579
+ compartments: compartmentResults.slice(0, tierLimit),
2862
3580
  limit: tierLimit
2863
3581
  });
2864
3582
  const [memoryOutcome, gitCommitResults, primerResults, noteResults] = await Promise.all([
@@ -2873,6 +3591,7 @@ async function unifiedSearch2(db, sessionId, projectPath, query, options = {}) {
2873
3591
  workspace,
2874
3592
  visibleMemoryIds: options.visibleMemoryIds,
2875
3593
  backfillMemoryEmbeddings: options.backfillMemoryEmbeddings,
3594
+ lanes,
2876
3595
  dateRange
2877
3596
  }) : Promise.resolve({
2878
3597
  results: [],
@@ -2885,7 +3604,8 @@ async function unifiedSearch2(db, sessionId, projectPath, query, options = {}) {
2885
3604
  limit: tierLimit,
2886
3605
  queryEmbedding,
2887
3606
  queryModelId: embeddingModelId && embeddingModelId !== "off" ? embeddingModelId : null,
2888
- dateRange
3607
+ dateRange,
3608
+ lanes
2889
3609
  })) : Promise.resolve([]),
2890
3610
  runPrimers ? Promise.resolve(searchPrimers({
2891
3611
  db,
@@ -2894,14 +3614,15 @@ async function unifiedSearch2(db, sessionId, projectPath, query, options = {}) {
2894
3614
  limit: tierLimit,
2895
3615
  queryEmbedding,
2896
3616
  queryModelId: embeddingModelId && embeddingModelId !== "off" ? embeddingModelId : null,
2897
- dateRange
3617
+ dateRange,
3618
+ lanes
2898
3619
  })) : Promise.resolve([]),
2899
3620
  runNotes ? Promise.resolve(searchNotes({
2900
3621
  db,
2901
3622
  sessionId,
2902
3623
  projectPath,
2903
3624
  query: trimmedQuery,
2904
- limit: tierLimit,
3625
+ limit: lanes ? Math.max(tierLimit, 25) : tierLimit,
2905
3626
  probes: messageProbes,
2906
3627
  dateRange
2907
3628
  })) : Promise.resolve([])
@@ -2909,23 +3630,37 @@ async function unifiedSearch2(db, sessionId, projectPath, query, options = {}) {
2909
3630
  if (options.diagnostics) {
2910
3631
  options.diagnostics.suppressedVisibleMemoryIds = memoryOutcome.suppressedVisibleIds;
2911
3632
  }
2912
- const results = [
3633
+ let results = [
2913
3634
  ...memoryOutcome.results,
2914
3635
  ...primerResults,
2915
3636
  ...messageLikeResults,
2916
3637
  ...gitCommitResults,
2917
3638
  ...noteResults
2918
3639
  ].sort(compareUnifiedResults).slice(0, limit);
3640
+ const originalResults = results;
3641
+ const originalLatencyMs = Date.now() - measurementStartedAt;
3642
+ if (lanes) {
3643
+ lanes.notes = noteResults.slice(0, 25);
3644
+ options.captureRerankLanes?.(lanes);
3645
+ }
3646
+ if (reranker && lanes) {
3647
+ const pool = fuseSearchLanes(lanes);
3648
+ try {
3649
+ results = await rerankSearchResults(reranker, trimmedQuery, results, pool, candidateTexts(db, sessionId, projectPath, pool), limit);
3650
+ } catch {
3651
+ logRerankFallback("candidate_validation");
3652
+ }
3653
+ }
2919
3654
  if (!options.measurementDisabled) {
2920
3655
  recordShadowMeasurement({
2921
3656
  db,
2922
3657
  sessionId,
2923
3658
  projectPath,
2924
3659
  query: trimmedQuery,
2925
- options,
2926
- primaryResults: results,
3660
+ options: { ...options, rerank: false, captureRerankLanes: undefined },
3661
+ primaryResults: originalResults,
2927
3662
  primaryQuery: queryContract,
2928
- primaryLatencyMs: Date.now() - measurementStartedAt,
3663
+ primaryLatencyMs: originalLatencyMs,
2929
3664
  search: unifiedSearch2
2930
3665
  });
2931
3666
  }
@@ -3066,4 +3801,4 @@ ${bodyParts.join(`
3066
3801
  `)}`;
3067
3802
  }
3068
3803
 
3069
- export { getNoteByIdInScope, getNotes, addNote, getSessionNotes, getPendingSmartNotes, getReadySmartNotes, updateNote, dismissNotes, dismissNote, markNoteReady, markNoteChecked, PRIMER_CANDIDATE_TTL_MS, PRIMER_CANDIDATE_MAX_AGE_MS, primerOccurrenceKey, primerOccurrenceUtcDay, insertPrimerCandidates, updatePrimerCandidateEmbedding, getPrimerCandidatesByIds, getPrimerCandidatesForPromotion, countPrimerCandidatesForProject, getActivePrimers, createPrimer, updatePrimerSupport, updatePrimerAnswer, promoteSessionFactsDurable, embedPromotedFacts, recordMemoryMapping, recordMemoryVerifications, getUnmappedMemoryIds, clearMemoryVerifications, getMemoryVerifications, resolveGitTopLevel, readGitHead, readGitChangedFilesSince, readGitFileChangeTimesSince, verificationFileExists, normalizeVerificationFiles, indexCommitsForProject, embedUnembeddedCommits, createUnifiedSearchDiagnostics2, searchMessageHistory2, parseIdShapedQuery2, resolveMemoriesByIdsForSearch2, unifiedSearch2, formatSearchResults2 };
3804
+ export { getNoteByIdInScope, getNotes, addNote, getSessionNotes, getPendingSmartNotes, getReadySmartNotes, updateNote, dismissNotes, dismissNote, markNoteReady, markNoteChecked, PRIMER_CANDIDATE_TTL_MS, PRIMER_CANDIDATE_MAX_AGE_MS, primerOccurrenceKey, primerOccurrenceUtcDay, insertPrimerCandidates, updatePrimerCandidateEmbedding, getPrimerCandidatesByIds, getPrimerCandidatesForPromotion, countPrimerCandidatesForProject, getActivePrimers, createPrimer, updatePrimerSupport, updatePrimerAnswer, USER_FACING_FAILURES, renderUserFacingFailure, userFacingFailureCode, renderCapabilityRefusal, renderDreamFailure, dreamFailureCode, renderEmbeddingFailure, renderSingleStoreMigrationRequiredRefusal, SingleStoreMigrationRequiredError, projectNeedsSingleStoreMigration, promoteSessionFactsDurable, embedPromotedFacts, recordMemoryMapping, recordMemoryVerifications, getUnmappedMemoryIds, clearMemoryVerifications, getMemoryVerifications, resolveGitTopLevel, readGitHead, readGitChangedFilesSince, readGitFileChangeTimesSince, verificationFileExists, normalizeVerificationFiles, indexCommitsForProject, embedUnembeddedCommits, createUnifiedSearchDiagnostics2, searchMessageHistory2, parseIdShapedQuery2, resolveMemoriesByIdsForSearch2, unifiedSearch2, formatSearchResults2 };