@blxzer/cursor-trellis 0.1.2 → 0.2.1

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 (105) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +45 -21
  3. package/dist/configurators/workflow.d.ts +1 -1
  4. package/dist/configurators/workflow.d.ts.map +1 -1
  5. package/dist/configurators/workflow.js +20 -9
  6. package/dist/configurators/workflow.js.map +1 -1
  7. package/dist/migrations/manifests/0.1.3.json +9 -0
  8. package/dist/migrations/manifests/0.1.4.json +9 -0
  9. package/dist/templates/cursor/rules/retrieval-routing.mdc +9 -7
  10. package/dist/templates/markdown/agents.md +1 -1
  11. package/dist/templates/markdown/index.d.ts +1 -0
  12. package/dist/templates/markdown/index.d.ts.map +1 -1
  13. package/dist/templates/markdown/index.js +1 -0
  14. package/dist/templates/markdown/index.js.map +1 -1
  15. package/dist/templates/markdown/prompts/run-semantic-slice-12.md.txt +13 -29
  16. package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +0 -49
  17. package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +0 -85
  18. package/dist/templates/markdown/spec/guides/cursor-semantic-compliance.md.txt +7 -21
  19. package/dist/templates/markdown/spec/guides/cursor-subagent-policy.md.txt +6 -10
  20. package/dist/templates/markdown/spec/guides/retrieval-daily-guide.md.txt +17 -18
  21. package/dist/templates/shared-hooks/inject-retrieval-plan.py +42 -23
  22. package/dist/templates/shared-hooks/inject-subagent-context.py +6 -2
  23. package/dist/templates/shared-hooks/session-start.py +17 -9
  24. package/dist/templates/trellis/index.d.ts +8 -4
  25. package/dist/templates/trellis/index.d.ts.map +1 -1
  26. package/dist/templates/trellis/index.js +13 -7
  27. package/dist/templates/trellis/index.js.map +1 -1
  28. package/dist/templates/trellis/scripts/common/codebase_retrieval_router.py +80 -31
  29. package/dist/templates/trellis/scripts/common/config.py +1 -1
  30. package/dist/templates/trellis/scripts/common/cursor_retrieval_env.py +92 -0
  31. package/dist/templates/trellis/scripts/common/parent_orchestration.py +27 -15
  32. package/dist/templates/trellis/scripts/common/retrieval_adapter_metadata.py +100 -9
  33. package/dist/templates/trellis/scripts/common/retrieval_agent_instructions.py +76 -31
  34. package/dist/templates/trellis/scripts/common/retrieval_tool_classification.py +18 -3
  35. package/dist/templates/trellis/scripts/common/semantic_plan_gate.py +19 -0
  36. package/dist/templates/trellis/scripts/common/smart_search_evidence.py +5 -2
  37. package/dist/templates/trellis/scripts/common/smart_search_resolve.py +28 -3
  38. package/dist/templates/trellis/scripts/common/task_gates.py +372 -73
  39. package/dist/templates/trellis/scripts/common/task_map.py +29 -1
  40. package/dist/templates/trellis/scripts/cursor_retrieval_probe.py +396 -0
  41. package/dist/templates/trellis/scripts/cursor_retrieval_probe_prompt.md +300 -0
  42. package/dist/templates/trellis/scripts/retrieval_probe_matrix_template.json +126 -0
  43. package/dist/templates/trellis/workflow.md +9 -53
  44. package/dist/utils/codebase-retrieval-router.d.ts +5 -0
  45. package/dist/utils/codebase-retrieval-router.d.ts.map +1 -1
  46. package/dist/utils/codebase-retrieval-router.js +48 -28
  47. package/dist/utils/codebase-retrieval-router.js.map +1 -1
  48. package/dist/utils/cursor-retrieval-env.d.ts +28 -0
  49. package/dist/utils/cursor-retrieval-env.d.ts.map +1 -0
  50. package/dist/utils/cursor-retrieval-env.js +89 -0
  51. package/dist/utils/cursor-retrieval-env.js.map +1 -0
  52. package/dist/utils/project-capabilities.d.ts.map +1 -1
  53. package/dist/utils/project-capabilities.js +22 -15
  54. package/dist/utils/project-capabilities.js.map +1 -1
  55. package/dist/utils/retrieval-agent-instructions.d.ts.map +1 -1
  56. package/dist/utils/retrieval-agent-instructions.js +37 -21
  57. package/dist/utils/retrieval-agent-instructions.js.map +1 -1
  58. package/dist/utils/retrieval-tool-classification.d.ts +2 -0
  59. package/dist/utils/retrieval-tool-classification.d.ts.map +1 -1
  60. package/dist/utils/retrieval-tool-classification.js +10 -2
  61. package/dist/utils/retrieval-tool-classification.js.map +1 -1
  62. package/dist/utils/semantic-plan-gate.d.ts +8 -0
  63. package/dist/utils/semantic-plan-gate.d.ts.map +1 -0
  64. package/dist/utils/semantic-plan-gate.js +42 -0
  65. package/dist/utils/semantic-plan-gate.js.map +1 -0
  66. package/package.json +5 -43
  67. package/bin/smart-search.js +0 -79
  68. package/dist/templates/trellis/scripts/aggregate_retrieval_telemetry.py +0 -342
  69. package/dist/templates/trellis/scripts/batch_plan_envelope.py +0 -105
  70. package/vendor/smart-search/LICENSE +0 -21
  71. package/vendor/smart-search/README.md +0 -412
  72. package/vendor/smart-search/README.zh-CN.md +0 -430
  73. package/vendor/smart-search/npm/bin/smart-search.js +0 -63
  74. package/vendor/smart-search/npm/scripts/postinstall.js +0 -87
  75. package/vendor/smart-search/npm/scripts/resolve-prerelease-version.js +0 -108
  76. package/vendor/smart-search/npm/scripts/set-package-version.js +0 -35
  77. package/vendor/smart-search/npm/scripts/sync-python-version.js +0 -22
  78. package/vendor/smart-search/npm/scripts/test-wrapper-repair.js +0 -99
  79. package/vendor/smart-search/npm/scripts/test.js +0 -85
  80. package/vendor/smart-search/package.json +0 -42
  81. package/vendor/smart-search/pyproject.toml +0 -37
  82. package/vendor/smart-search/skills/smart-search-cli/SKILL.md +0 -387
  83. package/vendor/smart-search/skills/smart-search-cli/agents/openai.yaml +0 -3
  84. package/vendor/smart-search/skills/smart-search-cli/examples/batch-search.md +0 -98
  85. package/vendor/smart-search/skills/smart-search-cli/examples/evidence-gathering.md +0 -89
  86. package/vendor/smart-search/skills/smart-search-cli/references/cli-contract.md +0 -337
  87. package/vendor/smart-search/src/smart_search/__init__.py +0 -1
  88. package/vendor/smart-search/src/smart_search/assets/skills/smart-search-cli/SKILL.md +0 -387
  89. package/vendor/smart-search/src/smart_search/assets/skills/smart-search-cli/agents/openai.yaml +0 -3
  90. package/vendor/smart-search/src/smart_search/assets/skills/smart-search-cli/examples/batch-search.md +0 -98
  91. package/vendor/smart-search/src/smart_search/assets/skills/smart-search-cli/examples/evidence-gathering.md +0 -89
  92. package/vendor/smart-search/src/smart_search/assets/skills/smart-search-cli/references/cli-contract.md +0 -337
  93. package/vendor/smart-search/src/smart_search/cli.py +0 -2003
  94. package/vendor/smart-search/src/smart_search/config.py +0 -580
  95. package/vendor/smart-search/src/smart_search/logger.py +0 -43
  96. package/vendor/smart-search/src/smart_search/providers/__init__.py +0 -16
  97. package/vendor/smart-search/src/smart_search/providers/base.py +0 -41
  98. package/vendor/smart-search/src/smart_search/providers/context7.py +0 -141
  99. package/vendor/smart-search/src/smart_search/providers/exa.py +0 -206
  100. package/vendor/smart-search/src/smart_search/providers/jina.py +0 -136
  101. package/vendor/smart-search/src/smart_search/providers/openai_compatible.py +0 -370
  102. package/vendor/smart-search/src/smart_search/providers/zhipu.py +0 -143
  103. package/vendor/smart-search/src/smart_search/service.py +0 -2865
  104. package/vendor/smart-search/src/smart_search/sources.py +0 -429
  105. package/vendor/smart-search/src/smart_search/utils.py +0 -220
@@ -12,6 +12,8 @@ from __future__ import annotations
12
12
  import re
13
13
  from typing import Any
14
14
 
15
+ from .cursor_retrieval_env import ENV_BYOK, detect_cursor_retrieval_env
16
+
15
17
  _SYMBOL_CANDIDATE = re.compile(
16
18
  r"\b([A-Za-z_][\w$]{2,})\b|"
17
19
  r"`([^`]+)`|"
@@ -104,7 +106,13 @@ def _intent_summary(intents: list[dict[str, object]]) -> str:
104
106
  return "、".join(parts)
105
107
 
106
108
 
107
- def _cursor_step_for_route(route: dict[str, object], *, symbol: str, query: str) -> str | None:
109
+ def _cursor_step_for_route(
110
+ route: dict[str, object],
111
+ *,
112
+ symbol: str,
113
+ query: str,
114
+ cursor_env: str,
115
+ ) -> str | None:
108
116
  role = str(route.get("role", ""))
109
117
  route_id = str(route.get("id", ""))
110
118
 
@@ -126,6 +134,11 @@ def _cursor_step_for_route(route: dict[str, object], *, symbol: str, query: str)
126
134
  return (
127
135
  f"使用 **codegraph_search**,路径侧重 `extensions/`,符号 `{symbol}`。"
128
136
  )
137
+ if route_id == "lsp-navigation":
138
+ return (
139
+ f"使用 **codegraph_node**(`includeCode=true`)或 **codegraph_search** 定位 `{symbol}` "
140
+ "的定义/引用(Agent 无 GO_TO_DEFINITION);再用 **Read** 验证行号与正文。"
141
+ )
129
142
  if role == "ast" or route_id in ("ast-codegraph",):
130
143
  return (
131
144
  f"使用 **codegraph_explore** 或 **codegraph_node**(`includeCode=true`),"
@@ -135,21 +148,27 @@ def _cursor_step_for_route(route: dict[str, object], *, symbol: str, query: str)
135
148
  if route_id == "platform-semantic" or (
136
149
  role == "semantic" and str(route.get("sourceFamily")) == "platform-semantic"
137
150
  ):
151
+ backend = str(route.get("semanticBackend", ""))
152
+ if cursor_env == ENV_BYOK or backend == "fast-context-mcp":
153
+ return (
154
+ "使用 **fast_context_search**(fast-context MCP)做概念/代码库语义检索;"
155
+ "**不要**假设 @codebase 或内置 SemanticSearch 可用;**不要**用 WebSearch 答代码库问题。"
156
+ )
138
157
  return (
139
- "使用 Cursor **内置代码库语义搜索**(Agent 语义搜索能力,等同 @codebase 语义索引;"
140
- "**不要**使用 fast-context MCP)。"
158
+ "使用 Cursor **内置代码库语义搜索**(宿主工具常为 **SemanticSearch**;"
159
+ "**`target_directories`** 为目录 glob 数组,省略会报错;**`[]`** = 不缩范围、搜全工作区索引;"
160
+ "若计划或 Grep/codegraph 已指向子树可传如 `['src/components']`;"
161
+ "无路径线索的概念题优先 **`[]`**;Native 下 **不要**用 fast-context MCP 顶替)。"
141
162
  )
142
163
  if role == "semantic":
164
+ if cursor_env == ENV_BYOK:
165
+ return (
166
+ "使用 **fast_context_search**(fast-context MCP);勿用 WebSearch 答代码库问题。"
167
+ )
143
168
  return (
144
169
  "使用 Cursor **内置代码库语义搜索**(不要用 fast-context MCP)。"
145
170
  )
146
171
 
147
- if route_id == "lsp-navigation" or role == "lsp":
148
- return (
149
- f"可选:若宿主暴露 **GO_TO_DEFINITION** / 查找引用,在已有候选上核对 `{symbol}`;"
150
- "非 Agent 默认保证,未调用时用 **Read** + **Grep** 验证。"
151
- )
152
-
153
172
  if route_id == "policy-docs-rg" or str(route.get("sourceFamily")) == "policy-docs":
154
173
  return (
155
174
  "使用 **Grep** 在 `AGENTS.md`、`**/AGENTS.md`、`.trellis/spec`、`README.md` "
@@ -162,6 +181,10 @@ def _cursor_step_for_route(route: dict[str, object], *, symbol: str, query: str)
162
181
  )
163
182
 
164
183
  if route_id == "cross-cutting-discovery" or "deep" in route_id.lower():
184
+ if cursor_env == ENV_BYOK:
185
+ return (
186
+ "复杂跨模块探索:使用 **Task** 子代理(explore),再用 Grep/codegraph/Read 验证。"
187
+ )
165
188
  return (
166
189
  "复杂跨模块探索:可选用 **DEEP_SEARCH** 或 Explore 子任务,再用 Grep/codegraph 验证。"
167
190
  )
@@ -201,6 +224,7 @@ def render_agent_instructions(
201
224
  verification_list = verification if isinstance(verification, list) else []
202
225
 
203
226
  symbol = guess_symbol_from_query(query) or "<symbol>"
227
+ cursor_env = str(envelope.get("cursorEnv") or detect_cursor_retrieval_env())
204
228
 
205
229
  if locale != "zh":
206
230
  header = "## Codebase retrieval plan\n"
@@ -211,6 +235,7 @@ def render_agent_instructions(
211
235
  header.rstrip(),
212
236
  f"问题:{query or '(空)'}",
213
237
  f"意图:{_intent_summary(intent_list)}",
238
+ f"检索环境(cursorEnv):{cursor_env}",
214
239
  "",
215
240
  ]
216
241
 
@@ -222,7 +247,9 @@ def render_agent_instructions(
222
247
  for route in sorted_routes:
223
248
  if not isinstance(route, dict):
224
249
  continue
225
- text = _cursor_step_for_route(route, symbol=symbol, query=query)
250
+ text = _cursor_step_for_route(
251
+ route, symbol=symbol, query=query, cursor_env=cursor_env
252
+ )
226
253
  if not text:
227
254
  continue
228
255
  step += 1
@@ -257,34 +284,52 @@ def render_agent_instructions(
257
284
 
258
285
  lines.append("")
259
286
  lines.append(
260
- "**codegraph 独用场景**:调用链、跨包 trap、extension 符号、影响面;"
261
- "纯字面搜索用 Grep,单点定义用 GO_TO_DEFINITION"
287
+ "**codegraph 独用场景**:调用链、跨包 trap、extension 符号、影响面、定义/引用定位;"
288
+ "纯字面搜索用 Grep(勿用 GO_TO_DEFINITION,Agent 未暴露)。"
262
289
  )
263
290
 
264
291
  if any(
265
292
  isinstance(r, dict) and r.get("id") == "platform-semantic" for r in route_list
266
293
  ):
267
294
  lines.append("")
268
- if locale != "zh":
269
- lines.append("**Semantic compliance (Cursor):**")
270
- lines.append(
271
- "- When this plan lists **platform-semantic**, run **one** Cursor built-in "
272
- "codebase / semantic search before final Top-1 (not fast-context MCP)."
273
- )
274
- lines.append(
275
- "- Log the **exact tool name** from the host (e.g. codebase_search, @codebase) "
276
- "in your run notes for semantic_exec_rate."
277
- )
295
+ if cursor_env == ENV_BYOK:
296
+ if locale != "zh":
297
+ lines.append("**Semantic compliance (Cursor++ BYOK):**")
298
+ lines.append(
299
+ "- Run **one** `fast_context_search` before final Top-1 when "
300
+ "**platform-semantic** is listed; log the MCP tool name."
301
+ )
302
+ else:
303
+ lines.append("**语义合规(Cursor++ BYOK):**")
304
+ lines.append(
305
+ "- 本计划含 **platform-semantic** 时:定 Top-1 前至少 **1 次** "
306
+ "**fast_context_search**(fast-context MCP),并记录工具名。"
307
+ )
278
308
  else:
279
- lines.append("**语义合规(Cursor):**")
280
- lines.append(
281
- "- 本计划含 **platform-semantic** 时:定 Top-1 前至少执行 **1 次** "
282
- "Cursor **内置代码库语义搜索**(不要用 fast-context MCP)。"
283
- )
284
- lines.append(
285
- "- 在 run 记录中写下宿主返回的**真实工具名**(如 codebase_search、@codebase),"
286
- " semantic_exec 统计。"
287
- )
309
+ if locale != "zh":
310
+ lines.append("**Semantic compliance (Cursor Native):**")
311
+ lines.append(
312
+ "- When this plan lists **platform-semantic**, run **one** Cursor built-in "
313
+ "codebase / semantic search before final Top-1 (not fast-context MCP)."
314
+ )
315
+ lines.append(
316
+ "- Log the **exact tool name** from the host (e.g. codebase_search, @codebase) "
317
+ "in your run notes for semantic_exec_rate."
318
+ )
319
+ else:
320
+ lines.append("**语义合规(Cursor Native):**")
321
+ lines.append(
322
+ "- 本计划含 **platform-semantic** 时:定 Top-1 前至少执行 **1 次** "
323
+ "Cursor **内置代码库语义搜索**(不要用 fast-context MCP)。"
324
+ )
325
+ lines.append(
326
+ "- 在 run 记录中写下宿主返回的**真实工具名**(如 SemanticSearch、codebase_search、@codebase),"
327
+ "供 semantic_exec 统计。"
328
+ )
329
+ lines.append(
330
+ "- 若工具为 **SemanticSearch**:**必须提供** **`target_directories`**;"
331
+ "**`[]`** = 全库;已知子目录时用 glob 收窄(勿省略该字段)。"
332
+ )
288
333
 
289
334
  try:
290
335
  from .semantic_plan_gate import semantic_compliance_gate_hint # noqa: PLC0415
@@ -88,7 +88,13 @@ class ClassifiedToolCalls:
88
88
  cursor_fast_context_misuse: bool = False
89
89
 
90
90
 
91
- def classify_tool_calls(raw: list[str], *, platform: str = "cursor") -> ClassifiedToolCalls:
91
+ def classify_tool_calls(
92
+ raw: list[str],
93
+ *,
94
+ platform: str = "cursor",
95
+ cursor_env: str | None = None,
96
+ route_ids: list[str] | None = None,
97
+ ) -> ClassifiedToolCalls:
92
98
  tools_called = list(raw)
93
99
  grep_count = 0
94
100
  read_count = 0
@@ -115,13 +121,22 @@ def classify_tool_calls(raw: list[str], *, platform: str = "cursor") -> Classifi
115
121
  if is_platform_semantic_tool_name(trimmed):
116
122
  platform_semantic_executed = True
117
123
 
124
+ env = (cursor_env or "").strip().lower()
118
125
  if plat == "cursor":
119
- semantic_executed = platform_semantic_executed
126
+ if env == "byok":
127
+ semantic_executed = platform_semantic_executed or fast_context_count > 0
128
+ else:
129
+ semantic_executed = platform_semantic_executed
120
130
  else:
121
131
  semantic_executed = platform_semantic_executed or fast_context_count > 0
122
132
 
123
133
  semantic_attempted = semantic_executed or fast_context_count > 0
124
- misuse = plat == "cursor" and fast_context_count > 0
134
+
135
+ misuse = (
136
+ plat == "cursor"
137
+ and fast_context_count > 0
138
+ and env != "byok"
139
+ )
125
140
 
126
141
  return ClassifiedToolCalls(
127
142
  tools_called=tools_called,
@@ -4,6 +4,8 @@ from __future__ import annotations
4
4
 
5
5
  from typing import Any
6
6
 
7
+ from .cursor_retrieval_env import ENV_BYOK, detect_cursor_retrieval_env
8
+
7
9
 
8
10
  def platform_semantic_order_from_envelope(envelope: dict[str, Any]) -> int | None:
9
11
  routes = envelope.get("routes")
@@ -37,6 +39,22 @@ def semantic_compliance_gate_hint(
37
39
  if not any(isinstance(r, dict) and r.get("id") == "platform-semantic" for r in routes):
38
40
  return ""
39
41
 
42
+ cursor_env = str(envelope.get("cursorEnv") or detect_cursor_retrieval_env())
43
+
44
+ if cursor_env == ENV_BYOK:
45
+ if locale != "zh":
46
+ return (
47
+ "**Plan gate (REC-11, BYOK):** `platform-semantic` is step "
48
+ f"#{order}. Before Top-1 you MUST run one **fast_context_search** "
49
+ "(fast-context MCP). Do not use WebSearch for codebase questions. "
50
+ "Corroborate hits with Read."
51
+ )
52
+ return (
53
+ "**计划门控(REC-11,BYOK):** 本问 `platform-semantic` 为第 "
54
+ f"{order} 步。定 Top-1 前 **必须** 执行 1 次 **fast_context_search**(fast-context MCP);"
55
+ "**禁止** 用 WebSearch 答代码库问题。命中路径后须 **Read** 验证。"
56
+ )
57
+
40
58
  if locale != "zh":
41
59
  return (
42
60
  "**Plan gate (REC-11):** `platform-semantic` is step "
@@ -48,5 +66,6 @@ def semantic_compliance_gate_hint(
48
66
  "**计划门控(REC-11):** 本问 `platform-semantic` 为第 "
49
67
  f"{order} 步。定 Top-1 前 **必须** 执行 1 次 Cursor **内置代码库语义搜索**,"
50
68
  "并在记录中写下宿主工具名;**禁止** fast-context MCP。"
69
+ "若工具为 **SemanticSearch**,须传 **`target_directories`**(`[]` 全库,或已知子目录 glob 收窄)。"
51
70
  "语义命中路径后须 **Read** 验证候选片段(verified 层)。"
52
71
  )
@@ -125,7 +125,7 @@ def main(argv: list[str] | None = None) -> int:
125
125
  print_manifest(manifest, args.json)
126
126
  return 4
127
127
  doctor_data = parse_json_output(doctor_result.stdout)
128
- if doctor_result.returncode != 0 or doctor_data.get("ok") is False:
128
+ if doctor_result.returncode != 0 or not doctor_data.get("ok"):
129
129
  manifest = build_manifest(
130
130
  repo_root=repo_root,
131
131
  query=args.query,
@@ -188,7 +188,7 @@ class CommandResult:
188
188
  self.not_found = not_found
189
189
 
190
190
 
191
- def run_command(command: list[str], cwd: Path) -> CommandResult:
191
+ def run_command(command: list[str], cwd: Path, timeout: int = 120) -> CommandResult:
192
192
  try:
193
193
  completed = subprocess.run(
194
194
  command,
@@ -198,8 +198,11 @@ def run_command(command: list[str], cwd: Path) -> CommandResult:
198
198
  errors="replace",
199
199
  capture_output=True,
200
200
  check=False,
201
+ timeout=timeout,
201
202
  )
202
203
  return CommandResult(completed.returncode, completed.stdout or "", completed.stderr or "")
204
+ except subprocess.TimeoutExpired:
205
+ return CommandResult(124, "", f"Command timed out after {timeout}s")
203
206
  except FileNotFoundError as error:
204
207
  return CommandResult(127, "", str(error), not_found=True)
205
208
 
@@ -65,6 +65,12 @@ def _npm_local_wrappers(repo_root: Path) -> list[list[str]]:
65
65
  repo_root / "node_modules" / ".bin" / "smart-search.js",
66
66
  repo_root
67
67
  / "node_modules"
68
+ / "@blxzer"
69
+ / "cursor-trellis"
70
+ / "bin"
71
+ / "smart-search.js",
72
+ repo_root
73
+ / "node_modules"
68
74
  / "@konbakuyomu"
69
75
  / "smart-search"
70
76
  / "npm"
@@ -83,9 +89,28 @@ def _npm_local_wrappers(repo_root: Path) -> list[list[str]]:
83
89
  return out
84
90
 
85
91
 
86
- def _harness_wrappers(repo_root: Path) -> list[list[str]]:
87
- """Optional polyrepo harness layouts (e.g. MyHarness)."""
92
+ def _optional_repo_wrappers(repo_root: Path) -> list[list[str]]:
93
+ """
94
+ Optional repo-local layouts when PATH and node_modules resolution fail.
95
+
96
+ Order is intentional: published npm co-install, standalone smart-search package,
97
+ then maintainer polyrepo sibling checkouts (names vary by fork/upstream).
98
+ """
88
99
  candidates: list[Path] = [
100
+ repo_root
101
+ / "node_modules"
102
+ / "@blxzer"
103
+ / "cursor-trellis"
104
+ / "bin"
105
+ / "smart-search.js",
106
+ repo_root
107
+ / "node_modules"
108
+ / "@konbakuyomu"
109
+ / "smart-search"
110
+ / "npm"
111
+ / "bin"
112
+ / "smart-search.js",
113
+ repo_root / "cursor-trellis" / "packages" / "cli" / "bin" / "smart-search.js",
89
114
  repo_root / "Trellis" / "packages" / "cli" / "bin" / "smart-search.js",
90
115
  repo_root / "smartsearch-private" / "npm" / "bin" / "smart-search.js",
91
116
  ]
@@ -115,7 +140,7 @@ def resolve_smart_search_argv(repo_root: Path | None = None) -> list[str] | None
115
140
  for argv in _npm_local_wrappers(root):
116
141
  return argv
117
142
 
118
- for argv in _harness_wrappers(root):
143
+ for argv in _optional_repo_wrappers(root):
119
144
  return argv
120
145
 
121
146
  return None