@crownpeak/dqm-react-component-dev-mcp 1.2.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 (444) hide show
  1. package/README.md +138 -0
  2. package/data/.env.example +22 -0
  3. package/data/.gitattributes +47 -0
  4. package/data/.glfrc.json +7 -0
  5. package/data/.husky/pre-commit +5 -0
  6. package/data/.nvmrc +1 -0
  7. package/data/CHANGELOG.md +75 -0
  8. package/data/CODE_OF_CONDUCT.md +129 -0
  9. package/data/CONTRIBUTING.md +203 -0
  10. package/data/DOCS-STRUCTURE.md +307 -0
  11. package/data/I18N.md +292 -0
  12. package/data/LICENSE +22 -0
  13. package/data/README.md +315 -0
  14. package/data/SECURITY.md +125 -0
  15. package/data/WIKI-DEPLOYMENT.md +348 -0
  16. package/data/docs/AI-FEATURES.md +610 -0
  17. package/data/docs/API-REFERENCE.md +1022 -0
  18. package/data/docs/AUTHENTICATION.md +301 -0
  19. package/data/docs/BACKEND-API.md +468 -0
  20. package/data/docs/DEVELOPMENT.md +375 -0
  21. package/data/docs/EXAMPLES.md +622 -0
  22. package/data/docs/MCP-SERVER.md +307 -0
  23. package/data/docs/MIGRATION-GUIDE.md +367 -0
  24. package/data/docs/NPM-PUBLISH.md +193 -0
  25. package/data/docs/QUICKSTART.md +206 -0
  26. package/data/docs/REDIS-SETUP.md +162 -0
  27. package/data/docs/SERVER.md +228 -0
  28. package/data/docs/TROUBLESHOOTING.md +657 -0
  29. package/data/docs/WIDGET-GUIDE.md +638 -0
  30. package/data/docs/WIKI-HOME.md +58 -0
  31. package/data/docs/WIKI-SIDEBAR.md +39 -0
  32. package/data/package.json +171 -0
  33. package/data/playwright.config.ts +64 -0
  34. package/data/probe/.cargo/config.toml +10 -0
  35. package/data/probe/.claude/commands/performance-review.md +15 -0
  36. package/data/probe/.clinerules +288 -0
  37. package/data/probe/.dockerignore +57 -0
  38. package/data/probe/.githooks/post-commit +11 -0
  39. package/data/probe/.githooks/pre-commit +99 -0
  40. package/data/probe/.githooks/pre-commit-vow +9 -0
  41. package/data/probe/.prompts/engineer.md +41 -0
  42. package/data/probe/.roomodes +28 -0
  43. package/data/probe/.windsurfrules +0 -0
  44. package/data/probe/BASH_TOOL_SUMMARY.md +148 -0
  45. package/data/probe/BENCHMARKING.md +256 -0
  46. package/data/probe/CLAUDE.md +226 -0
  47. package/data/probe/CODE_OF_CONDUCT.md +128 -0
  48. package/data/probe/CONTRIBUTING.md +193 -0
  49. package/data/probe/Cargo.toml +120 -0
  50. package/data/probe/Cross.toml +10 -0
  51. package/data/probe/DOCKER-README.md +224 -0
  52. package/data/probe/Dockerfile +32 -0
  53. package/data/probe/ENHANCED_DEBUG_TELEMETRY.md +188 -0
  54. package/data/probe/LICENSE +201 -0
  55. package/data/probe/Makefile +210 -0
  56. package/data/probe/README.md +824 -0
  57. package/data/probe/SECURITY.md +67 -0
  58. package/data/probe/WINDOWS-GUIDE.md +294 -0
  59. package/data/probe/benches/parsing_benchmarks.rs +370 -0
  60. package/data/probe/benches/search_benchmarks.rs +599 -0
  61. package/data/probe/benches/simd_benchmarks.rs +372 -0
  62. package/data/probe/benches/timing_benchmarks.rs +287 -0
  63. package/data/probe/build-windows.bat +229 -0
  64. package/data/probe/codex-config/config.toml +6 -0
  65. package/data/probe/docs/PERFORMANCE_OPTIMIZATION.md +161 -0
  66. package/data/probe/examples/cache_demo.rs +46 -0
  67. package/data/probe/examples/chat/.dockerignore +37 -0
  68. package/data/probe/examples/chat/ChatSessionManager.js +295 -0
  69. package/data/probe/examples/chat/Dockerfile +98 -0
  70. package/data/probe/examples/chat/LICENSE +201 -0
  71. package/data/probe/examples/chat/LOCAL_IMAGE_SUPPORT.md +195 -0
  72. package/data/probe/examples/chat/MCP_INTEGRATION.md +400 -0
  73. package/data/probe/examples/chat/README.md +338 -0
  74. package/data/probe/examples/chat/TRACING.md +226 -0
  75. package/data/probe/examples/chat/appTracer.js +968 -0
  76. package/data/probe/examples/chat/auth.js +76 -0
  77. package/data/probe/examples/chat/bin/probe-chat.js +13 -0
  78. package/data/probe/examples/chat/build.js +104 -0
  79. package/data/probe/examples/chat/cancelRequest.js +84 -0
  80. package/data/probe/examples/chat/demo-agentic-image-flow.js +88 -0
  81. package/data/probe/examples/chat/demo-local-images.js +128 -0
  82. package/data/probe/examples/chat/fileSpanExporter.js +181 -0
  83. package/data/probe/examples/chat/implement/README.md +228 -0
  84. package/data/probe/examples/chat/implement/backends/AiderBackend.js +750 -0
  85. package/data/probe/examples/chat/implement/backends/BaseBackend.js +276 -0
  86. package/data/probe/examples/chat/implement/backends/ClaudeCodeBackend.js +767 -0
  87. package/data/probe/examples/chat/implement/backends/MockBackend.js +237 -0
  88. package/data/probe/examples/chat/implement/backends/registry.js +85 -0
  89. package/data/probe/examples/chat/implement/core/BackendManager.js +567 -0
  90. package/data/probe/examples/chat/implement/core/ImplementTool.js +354 -0
  91. package/data/probe/examples/chat/implement/core/config.js +428 -0
  92. package/data/probe/examples/chat/implement/core/timeouts.js +58 -0
  93. package/data/probe/examples/chat/implement/core/utils.js +496 -0
  94. package/data/probe/examples/chat/implement/types/BackendTypes.js +126 -0
  95. package/data/probe/examples/chat/index.js +669 -0
  96. package/data/probe/examples/chat/mcpServer.js +341 -0
  97. package/data/probe/examples/chat/npm/LICENSE +15 -0
  98. package/data/probe/examples/chat/npm/README.md +168 -0
  99. package/data/probe/examples/chat/npm/bin/probe-chat.js +156 -0
  100. package/data/probe/examples/chat/npm/index.js +259 -0
  101. package/data/probe/examples/chat/npm/package.json +54 -0
  102. package/data/probe/examples/chat/package.json +102 -0
  103. package/data/probe/examples/chat/probeChat.js +456 -0
  104. package/data/probe/examples/chat/probeTool.js +491 -0
  105. package/data/probe/examples/chat/storage/JsonChatStorage.js +476 -0
  106. package/data/probe/examples/chat/telemetry.js +281 -0
  107. package/data/probe/examples/chat/test/integration/chatFlows.test.js +320 -0
  108. package/data/probe/examples/chat/test/integration/toolCalling.test.js +471 -0
  109. package/data/probe/examples/chat/test/mocks/mockLLMProvider.js +269 -0
  110. package/data/probe/examples/chat/test/test-backends.js +90 -0
  111. package/data/probe/examples/chat/test/testUtils.js +530 -0
  112. package/data/probe/examples/chat/test/unit/backendTimeout.test.js +161 -0
  113. package/data/probe/examples/chat/test/unit/packageFiles.test.js +120 -0
  114. package/data/probe/examples/chat/test/verify-tests.js +118 -0
  115. package/data/probe/examples/chat/test-agentic-image-loading.js +294 -0
  116. package/data/probe/examples/chat/test-ai-sdk-telemetry.js +204 -0
  117. package/data/probe/examples/chat/test-chat-tracing.js +38 -0
  118. package/data/probe/examples/chat/test-direct-function.js +49 -0
  119. package/data/probe/examples/chat/test-file-size-validation.js +103 -0
  120. package/data/probe/examples/chat/test-full-mcp-integration.js +258 -0
  121. package/data/probe/examples/chat/test-github-context.txt +12 -0
  122. package/data/probe/examples/chat/test-hierarchy.js +203 -0
  123. package/data/probe/examples/chat/test-image-spans.js +37 -0
  124. package/data/probe/examples/chat/test-local-image-reading.js +176 -0
  125. package/data/probe/examples/chat/test-mcp-integration.js +136 -0
  126. package/data/probe/examples/chat/test-mcp-probe-server.js +161 -0
  127. package/data/probe/examples/chat/test-mcp-with-ai.js +279 -0
  128. package/data/probe/examples/chat/test-multiple-allowed-dirs.js +111 -0
  129. package/data/probe/examples/chat/test-probe-mcp-server.js +110 -0
  130. package/data/probe/examples/chat/test-security-validation.js +145 -0
  131. package/data/probe/examples/chat/test-simple-tracing.js +32 -0
  132. package/data/probe/examples/chat/test-trace-verification.js +235 -0
  133. package/data/probe/examples/chat/test-tracing.js +114 -0
  134. package/data/probe/examples/chat/tokenCounter.js +419 -0
  135. package/data/probe/examples/chat/tokenUsageDisplay.js +134 -0
  136. package/data/probe/examples/chat/webServer.js +1103 -0
  137. package/data/probe/examples/reranker/Cargo.toml +33 -0
  138. package/data/probe/examples/reranker/DEBUG_OUTPUT_ANALYSIS.md +71 -0
  139. package/data/probe/examples/reranker/MODELS.md +66 -0
  140. package/data/probe/examples/reranker/MODEL_COMPARISON.md +60 -0
  141. package/data/probe/examples/reranker/MULTI_MODEL_ANALYSIS.md +176 -0
  142. package/data/probe/examples/reranker/PERFORMANCE_SUMMARY.md +156 -0
  143. package/data/probe/examples/reranker/README.md +347 -0
  144. package/data/probe/examples/reranker/RUST_BERT_COMPARISON.md +82 -0
  145. package/data/probe/examples/reranker/TOKENIZATION_GUIDE.md +120 -0
  146. package/data/probe/examples/reranker/check_rust_tokenizer.py +108 -0
  147. package/data/probe/examples/reranker/convert_to_torchscript.py +109 -0
  148. package/data/probe/examples/reranker/debug_scoring.py +189 -0
  149. package/data/probe/examples/reranker/debug_tokenization.py +154 -0
  150. package/data/probe/examples/reranker/download_models.sh +73 -0
  151. package/data/probe/examples/reranker/requirements.txt +13 -0
  152. package/data/probe/examples/reranker/run_comprehensive_benchmark.sh +83 -0
  153. package/data/probe/examples/reranker/rust_bert_test/Cargo.toml +12 -0
  154. package/data/probe/examples/reranker/rust_bert_test/README.md +54 -0
  155. package/data/probe/examples/reranker/simple_test.py +50 -0
  156. package/data/probe/examples/reranker/test_all_models.sh +63 -0
  157. package/data/probe/examples/reranker/test_bert_results.sh +44 -0
  158. package/data/probe/examples/reranker/test_cross_encoder.py +334 -0
  159. package/data/probe/examples/reranker/test_cross_encoder.sh +80 -0
  160. package/data/probe/examples/reranker/test_exact_comparison.py +151 -0
  161. package/data/probe/examples/reranker/test_parallel_performance.sh +56 -0
  162. package/data/probe/examples/reranker/test_scores.py +132 -0
  163. package/data/probe/install.ps1 +508 -0
  164. package/data/probe/install.sh +460 -0
  165. package/data/probe/npm/CLONE_METHOD_EXAMPLES.md +596 -0
  166. package/data/probe/npm/CONTEXT_COMPACTION.md +303 -0
  167. package/data/probe/npm/DELEGATE_TOOL_README.md +166 -0
  168. package/data/probe/npm/MAID_INTEGRATION.md +313 -0
  169. package/data/probe/npm/MCP_INTEGRATION_SUMMARY.md +241 -0
  170. package/data/probe/npm/README.md +824 -0
  171. package/data/probe/npm/bin/.gitignore +7 -0
  172. package/data/probe/npm/bin/.gitkeep +0 -0
  173. package/data/probe/npm/bin/README.md +12 -0
  174. package/data/probe/npm/bin/probe +167 -0
  175. package/data/probe/npm/docs/CLAUDE_CODE_INTEGRATION.md +414 -0
  176. package/data/probe/npm/docs/CODEX_INTEGRATION.md +502 -0
  177. package/data/probe/npm/docs/EDIT_CREATE_TOOLS.md +233 -0
  178. package/data/probe/npm/docs/RETRY_AND_FALLBACK.md +674 -0
  179. package/data/probe/npm/example-usage.js +335 -0
  180. package/data/probe/npm/examples/multi-engine-demo.js +117 -0
  181. package/data/probe/npm/examples/probe-agent-cli.js +113 -0
  182. package/data/probe/npm/examples/test-agent-edit.js +114 -0
  183. package/data/probe/npm/examples/test-edit-create.js +120 -0
  184. package/data/probe/npm/examples/test-edit-direct.js +114 -0
  185. package/data/probe/npm/index.d.ts +744 -0
  186. package/data/probe/npm/jest.config.js +52 -0
  187. package/data/probe/npm/package.json +117 -0
  188. package/data/probe/npm/scripts/build-agent.cjs +75 -0
  189. package/data/probe/npm/scripts/build-cjs.js +124 -0
  190. package/data/probe/npm/scripts/build-mcp.cjs +36 -0
  191. package/data/probe/npm/scripts/postinstall.js +216 -0
  192. package/data/probe/npm/test-codex-e2e.js +78 -0
  193. package/data/probe/npm/test-download-lock.js +109 -0
  194. package/data/probe/npm/test-grep-security.js +94 -0
  195. package/data/probe/npm/test-grep-simplified.js +63 -0
  196. package/data/probe/npm/test-grep.js +51 -0
  197. package/data/probe/npm/tests/README.md +96 -0
  198. package/data/probe/npm/tests/agent-compact-history.test.js +174 -0
  199. package/data/probe/npm/tests/allow-tests-default.test.js +151 -0
  200. package/data/probe/npm/tests/contextCompactor.test.js +498 -0
  201. package/data/probe/npm/tests/delegate-config.test.js +353 -0
  202. package/data/probe/npm/tests/delegate-integration.test.js +348 -0
  203. package/data/probe/npm/tests/extractor-integration.test.js +162 -0
  204. package/data/probe/npm/tests/extractor.test.js +317 -0
  205. package/data/probe/npm/tests/fixtures/sampleDiagrams.js +267 -0
  206. package/data/probe/npm/tests/integration/claude-code-auto-fallback.spec.js +148 -0
  207. package/data/probe/npm/tests/integration/claude-code-multi-step.spec.js +127 -0
  208. package/data/probe/npm/tests/integration/claude-code-tool-events.spec.js +163 -0
  209. package/data/probe/npm/tests/integration/codex-auto-fallback.spec.js +191 -0
  210. package/data/probe/npm/tests/integration/codex-tool-events.spec.js +147 -0
  211. package/data/probe/npm/tests/integration/examplesChatMcp.test.js +402 -0
  212. package/data/probe/npm/tests/integration/mcpDotenvSupport.test.js +174 -0
  213. package/data/probe/npm/tests/integration/mcpErrorHandling.test.js +566 -0
  214. package/data/probe/npm/tests/integration/mcpRobustness.test.js +564 -0
  215. package/data/probe/npm/tests/integration/mcpStdoutPurity.test.js +355 -0
  216. package/data/probe/npm/tests/integration/probeAgentMcp.test.js +398 -0
  217. package/data/probe/npm/tests/integration/retryFallback.test.js +368 -0
  218. package/data/probe/npm/tests/integration/schema-in-initial-message.test.js +318 -0
  219. package/data/probe/npm/tests/integration/schema-validation-loop-prevention.test.js +244 -0
  220. package/data/probe/npm/tests/integration/schemaRetryLogic.test.js +94 -0
  221. package/data/probe/npm/tests/integration/validationFlow.test.js +329 -0
  222. package/data/probe/npm/tests/manual/test-codex-basic.js +110 -0
  223. package/data/probe/npm/tests/mcp/mcpClientManager.test.js +614 -0
  224. package/data/probe/npm/tests/mcp/mcpConfig.test.js +359 -0
  225. package/data/probe/npm/tests/mcp/mcpXmlBridge.test.js +436 -0
  226. package/data/probe/npm/tests/mcp/mockMcpServer.js +510 -0
  227. package/data/probe/npm/tests/mcp-strict-syntax.test.js +319 -0
  228. package/data/probe/npm/tests/mermaidQuoteEscaping.test.js +214 -0
  229. package/data/probe/npm/tests/nestedQuoteFix.test.js +40 -0
  230. package/data/probe/npm/tests/setup.js +46 -0
  231. package/data/probe/npm/tests/unit/allowed-tools.test.js +513 -0
  232. package/data/probe/npm/tests/unit/attempt-completion-closing-tag-in-content.test.js +188 -0
  233. package/data/probe/npm/tests/unit/attemptCompletionJsonFix.test.js +238 -0
  234. package/data/probe/npm/tests/unit/attemptCompletionJsonIssue.test.js +128 -0
  235. package/data/probe/npm/tests/unit/backtickAutoFix.test.js +35 -0
  236. package/data/probe/npm/tests/unit/bash-probe-agent-integration.test.js +389 -0
  237. package/data/probe/npm/tests/unit/bash-simple-commands.test.js +324 -0
  238. package/data/probe/npm/tests/unit/bash-tool-comprehensive.test.js +371 -0
  239. package/data/probe/npm/tests/unit/bash-tool-integration.test.js +310 -0
  240. package/data/probe/npm/tests/unit/bash-tool.test.js +341 -0
  241. package/data/probe/npm/tests/unit/completion-prompt.test.js +379 -0
  242. package/data/probe/npm/tests/unit/cwd-path-options.test.js +287 -0
  243. package/data/probe/npm/tests/unit/delegate-limits.test.js +422 -0
  244. package/data/probe/npm/tests/unit/direct-content-attempt-completion.test.js +235 -0
  245. package/data/probe/npm/tests/unit/edit-create-tools.test.js +609 -0
  246. package/data/probe/npm/tests/unit/enhancedMermaidValidation.test.js +577 -0
  247. package/data/probe/npm/tests/unit/extract-content.test.js +83 -0
  248. package/data/probe/npm/tests/unit/extract-multiple-targets.test.js +89 -0
  249. package/data/probe/npm/tests/unit/fallbackManager.test.js +442 -0
  250. package/data/probe/npm/tests/unit/githubCompatibilityValidation.test.js +258 -0
  251. package/data/probe/npm/tests/unit/imageConfig.test.js +149 -0
  252. package/data/probe/npm/tests/unit/imagePathResolution.test.js +345 -0
  253. package/data/probe/npm/tests/unit/json-fixing-agent.test.js +238 -0
  254. package/data/probe/npm/tests/unit/json-validation-enhanced-errors.test.js +199 -0
  255. package/data/probe/npm/tests/unit/jsonValidationInfiniteLoopFix.test.js +228 -0
  256. package/data/probe/npm/tests/unit/maidIntegration.test.js +139 -0
  257. package/data/probe/npm/tests/unit/maxIterationsWarning.test.js +195 -0
  258. package/data/probe/npm/tests/unit/mermaidEdgeLabelFix.test.js +161 -0
  259. package/data/probe/npm/tests/unit/mermaidHtmlEntities.test.js +76 -0
  260. package/data/probe/npm/tests/unit/mermaidInfiniteLoopFix.test.js +64 -0
  261. package/data/probe/npm/tests/unit/mermaidValidation.test.js +723 -0
  262. package/data/probe/npm/tests/unit/mermaidValidationVisorExample.test.js +309 -0
  263. package/data/probe/npm/tests/unit/probe-agent-clone-realistic.test.js +643 -0
  264. package/data/probe/npm/tests/unit/probe-agent-clone.test.js +476 -0
  265. package/data/probe/npm/tests/unit/probe-agent-delegate.test.js +400 -0
  266. package/data/probe/npm/tests/unit/probe-agent-model-option.test.js +118 -0
  267. package/data/probe/npm/tests/unit/probeTool-security.test.js +283 -0
  268. package/data/probe/npm/tests/unit/readImageTool.test.js +418 -0
  269. package/data/probe/npm/tests/unit/retryManager.test.js +317 -0
  270. package/data/probe/npm/tests/unit/schema-aware-reminders.test.js +288 -0
  271. package/data/probe/npm/tests/unit/schemaDefinitionDetection.test.js +115 -0
  272. package/data/probe/npm/tests/unit/schemaUtils.test.js +1268 -0
  273. package/data/probe/npm/tests/unit/simpleTelemetry.test.js +282 -0
  274. package/data/probe/npm/tests/unit/simplified-attempt-completion.test.js +274 -0
  275. package/data/probe/npm/tests/unit/single-quote-json-bug.test.js +231 -0
  276. package/data/probe/npm/tests/unit/subgraphAutoFix.test.js +110 -0
  277. package/data/probe/npm/tests/unit/system-prompt.test.js +32 -0
  278. package/data/probe/npm/tests/unit/types-probe-agent-options.test.js +42 -0
  279. package/data/probe/npm/tests/unit/xmlParsing.test.js +720 -0
  280. package/data/probe/npm/tsconfig.json +21 -0
  281. package/data/probe/result1.txt +19 -0
  282. package/data/probe/result2.txt +26 -0
  283. package/data/probe/scripts/benchmark.sh +270 -0
  284. package/data/probe/scripts/cache_memory_analysis.rs +844 -0
  285. package/data/probe/scripts/claude-hook-wrapper.sh +56 -0
  286. package/data/probe/site/.env.example +10 -0
  287. package/data/probe/site/DEPLOYMENT.md +86 -0
  288. package/data/probe/site/README.md +183 -0
  289. package/data/probe/site/adding-languages.md +135 -0
  290. package/data/probe/site/ai-chat.md +427 -0
  291. package/data/probe/site/ai-integration.md +1488 -0
  292. package/data/probe/site/blog/agentic-flow-custom-xml-protocol.md +407 -0
  293. package/data/probe/site/blog/index.md +118 -0
  294. package/data/probe/site/blog/v0.6.0-release.md +426 -0
  295. package/data/probe/site/blog.md +8 -0
  296. package/data/probe/site/changelog.md +200 -0
  297. package/data/probe/site/cli-mode.md +437 -0
  298. package/data/probe/site/code-extraction.md +436 -0
  299. package/data/probe/site/contributing/README.md +9 -0
  300. package/data/probe/site/contributing/documentation-cross-references.md +215 -0
  301. package/data/probe/site/contributing/documentation-maintenance.md +275 -0
  302. package/data/probe/site/contributing/documentation-structure.md +75 -0
  303. package/data/probe/site/documentation-cross-references.md +215 -0
  304. package/data/probe/site/documentation-guide.md +132 -0
  305. package/data/probe/site/documentation-maintenance.md +275 -0
  306. package/data/probe/site/features.md +147 -0
  307. package/data/probe/site/how-it-works.md +118 -0
  308. package/data/probe/site/index.md +175 -0
  309. package/data/probe/site/index.md.bak +133 -0
  310. package/data/probe/site/installation.md +235 -0
  311. package/data/probe/site/integrations/docker.md +248 -0
  312. package/data/probe/site/integrations/github-actions.md +413 -0
  313. package/data/probe/site/language-support-overview.md +168 -0
  314. package/data/probe/site/mcp-integration.md +587 -0
  315. package/data/probe/site/mcp-server.md +304 -0
  316. package/data/probe/site/navigation-structure.md +76 -0
  317. package/data/probe/site/nodejs-sdk.md +798 -0
  318. package/data/probe/site/output-formats.md +625 -0
  319. package/data/probe/site/package.json +21 -0
  320. package/data/probe/site/public/_headers +28 -0
  321. package/data/probe/site/public/_redirects +11 -0
  322. package/data/probe/site/quick-start.md +289 -0
  323. package/data/probe/site/search-functionality.md +291 -0
  324. package/data/probe/site/search-reference.md +291 -0
  325. package/data/probe/site/supported-languages.md +215 -0
  326. package/data/probe/site/use-cases/README.md +8 -0
  327. package/data/probe/site/use-cases/advanced-cli.md +253 -0
  328. package/data/probe/site/use-cases/ai-code-editors.md +239 -0
  329. package/data/probe/site/use-cases/building-ai-tools.md +529 -0
  330. package/data/probe/site/use-cases/cli-ai-workflows.md +285 -0
  331. package/data/probe/site/use-cases/deploying-probe-web-interface.md +255 -0
  332. package/data/probe/site/use-cases/integrating-probe-into-ai-code-editors.md +161 -0
  333. package/data/probe/site/use-cases/nodejs-sdk.md +596 -0
  334. package/data/probe/site/use-cases/team-chat.md +350 -0
  335. package/data/probe/site/web-interface.md +434 -0
  336. package/data/probe/site/wrangler.toml +9 -0
  337. package/data/probe/test-api-key.sh +1 -0
  338. package/data/probe/test-probe-implementation/hello.js +7 -0
  339. package/data/probe/test_cases/demonstrate_early_termination_issues.sh +176 -0
  340. package/data/probe/test_cases/early_termination_issues.rs +533 -0
  341. package/data/probe/test_data/test_nested_struct.go +26 -0
  342. package/data/probe/tests/README.md +286 -0
  343. package/data/probe/tests/README_search_determinism_tests.md +116 -0
  344. package/data/probe/tests/adjacent_comment_test.rs +152 -0
  345. package/data/probe/tests/apostrophe_handling_tests.rs +132 -0
  346. package/data/probe/tests/block_filtering_with_ast_tests.rs +669 -0
  347. package/data/probe/tests/block_merging_tests.rs +396 -0
  348. package/data/probe/tests/c_outline_format_tests.rs +2179 -0
  349. package/data/probe/tests/cache_invalidation_issues.rs.disabled +682 -0
  350. package/data/probe/tests/cache_order_tests.rs +147 -0
  351. package/data/probe/tests/cache_query_scoping_tests.rs +221 -0
  352. package/data/probe/tests/cli_tests.rs +680 -0
  353. package/data/probe/tests/comment_context_integration_test.rs +240 -0
  354. package/data/probe/tests/common.rs +33 -0
  355. package/data/probe/tests/complex_block_merging_tests.rs +599 -0
  356. package/data/probe/tests/complex_query_block_filtering_tests.rs +422 -0
  357. package/data/probe/tests/control_flow_closing_braces_test.rs +91 -0
  358. package/data/probe/tests/cpp_outline_format_tests.rs +1507 -0
  359. package/data/probe/tests/csharp_outline_format_tests.rs +941 -0
  360. package/data/probe/tests/elastic_query_integration_tests.rs +922 -0
  361. package/data/probe/tests/extract_command_tests.rs +1848 -0
  362. package/data/probe/tests/extract_deduplication_tests.rs +146 -0
  363. package/data/probe/tests/extract_input_file_tests.rs +84 -0
  364. package/data/probe/tests/extract_prompt_tests.rs +102 -0
  365. package/data/probe/tests/filename_search_tests.rs +96 -0
  366. package/data/probe/tests/fixtures/user/AssemblyInfo.cs +3 -0
  367. package/data/probe/tests/github_extract_tests.rs +234 -0
  368. package/data/probe/tests/go_comment_test.rs +253 -0
  369. package/data/probe/tests/go_outline_format_tests.rs +2587 -0
  370. package/data/probe/tests/go_path_resolver_tests.rs +96 -0
  371. package/data/probe/tests/html_outline_format_tests.rs +637 -0
  372. package/data/probe/tests/integration_tests.rs +837 -0
  373. package/data/probe/tests/ip_whitelist_test.rs +148 -0
  374. package/data/probe/tests/java_outline_format_tests.rs +1611 -0
  375. package/data/probe/tests/javascript_extract_tests.rs +315 -0
  376. package/data/probe/tests/javascript_outline_format_tests.rs +1464 -0
  377. package/data/probe/tests/json_format_tests.rs +436 -0
  378. package/data/probe/tests/json_schema_validation_tests.rs +450 -0
  379. package/data/probe/tests/lib_usage.rs +60 -0
  380. package/data/probe/tests/line_comment_context_extension_test.rs +459 -0
  381. package/data/probe/tests/line_map_cache_tests.rs +114 -0
  382. package/data/probe/tests/markdown_integration_tests.rs +190 -0
  383. package/data/probe/tests/mocks/test_ip_whitelist.go +11 -0
  384. package/data/probe/tests/mocks/test_object.js +27 -0
  385. package/data/probe/tests/mocks/test_struct.go +50 -0
  386. package/data/probe/tests/multi_keyword_pattern_tests.rs +464 -0
  387. package/data/probe/tests/multi_language_syntax_integration_tests.rs +218 -0
  388. package/data/probe/tests/multiple_capture_groups_tests.rs +169 -0
  389. package/data/probe/tests/negative_compound_word_tests.rs +246 -0
  390. package/data/probe/tests/nested_symbol_extraction_tests.rs +99 -0
  391. package/data/probe/tests/outline_cross_file_interference_test.rs +335 -0
  392. package/data/probe/tests/outline_keyword_preservation_test.rs +67 -0
  393. package/data/probe/tests/output_format_edge_cases_tests.rs +693 -0
  394. package/data/probe/tests/parallel_extraction_tests.rs +178 -0
  395. package/data/probe/tests/parallel_search_tests.rs +355 -0
  396. package/data/probe/tests/path_resolver_tests.rs +698 -0
  397. package/data/probe/tests/php_outline_format_extended_tests.rs +928 -0
  398. package/data/probe/tests/php_outline_format_tests.rs +768 -0
  399. package/data/probe/tests/property_tests.proptest-regressions +9 -0
  400. package/data/probe/tests/property_tests.rs +118 -0
  401. package/data/probe/tests/python_outline_format_tests.rs +1538 -0
  402. package/data/probe/tests/query_command_json_tests.rs +438 -0
  403. package/data/probe/tests/query_command_tests.rs +232 -0
  404. package/data/probe/tests/query_command_xml_tests.rs +569 -0
  405. package/data/probe/tests/quoted_term_with_negative_keyword_tests.rs +216 -0
  406. package/data/probe/tests/required_terms_filename_tests.rs +116 -0
  407. package/data/probe/tests/ruby_outline_format_tests.rs +1011 -0
  408. package/data/probe/tests/rust_line_comment_context_test.rs +151 -0
  409. package/data/probe/tests/rust_outline_format_enhanced_tests.rs +725 -0
  410. package/data/probe/tests/rust_outline_format_tests.rs +843 -0
  411. package/data/probe/tests/schemas/xml_output_schema.xsd +38 -0
  412. package/data/probe/tests/search_determinism_tests.rs +451 -0
  413. package/data/probe/tests/search_hints_tests.rs +253 -0
  414. package/data/probe/tests/special_character_escaping_tests.rs +417 -0
  415. package/data/probe/tests/stemming_compound_word_filtering_tests.rs +535 -0
  416. package/data/probe/tests/strict_elastic_syntax_tests.rs +404 -0
  417. package/data/probe/tests/swift_outline_format_tests.rs +3319 -0
  418. package/data/probe/tests/symbols_tests.rs +166 -0
  419. package/data/probe/tests/test_file.rs +45 -0
  420. package/data/probe/tests/test_tokenize.rs +28 -0
  421. package/data/probe/tests/timeout_tests.rs +82 -0
  422. package/data/probe/tests/tokenization_tests.rs +195 -0
  423. package/data/probe/tests/tokenized_block_filtering_tests.rs +174 -0
  424. package/data/probe/tests/typescript_extract_tests.rs +214 -0
  425. package/data/probe/tests/typescript_outline_format_tests.rs +2188 -0
  426. package/data/probe/tests/xml_format_tests.rs +568 -0
  427. package/data/probe/tests/xml_schema_validation_tests.rs +497 -0
  428. package/data/scripts/postinstall.mjs +9 -0
  429. package/data/scripts/set-version.js +0 -0
  430. package/data/scripts/wiki-build.sh +111 -0
  431. package/data/scripts/wiki-deploy.sh +73 -0
  432. package/data/serve.json +12 -0
  433. package/data/test/demo-dynamic.html +134 -0
  434. package/data/test/demo-esm.html +105 -0
  435. package/data/test/demo-iife.html +78 -0
  436. package/data/tsconfig.json +7 -0
  437. package/data/vite.server.ts +483 -0
  438. package/data/vitest.config.ts +40 -0
  439. package/data/wiki/Home.md +58 -0
  440. package/data/wiki/_Sidebar.md +39 -0
  441. package/docs-mcp.config.json +20 -0
  442. package/package.json +56 -0
  443. package/src/config.js +111 -0
  444. package/src/index.js +395 -0
@@ -0,0 +1,928 @@
1
+ use anyhow::Result;
2
+ use std::fs;
3
+ use tempfile::TempDir;
4
+
5
+ mod common;
6
+ use common::TestContext;
7
+
8
+ #[test]
9
+ fn test_php_specific_constructs() -> Result<()> {
10
+ let temp_dir = TempDir::new()?;
11
+ let test_file = temp_dir.path().join("php_constructs.php");
12
+
13
+ let content = r#"<?php
14
+
15
+ namespace App\Core;
16
+
17
+ use Countable;
18
+ use ArrayAccess;
19
+
20
+ trait Cacheable
21
+ {
22
+ private array $cache = [];
23
+
24
+ protected function getCacheKey(string $method, array $args): string
25
+ {
26
+ return md5($method . serialize($args));
27
+ }
28
+
29
+ protected function getFromCache(string $key)
30
+ {
31
+ return $this->cache[$key] ?? null;
32
+ }
33
+
34
+ protected function putInCache(string $key, $value): void
35
+ {
36
+ $this->cache[$key] = $value;
37
+ }
38
+ }
39
+
40
+ trait Searchable
41
+ {
42
+ abstract protected function getSearchableFields(): array;
43
+
44
+ public function search(string $query): array
45
+ {
46
+ $fields = $this->getSearchableFields();
47
+ $results = [];
48
+
49
+ foreach ($fields as $field) {
50
+ if (stripos($this->$field, $query) !== false) {
51
+ $results[] = $field;
52
+ }
53
+ }
54
+
55
+ return $results;
56
+ }
57
+ }
58
+
59
+ abstract class BaseModel implements Countable, ArrayAccess
60
+ {
61
+ use Cacheable, Searchable;
62
+
63
+ protected array $data = [];
64
+ protected array $searchableFields = [];
65
+
66
+ public function __construct(array $data = [])
67
+ {
68
+ $this->data = $data;
69
+ }
70
+
71
+ // Magic methods
72
+ public function __get(string $name)
73
+ {
74
+ return $this->data[$name] ?? null;
75
+ }
76
+
77
+ public function __set(string $name, $value): void
78
+ {
79
+ $this->data[$name] = $value;
80
+ }
81
+
82
+ public function __isset(string $name): bool
83
+ {
84
+ return isset($this->data[$name]);
85
+ }
86
+
87
+ public function __unset(string $name): void
88
+ {
89
+ unset($this->data[$name]);
90
+ }
91
+
92
+ public function __toString(): string
93
+ {
94
+ return json_encode($this->data);
95
+ }
96
+
97
+ public function __debugInfo(): array
98
+ {
99
+ return ['data' => $this->data, 'searchable' => $this->searchableFields];
100
+ }
101
+
102
+ // ArrayAccess implementation
103
+ public function offsetExists($offset): bool
104
+ {
105
+ return isset($this->data[$offset]);
106
+ }
107
+
108
+ public function offsetGet($offset)
109
+ {
110
+ return $this->data[$offset] ?? null;
111
+ }
112
+
113
+ public function offsetSet($offset, $value): void
114
+ {
115
+ if (is_null($offset)) {
116
+ $this->data[] = $value;
117
+ } else {
118
+ $this->data[$offset] = $value;
119
+ }
120
+ }
121
+
122
+ public function offsetUnset($offset): void
123
+ {
124
+ unset($this->data[$offset]);
125
+ }
126
+
127
+ // Countable implementation
128
+ public function count(): int
129
+ {
130
+ return count($this->data);
131
+ }
132
+
133
+ // Abstract methods
134
+ abstract protected function validate(): bool;
135
+ abstract public function save(): bool;
136
+
137
+ protected function getSearchableFields(): array
138
+ {
139
+ return $this->searchableFields;
140
+ }
141
+ }
142
+
143
+ interface SearchableInterface
144
+ {
145
+ public function search(string $query): array;
146
+ public function getSearchableFields(): array;
147
+ }
148
+
149
+ class User extends BaseModel implements SearchableInterface
150
+ {
151
+ protected array $searchableFields = ['name', 'email', 'bio'];
152
+
153
+ public function __construct(array $data = [])
154
+ {
155
+ parent::__construct($data);
156
+ $this->data['created_at'] = $this->data['created_at'] ?? date('Y-m-d H:i:s');
157
+ }
158
+
159
+ protected function validate(): bool
160
+ {
161
+ return !empty($this->data['name']) && !empty($this->data['email']);
162
+ }
163
+
164
+ public function save(): bool
165
+ {
166
+ if (!$this->validate()) {
167
+ return false;
168
+ }
169
+
170
+ // Save logic here
171
+ return true;
172
+ }
173
+
174
+ public function getSearchableFields(): array
175
+ {
176
+ return $this->searchableFields;
177
+ }
178
+ }
179
+ "#;
180
+
181
+ fs::write(&test_file, content)?;
182
+
183
+ let ctx = TestContext::new();
184
+ let output = ctx.run_probe(&[
185
+ "search",
186
+ "class|trait|interface|function",
187
+ test_file.to_str().unwrap(),
188
+ "--format",
189
+ "outline",
190
+ ])?;
191
+
192
+ // Should extract PHP-specific constructs
193
+ assert!(
194
+ output.contains("trait") || output.contains("Cacheable"),
195
+ "Should extract traits - output: {}",
196
+ output
197
+ );
198
+
199
+ assert!(
200
+ output.contains("namespace") || output.contains("App\\Core"),
201
+ "Should show namespace - output: {}",
202
+ output
203
+ );
204
+
205
+ assert!(
206
+ output.contains("interface") || output.contains("SearchableInterface"),
207
+ "Should extract interfaces - output: {}",
208
+ output
209
+ );
210
+
211
+ assert!(
212
+ output.contains("abstract") || output.contains("BaseModel"),
213
+ "Should extract abstract classes - output: {}",
214
+ output
215
+ );
216
+
217
+ // Should show magic methods
218
+ assert!(
219
+ output.contains("__get") || output.contains("__set") || output.contains("__construct"),
220
+ "Should show magic methods - output: {}",
221
+ output
222
+ );
223
+
224
+ Ok(())
225
+ }
226
+
227
+ #[test]
228
+ fn test_php_control_flow_closing_braces() -> Result<()> {
229
+ let temp_dir = TempDir::new()?;
230
+ let test_file = temp_dir.path().join("control_flow.php");
231
+
232
+ let content = r#"<?php
233
+
234
+ class FlowController
235
+ {
236
+ public function processData(array $data): array
237
+ {
238
+ $results = [];
239
+ $counter = 0;
240
+
241
+ foreach ($data as $index => $item) {
242
+ if ($item === null) {
243
+ continue;
244
+ }
245
+
246
+ if (is_array($item)) {
247
+ foreach ($item as $key => $value) {
248
+ if (is_string($value)) {
249
+ $processed = strtolower($value);
250
+ $results[] = $processed;
251
+ $counter++;
252
+ } elseif (is_numeric($value)) {
253
+ $results[] = (float) $value;
254
+ $counter++;
255
+ }
256
+ }
257
+ } else {
258
+ switch (gettype($item)) {
259
+ case 'string':
260
+ $results[] = trim($item);
261
+ break;
262
+ case 'integer':
263
+ case 'double':
264
+ $results[] = $item * 2;
265
+ break;
266
+ default:
267
+ $results[] = 'unknown';
268
+ }
269
+ $counter++;
270
+ }
271
+
272
+ // Break if we have enough results
273
+ if ($counter >= 100) {
274
+ break;
275
+ }
276
+ }
277
+
278
+ return $results;
279
+ }
280
+
281
+ public function complexLogic(array $conditions): string
282
+ {
283
+ $result = 'default';
284
+
285
+ try {
286
+ if (!empty($conditions)) {
287
+ foreach ($conditions as $condition) {
288
+ if ($condition['type'] === 'search') {
289
+ $searchTerm = $condition['value'];
290
+
291
+ if (strlen($searchTerm) > 3) {
292
+ $result = 'search: ' . $searchTerm;
293
+ } else {
294
+ $result = 'short_search';
295
+ }
296
+ } elseif ($condition['type'] === 'filter') {
297
+ $filterValue = $condition['value'];
298
+
299
+ if (is_array($filterValue)) {
300
+ foreach ($filterValue as $filter) {
301
+ if (strpos($filter, 'important') !== false) {
302
+ $result = 'important_filter';
303
+ break 2;
304
+ }
305
+ }
306
+ }
307
+ }
308
+ }
309
+ }
310
+ } catch (Exception $e) {
311
+ $result = 'error: ' . $e->getMessage();
312
+ } finally {
313
+ $result .= ' [processed]';
314
+ }
315
+
316
+ return $result;
317
+ }
318
+ }
319
+ "#;
320
+
321
+ fs::write(&test_file, content)?;
322
+
323
+ let ctx = TestContext::new();
324
+ let output = ctx.run_probe(&[
325
+ "search",
326
+ "class|trait|interface|function",
327
+ test_file.to_str().unwrap(),
328
+ "--format",
329
+ "outline",
330
+ ])?;
331
+
332
+ // Should show control flow structures
333
+ assert!(
334
+ output.contains("foreach") || output.contains("if") || output.contains("switch"),
335
+ "Should show control flow structures - output: {}",
336
+ output
337
+ );
338
+
339
+ // Should have closing braces for large methods with // comments
340
+ assert!(
341
+ output.contains("//")
342
+ && (output.contains("processData") || output.contains("complexLogic")),
343
+ "Should have closing brace comments for large methods - output: {}",
344
+ output
345
+ );
346
+
347
+ // Should show try/catch/finally
348
+ assert!(
349
+ output.contains("try") || output.contains("catch") || output.contains("finally"),
350
+ "Should show try/catch/finally structures - output: {}",
351
+ output
352
+ );
353
+
354
+ Ok(())
355
+ }
356
+
357
+ #[test]
358
+ fn test_php_test_detection() -> Result<()> {
359
+ let temp_dir = TempDir::new()?;
360
+ let test_file = temp_dir.path().join("TestCalculator.php");
361
+
362
+ let content = r#"<?php
363
+
364
+ namespace Tests\Unit;
365
+
366
+ use PHPUnit\Framework\TestCase;
367
+ use App\Calculator;
368
+
369
+ class CalculatorTest extends TestCase
370
+ {
371
+ private Calculator $calculator;
372
+
373
+ protected function setUp(): void
374
+ {
375
+ parent::setUp();
376
+ $this->calculator = new Calculator();
377
+ }
378
+
379
+ protected function tearDown(): void
380
+ {
381
+ parent::tearDown();
382
+ unset($this->calculator);
383
+ }
384
+
385
+ /**
386
+ * @test
387
+ */
388
+ public function it_can_add_two_numbers(): void
389
+ {
390
+ $result = $this->calculator->add(2, 3);
391
+ $this->assertEquals(5, $result);
392
+ }
393
+
394
+ /**
395
+ * @test
396
+ * @dataProvider additionProvider
397
+ */
398
+ public function it_can_add_with_data_provider(int $a, int $b, int $expected): void
399
+ {
400
+ $result = $this->calculator->add($a, $b);
401
+ $this->assertEquals($expected, $result);
402
+ }
403
+
404
+ public function testMultiplication(): void
405
+ {
406
+ $result = $this->calculator->multiply(4, 5);
407
+ $this->assertSame(20, $result);
408
+ }
409
+
410
+ public function testDivisionByZero(): void
411
+ {
412
+ $this->expectException(InvalidArgumentException::class);
413
+ $this->calculator->divide(10, 0);
414
+ }
415
+
416
+ /**
417
+ * @test
418
+ * @group integration
419
+ */
420
+ public function it_handles_complex_calculations(): void
421
+ {
422
+ $result = $this->calculator->add(10, 5);
423
+ $result = $this->calculator->multiply($result, 2);
424
+ $result = $this->calculator->subtract($result, 5);
425
+
426
+ $this->assertEquals(25, $result);
427
+ }
428
+
429
+ public function additionProvider(): array
430
+ {
431
+ return [
432
+ [1, 1, 2],
433
+ [2, 3, 5],
434
+ [-1, 1, 0],
435
+ [0, 0, 0],
436
+ ];
437
+ }
438
+ }
439
+
440
+ // Simple test functions (non-PHPUnit style)
441
+ function testSimpleAddition(): bool
442
+ {
443
+ $calc = new Calculator();
444
+ return $calc->add(1, 1) === 2;
445
+ }
446
+
447
+ function test_snake_case_function(): bool
448
+ {
449
+ $calc = new Calculator();
450
+ return $calc->subtract(5, 3) === 2;
451
+ }
452
+
453
+ function validateCalculatorBehavior(): bool
454
+ {
455
+ // This is a test function but doesn't start with 'test'
456
+ $calc = new Calculator();
457
+ return $calc->multiply(2, 3) === 6;
458
+ }
459
+ "#;
460
+
461
+ fs::write(&test_file, content)?;
462
+
463
+ let ctx = TestContext::new();
464
+ let output = ctx.run_probe(&[
465
+ "extract",
466
+ test_file.to_str().unwrap(),
467
+ "--format",
468
+ "outline",
469
+ "--allow-tests",
470
+ ])?;
471
+
472
+ // Should detect PHPUnit test class
473
+ assert!(
474
+ output.contains("CalculatorTest") || output.contains("TestCase"),
475
+ "Should detect PHPUnit test class - output: {}",
476
+ output
477
+ );
478
+
479
+ // Should detect test methods with @test annotation
480
+ assert!(
481
+ output.contains("it_can_add_two_numbers") || output.contains("@test"),
482
+ "Should detect @test annotated methods - output: {}",
483
+ output
484
+ );
485
+
486
+ // Should detect testXxx methods
487
+ assert!(
488
+ output.contains("testMultiplication") || output.contains("testDivisionByZero"),
489
+ "Should detect testXxx methods - output: {}",
490
+ output
491
+ );
492
+
493
+ // Should detect simple test functions
494
+ assert!(
495
+ output.contains("testSimpleAddition") || output.contains("test_snake_case_function"),
496
+ "Should detect simple test functions - output: {}",
497
+ output
498
+ );
499
+
500
+ Ok(())
501
+ }
502
+
503
+ #[test]
504
+ fn test_php_modern_features() -> Result<()> {
505
+ let temp_dir = TempDir::new()?;
506
+ let test_file = temp_dir.path().join("modern_php.php");
507
+
508
+ let content = r#"<?php
509
+
510
+ declare(strict_types=1);
511
+
512
+ namespace App\Modern;
513
+
514
+ use Closure;
515
+
516
+ // PHP 8+ Union types and named arguments
517
+ class ModernProcessor
518
+ {
519
+ public function __construct(
520
+ private readonly string $name,
521
+ private readonly array $config = [],
522
+ ) {}
523
+
524
+ // Union types (PHP 8.0+)
525
+ public function process(string|array|null $data): int|float|null
526
+ {
527
+ return match ($data) {
528
+ null => null,
529
+ default => is_string($data) ? strlen($data) : count($data),
530
+ };
531
+ }
532
+
533
+ // Arrow functions (PHP 7.4+)
534
+ public function transformArray(array $items): array
535
+ {
536
+ return array_map(
537
+ fn($item) => strtoupper((string) $item),
538
+ array_filter($items, fn($item) => !empty($item))
539
+ );
540
+ }
541
+
542
+ // Nullable return type with arrow function
543
+ public function findFirst(array $items, callable $predicate): mixed
544
+ {
545
+ foreach ($items as $item) {
546
+ if ($predicate($item)) {
547
+ return $item;
548
+ }
549
+ }
550
+ return null;
551
+ }
552
+
553
+ // Match expression (PHP 8.0+) with search logic
554
+ public function getSearchStrategy(string $type): string
555
+ {
556
+ return match($type) {
557
+ 'fuzzy' => 'levenshtein',
558
+ 'exact' => 'strict_compare',
559
+ 'partial' => 'substring_search',
560
+ 'regex' => 'preg_match',
561
+ default => 'default_search',
562
+ };
563
+ }
564
+
565
+ // Named arguments and union types
566
+ public function search(
567
+ string|array $query,
568
+ array $options = [],
569
+ bool $caseSensitive = false,
570
+ int|null $limit = null
571
+ ): array {
572
+ $strategy = $this->getSearchStrategy($options['strategy'] ?? 'partial');
573
+
574
+ return [
575
+ 'query' => $query,
576
+ 'strategy' => $strategy,
577
+ 'case_sensitive' => $caseSensitive,
578
+ 'limit' => $limit,
579
+ ];
580
+ }
581
+
582
+ // Constructor property promotion (PHP 8.0+)
583
+ public static function create(
584
+ string $name,
585
+ array $config = [],
586
+ ?string $searchEngine = null
587
+ ): self {
588
+ return new self(
589
+ name: $name,
590
+ config: [...$config, 'search_engine' => $searchEngine]
591
+ );
592
+ }
593
+
594
+ // Readonly properties (PHP 8.1+)
595
+ public function getName(): string
596
+ {
597
+ return $this->name;
598
+ }
599
+
600
+ // First-class callable syntax (PHP 8.1+)
601
+ public function getTransformer(): callable
602
+ {
603
+ return $this->transformArray(...);
604
+ }
605
+ }
606
+
607
+ // Enum (PHP 8.1+)
608
+ enum SearchType: string
609
+ {
610
+ case EXACT = 'exact';
611
+ case FUZZY = 'fuzzy';
612
+ case PARTIAL = 'partial';
613
+ case REGEX = 'regex';
614
+
615
+ public function getDescription(): string
616
+ {
617
+ return match($this) {
618
+ self::EXACT => 'Exact match search',
619
+ self::FUZZY => 'Fuzzy search with similarity',
620
+ self::PARTIAL => 'Substring search',
621
+ self::REGEX => 'Regular expression search',
622
+ };
623
+ }
624
+ }
625
+
626
+ // Anonymous class with modern features
627
+ $processor = new class implements Countable {
628
+ private array $data = [];
629
+
630
+ public function add(mixed $item): void {
631
+ $this->data[] = $item;
632
+ }
633
+
634
+ public function count(): int {
635
+ return count($this->data);
636
+ }
637
+
638
+ public function search(string $term): array {
639
+ return array_filter(
640
+ $this->data,
641
+ fn($item) => str_contains(strtolower((string) $item), strtolower($term))
642
+ );
643
+ }
644
+ };
645
+
646
+ // Modern function with arrow function and match
647
+ function processSearchResults(array $results, string $format = 'json'): string
648
+ {
649
+ $processed = array_map(
650
+ fn($result) => is_array($result) ? $result : ['value' => $result],
651
+ $results
652
+ );
653
+
654
+ return match($format) {
655
+ 'json' => json_encode($processed),
656
+ 'xml' => 'XML output not implemented',
657
+ 'csv' => implode(',', array_column($processed, 'value')),
658
+ default => serialize($processed),
659
+ };
660
+ }
661
+ "#;
662
+
663
+ fs::write(&test_file, content)?;
664
+
665
+ let ctx = TestContext::new();
666
+ let output = ctx.run_probe(&[
667
+ "search",
668
+ "search",
669
+ test_file.to_str().unwrap(),
670
+ "--format",
671
+ "outline",
672
+ "--max-results",
673
+ "20",
674
+ ])?;
675
+
676
+ // Should contain search-related content
677
+ assert!(
678
+ output.contains("search"),
679
+ "Should contain 'search' keyword - output: {}",
680
+ output
681
+ );
682
+
683
+ // Should show modern PHP features
684
+ assert!(
685
+ output.contains("match") || output.contains("fn") || output.contains("enum"),
686
+ "Should show modern PHP features (match/arrow functions/enum) - output: {}",
687
+ output
688
+ );
689
+
690
+ // Should show union types or modern syntax
691
+ assert!(
692
+ output.contains("string|array") || output.contains("int|float") || output.contains("mixed"),
693
+ "Should show union types or mixed types - output: {}",
694
+ output
695
+ );
696
+
697
+ // Should show functions with search logic
698
+ assert!(
699
+ output.contains("getSearchStrategy") || output.contains("processSearchResults"),
700
+ "Should show functions with search logic - output: {}",
701
+ output
702
+ );
703
+
704
+ Ok(())
705
+ }
706
+
707
+ #[test]
708
+ fn test_php_outline_small_vs_large_functions() -> Result<()> {
709
+ let temp_dir = TempDir::new()?;
710
+ let test_file = temp_dir.path().join("function_sizes.php");
711
+
712
+ let content = r#"<?php
713
+
714
+ // Small function - should NOT get closing brace comment
715
+ function smallFunction(string $input): string
716
+ {
717
+ return strtoupper($input);
718
+ }
719
+
720
+ // Medium function - might get closing brace comment depending on implementation
721
+ function mediumFunction(array $data): array
722
+ {
723
+ $result = [];
724
+ foreach ($data as $key => $value) {
725
+ if (is_string($value)) {
726
+ $result[$key] = trim($value);
727
+ } elseif (is_numeric($value)) {
728
+ $result[$key] = (float) $value;
729
+ }
730
+ }
731
+ return $result;
732
+ }
733
+
734
+ // Large function - should get closing brace comment
735
+ function largeProcessingFunction(array $data): array
736
+ {
737
+ $results = [];
738
+ $errors = [];
739
+ $processed = 0;
740
+
741
+ foreach ($data as $index => $item) {
742
+ try {
743
+ if (!is_array($item)) {
744
+ $errors[] = "Item at index {$index} is not an array";
745
+ continue;
746
+ }
747
+
748
+ $processedItem = [];
749
+
750
+ foreach ($item as $key => $value) {
751
+ if (empty($key)) {
752
+ continue;
753
+ }
754
+
755
+ switch (gettype($value)) {
756
+ case 'string':
757
+ $processedItem[$key] = trim(strtolower($value));
758
+ break;
759
+ case 'integer':
760
+ case 'double':
761
+ $processedItem[$key] = round((float) $value, 2);
762
+ break;
763
+ case 'boolean':
764
+ $processedItem[$key] = $value ? 1 : 0;
765
+ break;
766
+ case 'array':
767
+ if (!empty($value)) {
768
+ $processedItem[$key] = array_values($value);
769
+ }
770
+ break;
771
+ default:
772
+ $processedItem[$key] = (string) $value;
773
+ }
774
+ }
775
+
776
+ if (!empty($processedItem)) {
777
+ $results[] = $processedItem;
778
+ $processed++;
779
+ }
780
+
781
+ } catch (Exception $e) {
782
+ $errors[] = "Error processing item {$index}: " . $e->getMessage();
783
+ }
784
+ }
785
+
786
+ return [
787
+ 'results' => $results,
788
+ 'errors' => $errors,
789
+ 'processed_count' => $processed,
790
+ 'total_count' => count($data),
791
+ ];
792
+ }
793
+
794
+ class ProcessorClass
795
+ {
796
+ // Small method - should NOT get closing brace comment
797
+ public function smallMethod(): string
798
+ {
799
+ return 'small';
800
+ }
801
+
802
+ // Large method - should get closing brace comment
803
+ public function largeMethod(array $data): array
804
+ {
805
+ $config = [
806
+ 'timeout' => 30,
807
+ 'retry_count' => 3,
808
+ 'batch_size' => 100,
809
+ ];
810
+
811
+ $batches = array_chunk($data, $config['batch_size']);
812
+ $allResults = [];
813
+
814
+ foreach ($batches as $batchIndex => $batch) {
815
+ $batchResults = [];
816
+ $retryCount = 0;
817
+
818
+ while ($retryCount < $config['retry_count']) {
819
+ try {
820
+ foreach ($batch as $item) {
821
+ if ($this->validateItem($item)) {
822
+ $processed = $this->processItem($item);
823
+ if ($processed !== null) {
824
+ $batchResults[] = $processed;
825
+ }
826
+ }
827
+ }
828
+ break; // Success, exit retry loop
829
+ } catch (Exception $e) {
830
+ $retryCount++;
831
+ if ($retryCount >= $config['retry_count']) {
832
+ error_log("Failed to process batch {$batchIndex}: " . $e->getMessage());
833
+ } else {
834
+ usleep(1000 * $retryCount); // Exponential backoff
835
+ }
836
+ }
837
+ }
838
+
839
+ $allResults = array_merge($allResults, $batchResults);
840
+ }
841
+
842
+ return $allResults;
843
+ }
844
+
845
+ private function validateItem($item): bool
846
+ {
847
+ return !empty($item);
848
+ }
849
+
850
+ private function processItem($item)
851
+ {
852
+ return $item;
853
+ }
854
+ }
855
+ "#;
856
+
857
+ fs::write(&test_file, content)?;
858
+
859
+ let ctx = TestContext::new();
860
+ let output = ctx.run_probe(&[
861
+ "search",
862
+ "class|trait|interface|function",
863
+ test_file.to_str().unwrap(),
864
+ "--format",
865
+ "outline",
866
+ ])?;
867
+
868
+ // Check if we found any functions at all first
869
+ if output.contains("No results found") {
870
+ // Try a different search pattern
871
+ let output2 = ctx.run_probe(&[
872
+ "search",
873
+ "large",
874
+ test_file.to_str().unwrap(),
875
+ "--format",
876
+ "outline",
877
+ "--max-results",
878
+ "20",
879
+ ])?;
880
+
881
+ if !output2.contains("No results found") {
882
+ // Use output2 for verification if it has results
883
+ let has_large_functions = output2.contains("largeProcessingFunction")
884
+ || output2.contains("largeMethod")
885
+ || output2.contains("function");
886
+ assert!(
887
+ has_large_functions,
888
+ "Should find large functions in search results - output: {}",
889
+ output2
890
+ );
891
+ }
892
+ } else {
893
+ // Original logic for when we have results
894
+ let has_large_functions = output.contains("largeProcessingFunction")
895
+ || output.contains("largeMethod")
896
+ || output.contains("function");
897
+ assert!(
898
+ has_large_functions,
899
+ "Should find large functions in search results - output: {}",
900
+ output
901
+ );
902
+ }
903
+
904
+ // Verify small functions do NOT have closing brace comments
905
+ // Look for the section containing smallFunction and ensure no // comment follows
906
+ let small_function_present = output.contains("smallFunction");
907
+ if small_function_present {
908
+ // Get the lines around smallFunction and check no // comment immediately follows
909
+ let lines: Vec<&str> = output.lines().collect();
910
+ let small_func_line = lines.iter().position(|line| line.contains("smallFunction"));
911
+
912
+ if let Some(pos) = small_func_line {
913
+ // Check next few lines don't contain a closing brace comment for small function
914
+ let next_few_lines = lines.get(pos..pos.min(lines.len()).max(pos + 5));
915
+ if let Some(section) = next_few_lines {
916
+ let section_text = section.join("\n");
917
+ assert!(
918
+ !section_text.contains("// function smallFunction")
919
+ && !section_text.contains("// smallFunction"),
920
+ "Small function should NOT have closing brace comment in section: {}",
921
+ section_text
922
+ );
923
+ }
924
+ }
925
+ }
926
+
927
+ Ok(())
928
+ }