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,261 @@
1
+ import { literalText, nodeText, type ModuleFacts } from "./import-model.js";
2
+ import { syntaxField } from "./syntax-tree.js";
3
+
4
+ const FUNCTIONS = new Set([
5
+ "function_declaration",
6
+ "function_expression",
7
+ "generator_function_declaration",
8
+ "generator_function",
9
+ "arrow_function",
10
+ "method_definition",
11
+ ]);
12
+ const SCOPES = new Set([
13
+ ...FUNCTIONS,
14
+ "program",
15
+ "statement_block",
16
+ "catch_clause",
17
+ "for_statement",
18
+ "for_in_statement",
19
+ "class_body",
20
+ ]);
21
+ const TEST_NAMES = new Set(["test", "it", "describe"]);
22
+ const FRAMEWORKS = new Map([
23
+ ["node:test", "node:test"],
24
+ ["bun:test", "bun:test"],
25
+ ["vitest", "Vitest"],
26
+ ["@jest/globals", "Jest"],
27
+ ]);
28
+
29
+ export interface TestCaseFact {
30
+ node: number;
31
+ name?: string;
32
+ callback?: number;
33
+ framework?: string;
34
+ testKind: string;
35
+ modifiers: string[];
36
+ status: "recognized" | "syntax-candidate";
37
+ notes: string[];
38
+ }
39
+ interface LocalBinding {
40
+ name: string;
41
+ node: number;
42
+ scope: number;
43
+ }
44
+
45
+ function nearestScope(
46
+ facts: ModuleFacts,
47
+ node: number | null | undefined,
48
+ functionOnly = false,
49
+ ): number {
50
+ let current = node;
51
+ while (current !== null && current !== undefined) {
52
+ const value = facts.syntax.nodes[current];
53
+ if (!value) break;
54
+ if (
55
+ functionOnly ? FUNCTIONS.has(value.kind) || value.kind === "program" : SCOPES.has(value.kind)
56
+ )
57
+ return current;
58
+ current = value.parent;
59
+ }
60
+ return 0;
61
+ }
62
+
63
+ function patternIdentifiers(facts: ModuleFacts, root: number | undefined): number[] {
64
+ if (root === undefined) return [];
65
+ const output: number[] = [];
66
+ const pending = [root];
67
+ while (pending.length) {
68
+ const id = pending.pop();
69
+ if (id === undefined) break;
70
+ const node = facts.syntax.nodes[id];
71
+ if (
72
+ !node ||
73
+ node.field === "type" ||
74
+ (node.field === "value" && facts.syntax.nodes[node.parent ?? -1]?.kind !== "pair_pattern") ||
75
+ node.field === "right" ||
76
+ node.field === "key" ||
77
+ node.kind === "type_annotation"
78
+ )
79
+ continue;
80
+ if (node.kind === "identifier" || node.kind === "shorthand_property_identifier_pattern")
81
+ output.push(id);
82
+ else pending.push(...(facts.syntax.children[id] ?? []));
83
+ }
84
+ return output;
85
+ }
86
+
87
+ /** Lexical ownership only. This intentionally makes no type/runtime binding claim. */
88
+ export class TestBindings {
89
+ readonly facts: ModuleFacts;
90
+ #bindings = new Map<string, LocalBinding[]>();
91
+ #declarations = new Set<number>();
92
+ constructor(facts: ModuleFacts) {
93
+ this.facts = facts;
94
+ const add = (ids: number[], scope: number): void => {
95
+ for (const node of ids) {
96
+ this.#declarations.add(node);
97
+ const name = nodeText(facts, node) ?? "";
98
+ const values = this.#bindings.get(name) ?? [];
99
+ values.push({ name, node, scope });
100
+ this.#bindings.set(name, values);
101
+ }
102
+ };
103
+ for (let id = 0; id < facts.syntax.nodes.length; id++) {
104
+ const node = facts.syntax.nodes[id];
105
+ if (!node) continue;
106
+ if (node.kind === "variable_declarator") {
107
+ const parent = node.parent === null ? undefined : facts.syntax.nodes[node.parent];
108
+ add(
109
+ patternIdentifiers(facts, syntaxField(facts.syntax, id, "name")),
110
+ nearestScope(facts, node.parent, parent?.kind === "variable_declaration"),
111
+ );
112
+ }
113
+ if (FUNCTIONS.has(node.kind)) {
114
+ add(
115
+ patternIdentifiers(
116
+ facts,
117
+ syntaxField(facts.syntax, id, "parameters") ??
118
+ syntaxField(facts.syntax, id, "parameter"),
119
+ ),
120
+ id,
121
+ );
122
+ const name = syntaxField(facts.syntax, id, "name");
123
+ if (name !== undefined && node.kind !== "method_definition")
124
+ add([name], node.kind.endsWith("declaration") ? nearestScope(facts, node.parent) : id);
125
+ }
126
+ if (node.kind === "class_declaration" || node.kind === "class") {
127
+ const name = syntaxField(facts.syntax, id, "name");
128
+ if (name !== undefined)
129
+ add([name], node.kind === "class_declaration" ? nearestScope(facts, node.parent) : id);
130
+ }
131
+ if (node.kind === "catch_clause")
132
+ add(patternIdentifiers(facts, syntaxField(facts.syntax, id, "parameter")), id);
133
+ }
134
+ }
135
+ shadowed(name: string, occurrence: number): boolean {
136
+ const local = this.#bindings.get(name);
137
+ if (!local?.length) return false;
138
+ const ancestors = new Set<number>();
139
+ let current: number | null = occurrence;
140
+ while (current !== null) {
141
+ ancestors.add(current);
142
+ current = this.facts.syntax.nodes[current]?.parent ?? null;
143
+ }
144
+ return local.some((binding) => ancestors.has(binding.scope));
145
+ }
146
+ isReference(node: number): boolean {
147
+ const value = this.facts.syntax.nodes[node];
148
+ if (
149
+ !value ||
150
+ this.#declarations.has(node) ||
151
+ !["identifier", "shorthand_property_identifier"].includes(value.kind)
152
+ )
153
+ return false;
154
+ let current: number | null = value.parent;
155
+ while (current !== null) {
156
+ const ancestor = this.facts.syntax.nodes[current];
157
+ if (!ancestor) break;
158
+ if (
159
+ [
160
+ "import_statement",
161
+ "export_statement",
162
+ "type_annotation",
163
+ "type_arguments",
164
+ "type_parameters",
165
+ "type_alias_declaration",
166
+ "interface_declaration",
167
+ ].includes(ancestor.kind)
168
+ )
169
+ return false;
170
+ current = ancestor.parent;
171
+ }
172
+ return true;
173
+ }
174
+ }
175
+
176
+ interface Callee {
177
+ root: string;
178
+ rootNode: number;
179
+ properties: string[];
180
+ }
181
+ function callee(facts: ModuleFacts, node: number | undefined): Callee | undefined {
182
+ if (node === undefined) return undefined;
183
+ const value = facts.syntax.nodes[node];
184
+ if (!value) return undefined;
185
+ if (value.kind === "identifier")
186
+ return { root: nodeText(facts, node) ?? "", rootNode: node, properties: [] };
187
+ if (value.kind !== "member_expression") return undefined;
188
+ const object = callee(facts, syntaxField(facts.syntax, node, "object"));
189
+ const property = syntaxField(facts.syntax, node, "property");
190
+ if (
191
+ !object ||
192
+ property === undefined ||
193
+ facts.syntax.nodes[property]?.kind !== "property_identifier"
194
+ )
195
+ return undefined;
196
+ return { ...object, properties: [...object.properties, nodeText(facts, property) ?? ""] };
197
+ }
198
+
199
+ export function collectTestCases(facts: ModuleFacts, bindings: TestBindings): TestCaseFact[] {
200
+ const cases: TestCaseFact[] = [];
201
+ for (let id = 0; id < facts.syntax.nodes.length; id++) {
202
+ if (facts.syntax.nodes[id]?.kind !== "call_expression") continue;
203
+ const call = callee(facts, syntaxField(facts.syntax, id, "function"));
204
+ if (!call) continue;
205
+ const imported = facts.imports.find((binding) => binding.local === call.root);
206
+ const properties = [...call.properties];
207
+ let kind = call.root;
208
+ let framework: string | undefined;
209
+ const notes: string[] = [];
210
+ if (imported && !imported.typeOnly && !bindings.shadowed(call.root, call.rootNode)) {
211
+ framework = FRAMEWORKS.get(imported.source ?? "");
212
+ if (imported.kind === "namespace") kind = properties.shift() ?? "";
213
+ else if (imported.kind === "default" && imported.source === "node:test") kind = "test";
214
+ else kind = imported.imported;
215
+ } else if (imported) notes.push("test-binding-shadowed-or-type-only");
216
+ if (!TEST_NAMES.has(kind)) continue;
217
+ if (!framework) notes.push("framework-binding-unresolved");
218
+ const modifiers = properties.filter((property) => property === "skip" || property === "only");
219
+ if (modifiers.length !== properties.length || modifiers.length > 1)
220
+ notes.push("parameterized-or-custom-test-wrapper-unsupported");
221
+ const argumentsNode = syntaxField(facts.syntax, id, "arguments");
222
+ const argumentsList =
223
+ argumentsNode === undefined
224
+ ? []
225
+ : (facts.syntax.children[argumentsNode] ?? []).filter(
226
+ (child) =>
227
+ facts.syntax.nodes[child]?.named && facts.syntax.nodes[child]?.kind !== "comment",
228
+ );
229
+ const nameNode = argumentsList[0];
230
+ const nameKind = nameNode === undefined ? undefined : facts.syntax.nodes[nameNode]?.kind;
231
+ const name =
232
+ nameKind === "string" || nameKind === "template_string"
233
+ ? literalText(nodeText(facts, nameNode))
234
+ : undefined;
235
+ if (name === undefined) notes.push("dynamic-or-missing-test-name");
236
+ const last = argumentsList.at(-1);
237
+ const callback =
238
+ last !== undefined &&
239
+ ["arrow_function", "function_expression", "generator_function"].includes(
240
+ facts.syntax.nodes[last]?.kind ?? "",
241
+ )
242
+ ? last
243
+ : undefined;
244
+ if (callback === undefined) notes.push("explicit-test-callback-unavailable");
245
+ const supportedArguments =
246
+ argumentsList.length === 2 ||
247
+ (argumentsList.length === 3 && facts.syntax.nodes[argumentsList[1] ?? -1]?.kind === "object");
248
+ if (!supportedArguments) notes.push("test-arguments-unsupported");
249
+ cases.push({
250
+ node: id,
251
+ ...(name !== undefined ? { name } : {}),
252
+ ...(callback !== undefined ? { callback } : {}),
253
+ ...(framework !== undefined ? { framework } : {}),
254
+ testKind: kind,
255
+ modifiers,
256
+ status: notes.length === 0 ? "recognized" : "syntax-candidate",
257
+ notes,
258
+ });
259
+ }
260
+ return cases;
261
+ }