sift-light 1.0.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 (145) hide show
  1. package/CHANGELOG.md +0 -0
  2. package/CONTRIBUTING.md +19 -0
  3. package/LICENSE +661 -0
  4. package/README.md +177 -0
  5. package/README.zh-CN.md +177 -0
  6. package/SECURITY.md +25 -0
  7. package/package.json +142 -0
  8. package/plugins/sift-light/.claude-plugin/plugin.json +10 -0
  9. package/plugins/sift-light/.codex-plugin/plugin.json +20 -0
  10. package/plugins/sift-light/.mcp.json +24 -0
  11. package/plugins/sift-light/LICENSE +661 -0
  12. package/plugins/sift-light/concept-worker.mjs +567 -0
  13. package/plugins/sift-light/hooks/THIRD_PARTY_NOTICES.txt +70 -0
  14. package/plugins/sift-light/hooks/hooks.json +16 -0
  15. package/plugins/sift-light/hooks/search-policy.mjs +4113 -0
  16. package/plugins/sift-light/hooks/tree-sitter-bash.wasm +0 -0
  17. package/plugins/sift-light/hooks/tree-sitter-powershell.wasm +0 -0
  18. package/plugins/sift-light/hooks/tree-sitter.wasm +0 -0
  19. package/plugins/sift-light/kimi.plugin.json +36 -0
  20. package/plugins/sift-light/mcp-server.mjs +1 -0
  21. package/plugins/sift-light/omp-extension.mjs +20914 -0
  22. package/plugins/sift-light/package.json +11 -0
  23. package/plugins/sift-light/syntax-worker.mjs +280 -0
  24. package/plugins/sift-light/syntax-worker.toml +2 -0
  25. package/src/analysis-evidence.ts +43 -0
  26. package/src/analysis-limits.ts +27 -0
  27. package/src/analysis-store.ts +559 -0
  28. package/src/analysis-term-pages.ts +73 -0
  29. package/src/analysis-types.ts +162 -0
  30. package/src/audit-search.ts +391 -0
  31. package/src/capped-lines.ts +112 -0
  32. package/src/concept-embedding-cache.ts +186 -0
  33. package/src/concept-inference.ts +218 -0
  34. package/src/concept-model.ts +96 -0
  35. package/src/concept-search.ts +577 -0
  36. package/src/concept-setup.ts +75 -0
  37. package/src/concept-source-generation.ts +268 -0
  38. package/src/concept-worker.mjs +567 -0
  39. package/src/concept-worker.ts +210 -0
  40. package/src/config-reader.ts +283 -0
  41. package/src/config.ts +37 -0
  42. package/src/context-budget.ts +26 -0
  43. package/src/discovery-errors.ts +2 -0
  44. package/src/errors.ts +95 -0
  45. package/src/evidence-candidates.ts +344 -0
  46. package/src/evidence-ranking.ts +48 -0
  47. package/src/evidence-service.ts +1047 -0
  48. package/src/evidence-validation.ts +466 -0
  49. package/src/evidence-validity.ts +33 -0
  50. package/src/excerpt.ts +53 -0
  51. package/src/file-discovery.ts +150 -0
  52. package/src/file-metadata-filter.ts +46 -0
  53. package/src/format.ts +407 -0
  54. package/src/git-diff.ts +195 -0
  55. package/src/git-process.ts +189 -0
  56. package/src/git-repository.ts +367 -0
  57. package/src/git-source.ts +385 -0
  58. package/src/historical-paths.ts +205 -0
  59. package/src/hybrid-search.ts +340 -0
  60. package/src/import-model.ts +611 -0
  61. package/src/import-navigation.ts +100 -0
  62. package/src/import-resolution.ts +240 -0
  63. package/src/index.ts +97 -0
  64. package/src/inspect-batch.ts +265 -0
  65. package/src/inspect.ts +271 -0
  66. package/src/language-capabilities.ts +157 -0
  67. package/src/language-capability-definitions.ts +204 -0
  68. package/src/literal-search.ts +25 -0
  69. package/src/mcp-cli.ts +21 -0
  70. package/src/mcp-model-output.ts +120 -0
  71. package/src/mcp-output.ts +9 -0
  72. package/src/mcp-semantic-judge.ts +39 -0
  73. package/src/mcp-server.mjs +14064 -0
  74. package/src/mcp-server.ts +157 -0
  75. package/src/mcp-stdio.ts +114 -0
  76. package/src/mcp.ts +631 -0
  77. package/src/model-error.ts +120 -0
  78. package/src/multi-term-search.ts +122 -0
  79. package/src/omp-index.ts +277 -0
  80. package/src/omp-marketplace-entry.ts +7 -0
  81. package/src/operation-lifecycle.ts +413 -0
  82. package/src/operation-output.ts +100 -0
  83. package/src/owned-parallel.ts +22 -0
  84. package/src/owned-process.ts +102 -0
  85. package/src/owned-task-queue.ts +38 -0
  86. package/src/package-version.ts +3 -0
  87. package/src/path-policy.ts +203 -0
  88. package/src/pi-search-policy.ts +33 -0
  89. package/src/prompt-guidelines.ts +54 -0
  90. package/src/python-outline.ts +231 -0
  91. package/src/record-value.ts +3 -0
  92. package/src/redaction.ts +95 -0
  93. package/src/request-contract-catalog.ts +215 -0
  94. package/src/request-contract-error.ts +96 -0
  95. package/src/request-contract.ts +481 -0
  96. package/src/request.ts +132 -0
  97. package/src/result-statistics.ts +178 -0
  98. package/src/rg.ts +574 -0
  99. package/src/ripgrep-diagnostics.ts +122 -0
  100. package/src/ripgrep-executable.ts +43 -0
  101. package/src/runtime.ts +53 -0
  102. package/src/scan-revisions.ts +148 -0
  103. package/src/script-runtime.ts +11 -0
  104. package/src/search-policy-commands.ts +170 -0
  105. package/src/search-policy-hook.ts +61 -0
  106. package/src/search-policy-recovery.ts +388 -0
  107. package/src/search-policy-shell.ts +280 -0
  108. package/src/search-policy.ts +102 -0
  109. package/src/search-retention.ts +77 -0
  110. package/src/semantic-judge-batches.ts +135 -0
  111. package/src/semantic-judge.ts +519 -0
  112. package/src/service.ts +945 -0
  113. package/src/session-summary.ts +100 -0
  114. package/src/snapshot-store.ts +203 -0
  115. package/src/source-access.ts +288 -0
  116. package/src/source-continuations.ts +168 -0
  117. package/src/source-document.ts +277 -0
  118. package/src/source-inspection.ts +731 -0
  119. package/src/source-pages.ts +112 -0
  120. package/src/source.ts +286 -0
  121. package/src/structural-search.ts +125 -0
  122. package/src/structure.ts +259 -0
  123. package/src/summary-previews.ts +96 -0
  124. package/src/summary.ts +79 -0
  125. package/src/syntax-facts.ts +464 -0
  126. package/src/syntax-fields.ts +161 -0
  127. package/src/syntax-search.ts +361 -0
  128. package/src/syntax-tree.ts +30 -0
  129. package/src/syntax-types.ts +72 -0
  130. package/src/syntax-worker.mjs +280 -0
  131. package/src/syntax-worker.toml +2 -0
  132. package/src/syntax-worker.ts +143 -0
  133. package/src/syntax.ts +259 -0
  134. package/src/test-navigation-facts.ts +261 -0
  135. package/src/test-navigation.ts +543 -0
  136. package/src/tool-schema.ts +321 -0
  137. package/src/tui/dashboard.ts +107 -0
  138. package/src/tui/layout.ts +291 -0
  139. package/src/tui/palette.ts +73 -0
  140. package/src/tui/presentation.ts +240 -0
  141. package/src/tui/renderers.ts +106 -0
  142. package/src/types.ts +368 -0
  143. package/src/validation-output.ts +148 -0
  144. package/src/validation-types.ts +48 -0
  145. package/src/workspace-files.ts +142 -0
@@ -0,0 +1,178 @@
1
+ import type { AnalysisItem } from "./analysis-types.js";
2
+ import type {
3
+ ResultStatistics,
4
+ SearchSnapshot,
5
+ StatisticsEntry,
6
+ StatisticsGroup,
7
+ } from "./types.js";
8
+
9
+ const MAX_BREAKDOWN_ENTRIES = 5;
10
+ const MAX_TOP_FILES = 8;
11
+
12
+ type CountMap = Map<string, number>;
13
+
14
+ function normalizedPath(value: string): string {
15
+ return value.replaceAll("\\", "/");
16
+ }
17
+
18
+ function extensionOf(value: string): string {
19
+ const path = normalizedPath(value);
20
+ const slash = path.lastIndexOf("/");
21
+ const basename = path.slice(slash + 1);
22
+ const dot = basename.lastIndexOf(".");
23
+ if (dot <= 0) return "[no extension]";
24
+ return basename.slice(dot).toLowerCase();
25
+ }
26
+
27
+ function directoryOf(value: string): string {
28
+ const path = normalizedPath(value);
29
+ const slash = path.lastIndexOf("/");
30
+ return slash < 0 ? "." : `${path.slice(0, slash)}/`;
31
+ }
32
+
33
+ function rankedEntries(counts: CountMap): StatisticsEntry[] {
34
+ return [...counts.entries()]
35
+ .map(([label, count]) => ({ label, count }))
36
+ .toSorted((left, right) => right.count - left.count || left.label.localeCompare(right.label));
37
+ }
38
+
39
+ function group(dimension: string, counts: CountMap): StatisticsGroup | undefined {
40
+ const ranked = rankedEntries(counts);
41
+ if (!ranked.length) return undefined;
42
+ return {
43
+ dimension,
44
+ entries: ranked.slice(0, MAX_BREAKDOWN_ENTRIES),
45
+ omitted: Math.max(0, ranked.length - MAX_BREAKDOWN_ENTRIES),
46
+ total: ranked.reduce((sum, entry) => sum + entry.count, 0),
47
+ };
48
+ }
49
+
50
+ function fileCountsFromItems(items: readonly AnalysisItem[]): CountMap {
51
+ const counts: CountMap = new Map();
52
+ for (const item of items) counts.set(item.path, (counts.get(item.path) ?? 0) + 1);
53
+ return counts;
54
+ }
55
+
56
+ function pathsFromCounts(counts: CountMap): string[] {
57
+ return [...counts.keys()];
58
+ }
59
+
60
+ function createStatistics(
61
+ unit: string,
62
+ total: number,
63
+ fileCounts: CountMap,
64
+ extraGroups: readonly StatisticsGroup[] = [],
65
+ ): ResultStatistics {
66
+ const extensionCounts: CountMap = new Map();
67
+ const directoryCounts: CountMap = new Map();
68
+ for (const path of pathsFromCounts(fileCounts)) {
69
+ extensionCounts.set(
70
+ extensionOf(path),
71
+ (extensionCounts.get(extensionOf(path)) ?? 0) + (fileCounts.get(path) ?? 0),
72
+ );
73
+ directoryCounts.set(
74
+ directoryOf(path),
75
+ (directoryCounts.get(directoryOf(path)) ?? 0) + (fileCounts.get(path) ?? 0),
76
+ );
77
+ }
78
+ const groups = [
79
+ group("file type", extensionCounts),
80
+ group("directory", directoryCounts),
81
+ ...extraGroups,
82
+ ].filter((entry): entry is StatisticsGroup => entry !== undefined);
83
+ const rankedFiles = rankedEntries(fileCounts);
84
+ return {
85
+ unit,
86
+ total,
87
+ files: fileCounts.size,
88
+ directories: new Set(pathsFromCounts(fileCounts).map(directoryOf)).size,
89
+ groups,
90
+ topFiles: rankedFiles.slice(0, MAX_TOP_FILES),
91
+ topFilesOmitted: Math.max(0, rankedFiles.length - MAX_TOP_FILES),
92
+ };
93
+ }
94
+
95
+ export function statisticsForSnapshot(snapshot: SearchSnapshot): ResultStatistics {
96
+ return createStatistics("matches", snapshot.totalMatches, new Map(snapshot.fileCounts));
97
+ }
98
+
99
+ export function statisticsForItems(
100
+ items: readonly AnalysisItem[],
101
+ total: number,
102
+ unit: string,
103
+ extraGroups: readonly StatisticsGroup[] = [],
104
+ ): ResultStatistics {
105
+ return createStatistics(unit, total, fileCountsFromItems(items), extraGroups);
106
+ }
107
+
108
+ export function statisticsGroup(
109
+ dimension: string,
110
+ entries: readonly StatisticsEntry[],
111
+ ): StatisticsGroup | undefined {
112
+ if (!entries.length) return undefined;
113
+ const ranked = [...entries].toSorted(
114
+ (left, right) => right.count - left.count || left.label.localeCompare(right.label),
115
+ );
116
+ return {
117
+ dimension,
118
+ entries: ranked.slice(0, MAX_BREAKDOWN_ENTRIES),
119
+ omitted: Math.max(0, ranked.length - MAX_BREAKDOWN_ENTRIES),
120
+ total: ranked.reduce((sum, entry) => sum + entry.count, 0),
121
+ };
122
+ }
123
+
124
+ export function formatStatistics(
125
+ statistics: ResultStatistics,
126
+ options: { includeTopFiles?: boolean } = {},
127
+ ): string[] {
128
+ const lines = [
129
+ `Result: ${String(statistics.total)} ${statistics.unit} across ${String(statistics.files)} files and ${String(statistics.directories)} directories.`,
130
+ ];
131
+ for (const breakdown of statistics.groups) {
132
+ const entries = breakdown.entries
133
+ .map((entry) => `${entry.label}=${String(entry.count)}`)
134
+ .join(", ");
135
+ const omitted = breakdown.omitted > 0 ? `, +${String(breakdown.omitted)} other categories` : "";
136
+ lines.push(`By ${breakdown.dimension}: ${entries}${omitted}`);
137
+ }
138
+ if (options.includeTopFiles !== false && statistics.topFiles.length) {
139
+ lines.push(
140
+ `Top files: ${statistics.topFiles.map((entry) => `${entry.label}=${String(entry.count)}`).join(", ")}${statistics.topFilesOmitted > 0 ? `, +${String(statistics.topFilesOmitted)} other files` : ""}`,
141
+ );
142
+ }
143
+ return lines;
144
+ }
145
+
146
+ export function analysisExtraGroups(
147
+ counts: Record<string, number> | undefined,
148
+ termCounts: readonly { retainedOccurrences: number }[] | undefined,
149
+ items: readonly AnalysisItem[],
150
+ ): StatisticsGroup[] {
151
+ const groups: StatisticsGroup[] = [];
152
+ const classification = counts
153
+ ? statisticsGroup(
154
+ "classification",
155
+ Object.entries(counts).map(([label, count]) => ({ label, count })),
156
+ )
157
+ : undefined;
158
+ if (classification) groups.push(classification);
159
+ const terms = termCounts
160
+ ? statisticsGroup(
161
+ "conditions",
162
+ termCounts.map((term, index) => ({
163
+ label: `condition #${String(index + 1)}`,
164
+ count: term.retainedOccurrences,
165
+ })),
166
+ )
167
+ : undefined;
168
+ if (terms) groups.push(terms);
169
+ const evidence = new Map<string, number>();
170
+ for (const item of items) {
171
+ const source = item.details?.source;
172
+ if (source === "literal" || source === "concept")
173
+ evidence.set(source, (evidence.get(source) ?? 0) + 1);
174
+ }
175
+ const evidenceGroup = group("evidence", evidence);
176
+ if (evidenceGroup) groups.push(evidenceGroup);
177
+ return groups;
178
+ }