igel-qe-core 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 (394) hide show
  1. package/dist/cli/index.js +38 -0
  2. package/dist/mcp/server.js +104 -0
  3. package/knowledge_base/__init__.py +3 -0
  4. package/knowledge_base/__pycache__/__init__.cpython-314.pyc +0 -0
  5. package/knowledge_base/__pycache__/__init__.cpython-37.pyc +0 -0
  6. package/knowledge_base/__pycache__/__init__.cpython-38.pyc +0 -0
  7. package/knowledge_base/__pycache__/confidence.cpython-37.pyc +0 -0
  8. package/knowledge_base/__pycache__/config.cpython-314.pyc +0 -0
  9. package/knowledge_base/__pycache__/config.cpython-37.pyc +0 -0
  10. package/knowledge_base/__pycache__/config.cpython-38.pyc +0 -0
  11. package/knowledge_base/__pycache__/context_fusion.cpython-314.pyc +0 -0
  12. package/knowledge_base/__pycache__/context_fusion.cpython-37.pyc +0 -0
  13. package/knowledge_base/__pycache__/feedback_analytics.cpython-37.pyc +0 -0
  14. package/knowledge_base/__pycache__/feedback_applier.cpython-37.pyc +0 -0
  15. package/knowledge_base/__pycache__/feedback_cli.cpython-37.pyc +0 -0
  16. package/knowledge_base/__pycache__/feedback_curator.cpython-37.pyc +0 -0
  17. package/knowledge_base/__pycache__/feedback_handler.cpython-37.pyc +0 -0
  18. package/knowledge_base/__pycache__/generate.cpython-37.pyc +0 -0
  19. package/knowledge_base/__pycache__/generate_qcapps134.cpython-37.pyc +0 -0
  20. package/knowledge_base/__pycache__/input_classifier.cpython-314.pyc +0 -0
  21. package/knowledge_base/__pycache__/input_classifier.cpython-37.pyc +0 -0
  22. package/knowledge_base/__pycache__/kg_extractor.cpython-37.pyc +0 -0
  23. package/knowledge_base/__pycache__/knowledge_graph.cpython-314.pyc +0 -0
  24. package/knowledge_base/__pycache__/knowledge_graph.cpython-37.pyc +0 -0
  25. package/knowledge_base/__pycache__/manual_tc_parser.cpython-314.pyc +0 -0
  26. package/knowledge_base/__pycache__/manual_tc_parser.cpython-37.pyc +0 -0
  27. package/knowledge_base/__pycache__/precedence.cpython-37.pyc +0 -0
  28. package/knowledge_base/__pycache__/prompts.cpython-314.pyc +0 -0
  29. package/knowledge_base/__pycache__/prompts.cpython-37.pyc +0 -0
  30. package/knowledge_base/__pycache__/reranker.cpython-314.pyc +0 -0
  31. package/knowledge_base/__pycache__/reranker.cpython-37.pyc +0 -0
  32. package/knowledge_base/__pycache__/retrieval_debug.cpython-314.pyc +0 -0
  33. package/knowledge_base/__pycache__/retrieval_debug.cpython-37.pyc +0 -0
  34. package/knowledge_base/__pycache__/retriever.cpython-314.pyc +0 -0
  35. package/knowledge_base/__pycache__/retriever.cpython-37.pyc +0 -0
  36. package/knowledge_base/__pycache__/server.cpython-37.pyc +0 -0
  37. package/knowledge_base/__pycache__/tc_transformer.cpython-314.pyc +0 -0
  38. package/knowledge_base/__pycache__/tc_transformer.cpython-37.pyc +0 -0
  39. package/knowledge_base/__pycache__/test_generator.cpython-314.pyc +0 -0
  40. package/knowledge_base/__pycache__/test_generator.cpython-37.pyc +0 -0
  41. package/knowledge_base/agents/__init__.py +6 -0
  42. package/knowledge_base/agents/__pycache__/__init__.cpython-37.pyc +0 -0
  43. package/knowledge_base/agents/__pycache__/__init__.cpython-38.pyc +0 -0
  44. package/knowledge_base/agents/__pycache__/fusion_agent.cpython-37.pyc +0 -0
  45. package/knowledge_base/agents/__pycache__/fusion_agent.cpython-38.pyc +0 -0
  46. package/knowledge_base/agents/__pycache__/graph.cpython-37.pyc +0 -0
  47. package/knowledge_base/agents/__pycache__/graph.cpython-38.pyc +0 -0
  48. package/knowledge_base/agents/__pycache__/healing_agent.cpython-37.pyc +0 -0
  49. package/knowledge_base/agents/__pycache__/intent_agent.cpython-37.pyc +0 -0
  50. package/knowledge_base/agents/__pycache__/intent_agent.cpython-38.pyc +0 -0
  51. package/knowledge_base/agents/__pycache__/kg_agent.cpython-37.pyc +0 -0
  52. package/knowledge_base/agents/__pycache__/kg_agent.cpython-38.pyc +0 -0
  53. package/knowledge_base/agents/__pycache__/memory_agent.cpython-37.pyc +0 -0
  54. package/knowledge_base/agents/__pycache__/memory_agent.cpython-38.pyc +0 -0
  55. package/knowledge_base/agents/__pycache__/rca_agent.cpython-37.pyc +0 -0
  56. package/knowledge_base/agents/__pycache__/reflection_agent.cpython-37.pyc +0 -0
  57. package/knowledge_base/agents/__pycache__/reflection_agent.cpython-38.pyc +0 -0
  58. package/knowledge_base/agents/__pycache__/regression_agent.cpython-37.pyc +0 -0
  59. package/knowledge_base/agents/__pycache__/retrieval_agent.cpython-37.pyc +0 -0
  60. package/knowledge_base/agents/__pycache__/retrieval_agent.cpython-38.pyc +0 -0
  61. package/knowledge_base/agents/__pycache__/script_agent.cpython-37.pyc +0 -0
  62. package/knowledge_base/agents/__pycache__/script_agent.cpython-38.pyc +0 -0
  63. package/knowledge_base/agents/__pycache__/state.cpython-37.pyc +0 -0
  64. package/knowledge_base/agents/__pycache__/state.cpython-38.pyc +0 -0
  65. package/knowledge_base/agents/__pycache__/temporal_agent.cpython-37.pyc +0 -0
  66. package/knowledge_base/agents/__pycache__/temporal_agent.cpython-38.pyc +0 -0
  67. package/knowledge_base/agents/__pycache__/validation_agent.cpython-37.pyc +0 -0
  68. package/knowledge_base/agents/__pycache__/validation_agent.cpython-38.pyc +0 -0
  69. package/knowledge_base/agents/automation_design_agent.py +123 -0
  70. package/knowledge_base/agents/code_intelligence_agent.py +147 -0
  71. package/knowledge_base/agents/confidence_agent.py +94 -0
  72. package/knowledge_base/agents/execution_validation_agent.py +129 -0
  73. package/knowledge_base/agents/feedback_agent.py +56 -0
  74. package/knowledge_base/agents/fusion_agent.py +113 -0
  75. package/knowledge_base/agents/graph.py +152 -0
  76. package/knowledge_base/agents/healing_agent.py +62 -0
  77. package/knowledge_base/agents/intent_agent.py +76 -0
  78. package/knowledge_base/agents/kg_agent.py +91 -0
  79. package/knowledge_base/agents/memory_agent.py +62 -0
  80. package/knowledge_base/agents/rca_agent.py +53 -0
  81. package/knowledge_base/agents/reflection_agent.py +62 -0
  82. package/knowledge_base/agents/regression_agent.py +81 -0
  83. package/knowledge_base/agents/requirement_agent.py +71 -0
  84. package/knowledge_base/agents/retrieval_agent.py +66 -0
  85. package/knowledge_base/agents/scenario_agent.py +81 -0
  86. package/knowledge_base/agents/script_agent.py +121 -0
  87. package/knowledge_base/agents/script_generator_agent.py +77 -0
  88. package/knowledge_base/agents/state.py +53 -0
  89. package/knowledge_base/agents/temporal_agent.py +48 -0
  90. package/knowledge_base/agents/testcase_agent.py +111 -0
  91. package/knowledge_base/agents/validation_agent.py +49 -0
  92. package/knowledge_base/agents/workflow_engine.py +87 -0
  93. package/knowledge_base/alembic/README.md +104 -0
  94. package/knowledge_base/alembic/__pycache__/env.cpython-37.pyc +0 -0
  95. package/knowledge_base/alembic/__pycache__/env.cpython-38.pyc +0 -0
  96. package/knowledge_base/alembic/env.py +76 -0
  97. package/knowledge_base/alembic/script.py.mako +5 -0
  98. package/knowledge_base/alembic/versions/.gitkeep +26 -0
  99. package/knowledge_base/alembic/versions/001_phase0_feedback.py +122 -0
  100. package/knowledge_base/alembic/versions/002_feedback_promotions.py +60 -0
  101. package/knowledge_base/alembic/versions/003_enterprise_hardening.py +74 -0
  102. package/knowledge_base/alembic/versions/__pycache__/001_phase0_feedback.cpython-37.pyc +0 -0
  103. package/knowledge_base/alembic/versions/__pycache__/001_phase0_feedback.cpython-38.pyc +0 -0
  104. package/knowledge_base/alembic/versions/__pycache__/002_feedback_promotions.cpython-37.pyc +0 -0
  105. package/knowledge_base/alembic/versions/__pycache__/002_feedback_promotions.cpython-38.pyc +0 -0
  106. package/knowledge_base/api/__init__.py +1 -0
  107. package/knowledge_base/api/__pycache__/__init__.cpython-37.pyc +0 -0
  108. package/knowledge_base/api/__pycache__/__init__.cpython-38.pyc +0 -0
  109. package/knowledge_base/api/__pycache__/middleware.cpython-38.pyc +0 -0
  110. package/knowledge_base/api/__pycache__/server.cpython-37.pyc +0 -0
  111. package/knowledge_base/api/__pycache__/server.cpython-38.pyc +0 -0
  112. package/knowledge_base/api/middleware.py +78 -0
  113. package/knowledge_base/api/server.py +778 -0
  114. package/knowledge_base/chunking/__init__.py +0 -0
  115. package/knowledge_base/chunking/__pycache__/__init__.cpython-37.pyc +0 -0
  116. package/knowledge_base/chunking/__pycache__/__init__.cpython-38.pyc +0 -0
  117. package/knowledge_base/chunking/__pycache__/chunker.cpython-37.pyc +0 -0
  118. package/knowledge_base/chunking/__pycache__/chunker.cpython-38.pyc +0 -0
  119. package/knowledge_base/chunking/__pycache__/validators.cpython-37.pyc +0 -0
  120. package/knowledge_base/chunking/__pycache__/validators.cpython-38.pyc +0 -0
  121. package/knowledge_base/chunking/chunker.py +402 -0
  122. package/knowledge_base/chunking/validators.py +144 -0
  123. package/knowledge_base/cli/__init__.py +1 -0
  124. package/knowledge_base/cli/__pycache__/__init__.cpython-37.pyc +0 -0
  125. package/knowledge_base/cli/__pycache__/__init__.cpython-38.pyc +0 -0
  126. package/knowledge_base/cli/__pycache__/feedback_cli.cpython-37.pyc +0 -0
  127. package/knowledge_base/cli/__pycache__/feedback_cli.cpython-38.pyc +0 -0
  128. package/knowledge_base/cli/__pycache__/generate.cpython-37.pyc +0 -0
  129. package/knowledge_base/cli/__pycache__/generate.cpython-38.pyc +0 -0
  130. package/knowledge_base/cli/__pycache__/generate_qcapps134.cpython-37.pyc +0 -0
  131. package/knowledge_base/cli/feedback_cli.py +121 -0
  132. package/knowledge_base/cli/generate.py +308 -0
  133. package/knowledge_base/cli/generate_qcapps134.py +391 -0
  134. package/knowledge_base/config/.env +100 -0
  135. package/knowledge_base/config/.env.example +75 -0
  136. package/knowledge_base/config/__init__.py +5 -0
  137. package/knowledge_base/config/__pycache__/__init__.cpython-37.pyc +0 -0
  138. package/knowledge_base/config/__pycache__/__init__.cpython-38.pyc +0 -0
  139. package/knowledge_base/config/__pycache__/settings.cpython-37.pyc +0 -0
  140. package/knowledge_base/config/__pycache__/settings.cpython-38.pyc +0 -0
  141. package/knowledge_base/config/settings.py +280 -0
  142. package/knowledge_base/connectors/__init__.py +5 -0
  143. package/knowledge_base/connectors/__pycache__/__init__.cpython-37.pyc +0 -0
  144. package/knowledge_base/connectors/__pycache__/__init__.cpython-38.pyc +0 -0
  145. package/knowledge_base/connectors/__pycache__/base.cpython-37.pyc +0 -0
  146. package/knowledge_base/connectors/__pycache__/base.cpython-38.pyc +0 -0
  147. package/knowledge_base/connectors/__pycache__/bitbucket_connector.cpython-37.pyc +0 -0
  148. package/knowledge_base/connectors/__pycache__/bitbucket_connector.cpython-38.pyc +0 -0
  149. package/knowledge_base/connectors/__pycache__/community_connector.cpython-38.pyc +0 -0
  150. package/knowledge_base/connectors/__pycache__/confluence_connector.cpython-37.pyc +0 -0
  151. package/knowledge_base/connectors/__pycache__/confluence_connector.cpython-38.pyc +0 -0
  152. package/knowledge_base/connectors/__pycache__/jira_connector.cpython-37.pyc +0 -0
  153. package/knowledge_base/connectors/__pycache__/jira_connector.cpython-38.pyc +0 -0
  154. package/knowledge_base/connectors/__pycache__/kb_igel_connector.cpython-38.pyc +0 -0
  155. package/knowledge_base/connectors/__pycache__/playwright_fetcher.cpython-38.pyc +0 -0
  156. package/knowledge_base/connectors/__pycache__/query_bridge.cpython-38.pyc +0 -0
  157. package/knowledge_base/connectors/__pycache__/search_backends.cpython-38.pyc +0 -0
  158. package/knowledge_base/connectors/__pycache__/serviceNow_connector.cpython-37.pyc +0 -0
  159. package/knowledge_base/connectors/__pycache__/serviceNow_connector.cpython-38.pyc +0 -0
  160. package/knowledge_base/connectors/__pycache__/sync_scheduler.cpython-37.pyc +0 -0
  161. package/knowledge_base/connectors/__pycache__/sync_scheduler.cpython-38.pyc +0 -0
  162. package/knowledge_base/connectors/__pycache__/teamcity_connector.cpython-37.pyc +0 -0
  163. package/knowledge_base/connectors/__pycache__/teamcity_connector.cpython-38.pyc +0 -0
  164. package/knowledge_base/connectors/__pycache__/testRail_connector.cpython-37.pyc +0 -0
  165. package/knowledge_base/connectors/__pycache__/testRail_connector.cpython-38.pyc +0 -0
  166. package/knowledge_base/connectors/__pycache__/web_fetcher.cpython-38.pyc +0 -0
  167. package/knowledge_base/connectors/base.py +44 -0
  168. package/knowledge_base/connectors/bitbucket_connector.py +25 -0
  169. package/knowledge_base/connectors/community_connector.py +112 -0
  170. package/knowledge_base/connectors/confluence_connector.py +165 -0
  171. package/knowledge_base/connectors/jira_connector.py +174 -0
  172. package/knowledge_base/connectors/kb_igel_connector.py +145 -0
  173. package/knowledge_base/connectors/playwright_fetcher.py +50 -0
  174. package/knowledge_base/connectors/query_bridge.py +170 -0
  175. package/knowledge_base/connectors/search_backends.py +368 -0
  176. package/knowledge_base/connectors/serviceNow_connector.py +25 -0
  177. package/knowledge_base/connectors/sync_scheduler.py +111 -0
  178. package/knowledge_base/connectors/teamcity_connector.py +25 -0
  179. package/knowledge_base/connectors/testRail_connector.py +25 -0
  180. package/knowledge_base/connectors/web_fetcher.py +280 -0
  181. package/knowledge_base/core/__init__.py +8 -0
  182. package/knowledge_base/core/__pycache__/__init__.cpython-37.pyc +0 -0
  183. package/knowledge_base/core/__pycache__/__init__.cpython-38.pyc +0 -0
  184. package/knowledge_base/core/__pycache__/cache.cpython-38.pyc +0 -0
  185. package/knowledge_base/core/__pycache__/circuit_breaker.cpython-38.pyc +0 -0
  186. package/knowledge_base/core/__pycache__/confidence.cpython-37.pyc +0 -0
  187. package/knowledge_base/core/__pycache__/confidence.cpython-38.pyc +0 -0
  188. package/knowledge_base/core/__pycache__/logging_setup.cpython-38.pyc +0 -0
  189. package/knowledge_base/core/__pycache__/metrics.cpython-38.pyc +0 -0
  190. package/knowledge_base/core/__pycache__/precedence.cpython-37.pyc +0 -0
  191. package/knowledge_base/core/__pycache__/precedence.cpython-38.pyc +0 -0
  192. package/knowledge_base/core/__pycache__/request_context.cpython-38.pyc +0 -0
  193. package/knowledge_base/core/cache.py +98 -0
  194. package/knowledge_base/core/circuit_breaker.py +33 -0
  195. package/knowledge_base/core/confidence.py +254 -0
  196. package/knowledge_base/core/logging_setup.py +39 -0
  197. package/knowledge_base/core/metrics.py +63 -0
  198. package/knowledge_base/core/precedence.py +354 -0
  199. package/knowledge_base/core/request_context.py +54 -0
  200. package/knowledge_base/db/__init__.py +0 -0
  201. package/knowledge_base/db/__pycache__/__init__.cpython-314.pyc +0 -0
  202. package/knowledge_base/db/__pycache__/__init__.cpython-37.pyc +0 -0
  203. package/knowledge_base/db/__pycache__/__init__.cpython-38.pyc +0 -0
  204. package/knowledge_base/db/__pycache__/client.cpython-314.pyc +0 -0
  205. package/knowledge_base/db/__pycache__/client.cpython-37.pyc +0 -0
  206. package/knowledge_base/db/__pycache__/client.cpython-38.pyc +0 -0
  207. package/knowledge_base/db/__pycache__/connector_sync.cpython-38.pyc +0 -0
  208. package/knowledge_base/db/__pycache__/feedback_schema.cpython-37.pyc +0 -0
  209. package/knowledge_base/db/__pycache__/feedback_schema.cpython-38.pyc +0 -0
  210. package/knowledge_base/db/__pycache__/kg_introspect.cpython-314.pyc +0 -0
  211. package/knowledge_base/db/__pycache__/kg_introspect.cpython-37.pyc +0 -0
  212. package/knowledge_base/db/__pycache__/kg_introspect.cpython-38.pyc +0 -0
  213. package/knowledge_base/db/__pycache__/schema.cpython-37.pyc +0 -0
  214. package/knowledge_base/db/__pycache__/schema.cpython-38.pyc +0 -0
  215. package/knowledge_base/db/client.py +100 -0
  216. package/knowledge_base/db/connector_sync.py +43 -0
  217. package/knowledge_base/db/feedback_schema.py +548 -0
  218. package/knowledge_base/db/igel_schema.py +150 -0
  219. package/knowledge_base/db/kg_introspect.py +116 -0
  220. package/knowledge_base/db/migrations.py +22 -0
  221. package/knowledge_base/db/schema.py +649 -0
  222. package/knowledge_base/deploy/Dockerfile +23 -0
  223. package/knowledge_base/deploy/feedback_automation.sh +18 -0
  224. package/knowledge_base/deploy/firecrawl-docker.sh +50 -0
  225. package/knowledge_base/deploy/igel-testgen.service +26 -0
  226. package/knowledge_base/deploy/install_reranker.sh +92 -0
  227. package/knowledge_base/deploy/requirements.txt +68 -0
  228. package/knowledge_base/deploy/run_server.sh +35 -0
  229. package/knowledge_base/docs/TEST_GENERATION_GUIDE.md +174 -0
  230. package/knowledge_base/embeddings/__init__.py +0 -0
  231. package/knowledge_base/embeddings/__pycache__/__init__.cpython-314.pyc +0 -0
  232. package/knowledge_base/embeddings/__pycache__/__init__.cpython-37.pyc +0 -0
  233. package/knowledge_base/embeddings/__pycache__/__init__.cpython-38.pyc +0 -0
  234. package/knowledge_base/embeddings/__pycache__/azure_embedder.cpython-314.pyc +0 -0
  235. package/knowledge_base/embeddings/__pycache__/azure_embedder.cpython-37.pyc +0 -0
  236. package/knowledge_base/embeddings/__pycache__/azure_embedder.cpython-38.pyc +0 -0
  237. package/knowledge_base/embeddings/azure_embedder.py +99 -0
  238. package/knowledge_base/eval/__init__.py +33 -0
  239. package/knowledge_base/eval/__main__.py +172 -0
  240. package/knowledge_base/eval/__pycache__/__init__.cpython-37.pyc +0 -0
  241. package/knowledge_base/eval/__pycache__/__init__.cpython-38.pyc +0 -0
  242. package/knowledge_base/eval/__pycache__/__main__.cpython-37.pyc +0 -0
  243. package/knowledge_base/eval/__pycache__/baseline.cpython-37.pyc +0 -0
  244. package/knowledge_base/eval/__pycache__/baseline.cpython-38.pyc +0 -0
  245. package/knowledge_base/eval/__pycache__/harness.cpython-37.pyc +0 -0
  246. package/knowledge_base/eval/__pycache__/harness.cpython-38.pyc +0 -0
  247. package/knowledge_base/eval/__pycache__/scorers.cpython-37.pyc +0 -0
  248. package/knowledge_base/eval/__pycache__/scorers.cpython-38.pyc +0 -0
  249. package/knowledge_base/eval/baseline.py +213 -0
  250. package/knowledge_base/eval/harness.py +400 -0
  251. package/knowledge_base/eval/queries_50.json +302 -0
  252. package/knowledge_base/eval/scorers.py +494 -0
  253. package/knowledge_base/exemplars/README.md +7 -0
  254. package/knowledge_base/exemplars/__pycache__/pytest_reference_snippet.cpython-37.pyc +0 -0
  255. package/knowledge_base/exemplars/gold_manual_concise_snippet.md +8 -0
  256. package/knowledge_base/exemplars/gold_manual_detailed_snippet.md +7 -0
  257. package/knowledge_base/exemplars/pytest_reference_snippet.py +37 -0
  258. package/knowledge_base/feedback/__init__.py +10 -0
  259. package/knowledge_base/feedback/__pycache__/__init__.cpython-37.pyc +0 -0
  260. package/knowledge_base/feedback/__pycache__/__init__.cpython-38.pyc +0 -0
  261. package/knowledge_base/feedback/__pycache__/analytics.cpython-37.pyc +0 -0
  262. package/knowledge_base/feedback/__pycache__/analytics.cpython-38.pyc +0 -0
  263. package/knowledge_base/feedback/__pycache__/applier.cpython-37.pyc +0 -0
  264. package/knowledge_base/feedback/__pycache__/applier.cpython-38.pyc +0 -0
  265. package/knowledge_base/feedback/__pycache__/curator.cpython-37.pyc +0 -0
  266. package/knowledge_base/feedback/__pycache__/curator.cpython-38.pyc +0 -0
  267. package/knowledge_base/feedback/__pycache__/handler.cpython-37.pyc +0 -0
  268. package/knowledge_base/feedback/__pycache__/handler.cpython-38.pyc +0 -0
  269. package/knowledge_base/feedback/analytics.py +72 -0
  270. package/knowledge_base/feedback/applier.py +93 -0
  271. package/knowledge_base/feedback/curator.py +49 -0
  272. package/knowledge_base/feedback/handler.py +151 -0
  273. package/knowledge_base/generation/__init__.py +5 -0
  274. package/knowledge_base/generation/__pycache__/__init__.cpython-37.pyc +0 -0
  275. package/knowledge_base/generation/__pycache__/__init__.cpython-38.pyc +0 -0
  276. package/knowledge_base/generation/__pycache__/input_classifier.cpython-37.pyc +0 -0
  277. package/knowledge_base/generation/__pycache__/input_classifier.cpython-38.pyc +0 -0
  278. package/knowledge_base/generation/__pycache__/manual_tc_parser.cpython-37.pyc +0 -0
  279. package/knowledge_base/generation/__pycache__/manual_tc_parser.cpython-38.pyc +0 -0
  280. package/knowledge_base/generation/__pycache__/prompts.cpython-37.pyc +0 -0
  281. package/knowledge_base/generation/__pycache__/prompts.cpython-38.pyc +0 -0
  282. package/knowledge_base/generation/__pycache__/tc_transformer.cpython-37.pyc +0 -0
  283. package/knowledge_base/generation/__pycache__/test_generator.cpython-37.pyc +0 -0
  284. package/knowledge_base/generation/__pycache__/test_generator.cpython-38.pyc +0 -0
  285. package/knowledge_base/generation/input_classifier.py +148 -0
  286. package/knowledge_base/generation/manual_tc_parser.py +180 -0
  287. package/knowledge_base/generation/prompts.py +755 -0
  288. package/knowledge_base/generation/tc_transformer.py +368 -0
  289. package/knowledge_base/generation/test_generator.py +553 -0
  290. package/knowledge_base/graph_db/__init__.py +5 -0
  291. package/knowledge_base/graph_db/__pycache__/__init__.cpython-37.pyc +0 -0
  292. package/knowledge_base/graph_db/__pycache__/__init__.cpython-38.pyc +0 -0
  293. package/knowledge_base/graph_db/__pycache__/graphiti_client.cpython-37.pyc +0 -0
  294. package/knowledge_base/graph_db/__pycache__/kg_traversal.cpython-37.pyc +0 -0
  295. package/knowledge_base/graph_db/__pycache__/migrate_kg.cpython-37.pyc +0 -0
  296. package/knowledge_base/graph_db/__pycache__/neo4j_client.cpython-37.pyc +0 -0
  297. package/knowledge_base/graph_db/__pycache__/neo4j_client.cpython-38.pyc +0 -0
  298. package/knowledge_base/graph_db/__pycache__/schema.cpython-37.pyc +0 -0
  299. package/knowledge_base/graph_db/__pycache__/temporal_ingest.cpython-37.pyc +0 -0
  300. package/knowledge_base/graph_db/graphiti_client.py +127 -0
  301. package/knowledge_base/graph_db/kg_traversal.py +192 -0
  302. package/knowledge_base/graph_db/migrate_kg.py +93 -0
  303. package/knowledge_base/graph_db/neo4j_client.py +116 -0
  304. package/knowledge_base/graph_db/schema.py +22 -0
  305. package/knowledge_base/graph_db/temporal_ingest.py +59 -0
  306. package/knowledge_base/ingestion/__init__.py +1 -0
  307. package/knowledge_base/ingestion/__pycache__/__init__.cpython-37.pyc +0 -0
  308. package/knowledge_base/ingestion/__pycache__/__init__.cpython-38.pyc +0 -0
  309. package/knowledge_base/ingestion/__pycache__/ingest.cpython-37.pyc +0 -0
  310. package/knowledge_base/ingestion/__pycache__/ingest.cpython-38.pyc +0 -0
  311. package/knowledge_base/ingestion/__pycache__/ingest_images.cpython-37.pyc +0 -0
  312. package/knowledge_base/ingestion/__pycache__/ingest_images.cpython-38.pyc +0 -0
  313. package/knowledge_base/ingestion/__pycache__/kg_extractor.cpython-37.pyc +0 -0
  314. package/knowledge_base/ingestion/__pycache__/kg_extractor.cpython-38.pyc +0 -0
  315. package/knowledge_base/ingestion/__pycache__/web_ingest.cpython-38.pyc +0 -0
  316. package/knowledge_base/ingestion/ingest.py +346 -0
  317. package/knowledge_base/ingestion/ingest_images.py +330 -0
  318. package/knowledge_base/ingestion/kg_extractor.py +358 -0
  319. package/knowledge_base/ingestion/web_ingest.py +83 -0
  320. package/knowledge_base/intelligence/__init__.py +1 -0
  321. package/knowledge_base/intelligence/__pycache__/__init__.cpython-37.pyc +0 -0
  322. package/knowledge_base/intelligence/__pycache__/execution_ingest.cpython-37.pyc +0 -0
  323. package/knowledge_base/intelligence/__pycache__/predictive_engine.cpython-37.pyc +0 -0
  324. package/knowledge_base/intelligence/__pycache__/risk_scorer.cpython-37.pyc +0 -0
  325. package/knowledge_base/intelligence/execution_ingest.py +34 -0
  326. package/knowledge_base/intelligence/predictive_engine.py +7 -0
  327. package/knowledge_base/intelligence/risk_scorer.py +8 -0
  328. package/knowledge_base/memory/__init__.py +6 -0
  329. package/knowledge_base/memory/__pycache__/__init__.cpython-37.pyc +0 -0
  330. package/knowledge_base/memory/__pycache__/__init__.cpython-38.pyc +0 -0
  331. package/knowledge_base/memory/__pycache__/cognee_client.cpython-37.pyc +0 -0
  332. package/knowledge_base/memory/__pycache__/cognee_client.cpython-38.pyc +0 -0
  333. package/knowledge_base/memory/__pycache__/ingest_memory.cpython-37.pyc +0 -0
  334. package/knowledge_base/memory/__pycache__/memory_types.cpython-37.pyc +0 -0
  335. package/knowledge_base/memory/__pycache__/memory_types.cpython-38.pyc +0 -0
  336. package/knowledge_base/memory/cognee_client.py +164 -0
  337. package/knowledge_base/memory/ingest_memory.py +60 -0
  338. package/knowledge_base/memory/memory_types.py +23 -0
  339. package/knowledge_base/models/test_requirement.py +84 -0
  340. package/knowledge_base/parsers/__init__.py +0 -0
  341. package/knowledge_base/parsers/__pycache__/__init__.cpython-37.pyc +0 -0
  342. package/knowledge_base/parsers/__pycache__/__init__.cpython-38.pyc +0 -0
  343. package/knowledge_base/parsers/__pycache__/csv_parser.cpython-37.pyc +0 -0
  344. package/knowledge_base/parsers/__pycache__/csv_parser.cpython-38.pyc +0 -0
  345. package/knowledge_base/parsers/__pycache__/doc_parser.cpython-37.pyc +0 -0
  346. package/knowledge_base/parsers/__pycache__/doc_parser.cpython-38.pyc +0 -0
  347. package/knowledge_base/parsers/__pycache__/html_parser.cpython-38.pyc +0 -0
  348. package/knowledge_base/parsers/__pycache__/image_extractor.cpython-37.pyc +0 -0
  349. package/knowledge_base/parsers/__pycache__/image_extractor.cpython-38.pyc +0 -0
  350. package/knowledge_base/parsers/__pycache__/markdown_parser.cpython-37.pyc +0 -0
  351. package/knowledge_base/parsers/__pycache__/markdown_parser.cpython-38.pyc +0 -0
  352. package/knowledge_base/parsers/__pycache__/pdf_parser.cpython-37.pyc +0 -0
  353. package/knowledge_base/parsers/__pycache__/pdf_parser.cpython-38.pyc +0 -0
  354. package/knowledge_base/parsers/csv_parser.py +126 -0
  355. package/knowledge_base/parsers/doc_parser.py +176 -0
  356. package/knowledge_base/parsers/html_parser.py +151 -0
  357. package/knowledge_base/parsers/image_extractor.py +370 -0
  358. package/knowledge_base/parsers/markdown_parser.py +116 -0
  359. package/knowledge_base/parsers/pdf_parser.py +178 -0
  360. package/knowledge_base/retrieval/__init__.py +1 -0
  361. package/knowledge_base/retrieval/__pycache__/__init__.cpython-37.pyc +0 -0
  362. package/knowledge_base/retrieval/__pycache__/__init__.cpython-38.pyc +0 -0
  363. package/knowledge_base/retrieval/__pycache__/context_fusion.cpython-37.pyc +0 -0
  364. package/knowledge_base/retrieval/__pycache__/context_fusion.cpython-38.pyc +0 -0
  365. package/knowledge_base/retrieval/__pycache__/knowledge_graph.cpython-37.pyc +0 -0
  366. package/knowledge_base/retrieval/__pycache__/knowledge_graph.cpython-38.pyc +0 -0
  367. package/knowledge_base/retrieval/__pycache__/reranker.cpython-37.pyc +0 -0
  368. package/knowledge_base/retrieval/__pycache__/reranker.cpython-38.pyc +0 -0
  369. package/knowledge_base/retrieval/__pycache__/retrieval_debug.cpython-37.pyc +0 -0
  370. package/knowledge_base/retrieval/__pycache__/retrieval_debug.cpython-38.pyc +0 -0
  371. package/knowledge_base/retrieval/__pycache__/retriever.cpython-37.pyc +0 -0
  372. package/knowledge_base/retrieval/__pycache__/retriever.cpython-38.pyc +0 -0
  373. package/knowledge_base/retrieval/__pycache__/unified_query.cpython-38.pyc +0 -0
  374. package/knowledge_base/retrieval/__pycache__/web_retriever.cpython-38.pyc +0 -0
  375. package/knowledge_base/retrieval/context_fusion.py +264 -0
  376. package/knowledge_base/retrieval/knowledge_graph.py +267 -0
  377. package/knowledge_base/retrieval/reranker.py +308 -0
  378. package/knowledge_base/retrieval/retrieval_debug.py +69 -0
  379. package/knowledge_base/retrieval/retriever.py +885 -0
  380. package/knowledge_base/retrieval/unified_query.py +189 -0
  381. package/knowledge_base/retrieval/web_retriever.py +337 -0
  382. package/knowledge_base/validators/__init__.py +1 -0
  383. package/knowledge_base/validators/__pycache__/__init__.cpython-314.pyc +0 -0
  384. package/knowledge_base/validators/__pycache__/__init__.cpython-37.pyc +0 -0
  385. package/knowledge_base/validators/__pycache__/step_fidelity.cpython-314.pyc +0 -0
  386. package/knowledge_base/validators/__pycache__/step_fidelity.cpython-37.pyc +0 -0
  387. package/knowledge_base/validators/step_fidelity.py +88 -0
  388. package/knowledge_base/vision/__init__.py +0 -0
  389. package/knowledge_base/vision/__pycache__/__init__.cpython-37.pyc +0 -0
  390. package/knowledge_base/vision/__pycache__/__init__.cpython-38.pyc +0 -0
  391. package/knowledge_base/vision/__pycache__/image_describer.cpython-37.pyc +0 -0
  392. package/knowledge_base/vision/__pycache__/image_describer.cpython-38.pyc +0 -0
  393. package/knowledge_base/vision/image_describer.py +202 -0
  394. package/package.json +31 -0
@@ -0,0 +1,94 @@
1
+ import logging
2
+ from knowledge_base.models.test_requirement import (
3
+ GeneratedTestCase,
4
+ ScenarioWithRules,
5
+ ConfidenceMetrics,
6
+ TestCaseWithConfidence
7
+ )
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+ def evaluate_coverage(tc: GeneratedTestCase, scenario: ScenarioWithRules) -> float:
12
+ """Calculate if the test cases cover the business rules.
13
+ If we are evaluating a single TC, we see if it represents its rule properly.
14
+ Here we return 1.0 if it maps to a rule, 0.0 otherwise.
15
+ """
16
+ if any(r.description == tc.business_rule.description for r in scenario.business_rules):
17
+ return 1.0
18
+ return 0.0
19
+
20
+ def evaluate_traceability(tc: GeneratedTestCase) -> float:
21
+ """Check if the test case is traceable to a specific step."""
22
+ return 1.0 if "S" in tc.tc_reference and tc.business_rule else 0.0
23
+
24
+ def evaluate_completeness(tc: GeneratedTestCase) -> float:
25
+ """Evaluate completeness of steps, data, and expected results."""
26
+ if not tc.steps:
27
+ return 0.0
28
+
29
+ score = 0.0
30
+ for step in tc.steps:
31
+ step_score = 0.0
32
+ if step.action: step_score += 0.4
33
+ if step.data: step_score += 0.2
34
+ if step.expected_result: step_score += 0.4
35
+ score += step_score
36
+
37
+ return score / len(tc.steps)
38
+
39
+ def evaluate_automation_feasibility(tc: GeneratedTestCase) -> float:
40
+ """
41
+ Evaluate if this test case can be automated based on the Asset Registry.
42
+ For now, return a placeholder high score unless we have specific constraints.
43
+ (This will be enhanced when the Code Intelligence Agent is fully integrated).
44
+ """
45
+ return 0.9
46
+
47
+ def compute_hybrid_confidence(tc: GeneratedTestCase, scenario: ScenarioWithRules) -> TestCaseWithConfidence:
48
+ """
49
+ Compute the deterministic hybrid confidence score.
50
+ Weights:
51
+ - Coverage: 25%
52
+ - Traceability: 20%
53
+ - Completeness: 20%
54
+ - Historical Similarity: 15% (Stubbed to 0.8 for now)
55
+ - Automation Feasibility: 20%
56
+ """
57
+ coverage = evaluate_coverage(tc, scenario)
58
+ traceability = evaluate_traceability(tc)
59
+ completeness = evaluate_completeness(tc)
60
+ historical_similarity = 0.8 # Placeholder for vector DB search against approved tests
61
+ automation_feasibility = evaluate_automation_feasibility(tc)
62
+
63
+ total = (
64
+ coverage * 0.25 +
65
+ traceability * 0.20 +
66
+ completeness * 0.20 +
67
+ historical_similarity * 0.15 +
68
+ automation_feasibility * 0.20
69
+ )
70
+
71
+ metrics = ConfidenceMetrics(
72
+ coverage_score=coverage,
73
+ traceability_score=traceability,
74
+ completeness_score=completeness,
75
+ historical_similarity_score=historical_similarity,
76
+ automation_feasibility_score=automation_feasibility,
77
+ total_score=total
78
+ )
79
+
80
+ tc.confidence_score = total
81
+ tc.confidence_metrics = metrics.dict()
82
+
83
+ is_approved = total >= 0.80
84
+
85
+ if not is_approved:
86
+ logger.info(f"Test case {tc.tc_reference} needs review (score: {total:.2f})")
87
+ else:
88
+ logger.info(f"Test case {tc.tc_reference} auto-approved (score: {total:.2f})")
89
+
90
+ return TestCaseWithConfidence(
91
+ test_case=tc,
92
+ confidence=metrics,
93
+ is_approved=is_approved
94
+ )
@@ -0,0 +1,129 @@
1
+ import ast
2
+ import logging
3
+ import subprocess
4
+ from pathlib import Path
5
+ from typing import Tuple, List, Set
6
+
7
+ from knowledge_base.db.client import get_conn
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+ class ExecutionValidationAgent:
12
+ """Multi-stage validation pipeline for generated automation scripts."""
13
+
14
+ def __init__(self, repo_path: Path):
15
+ self.repo_path = repo_path
16
+
17
+ def validate_syntax(self, code: str) -> Tuple[bool, str]:
18
+ """Stage 1: Check Python syntax."""
19
+ try:
20
+ ast.parse(code)
21
+ return True, ""
22
+ except SyntaxError as e:
23
+ return False, f"SyntaxError at line {e.lineno}: {e.msg}"
24
+
25
+ def _get_known_assets(self, asset_type: str) -> Set[str]:
26
+ """Fetch all known assets of a specific type from the Asset Registry."""
27
+ assets = set()
28
+ try:
29
+ with get_conn() as conn:
30
+ with conn.cursor() as cur:
31
+ cur.execute("SELECT name FROM igel_asset_registry WHERE asset_type = %s", (asset_type,))
32
+ for row in cur.fetchall():
33
+ assets.add(row[0])
34
+ except Exception as e:
35
+ logger.error(f"Failed to query registry for {asset_type}: {e}")
36
+ return assets
37
+
38
+ def validate_imports(self, code: str) -> Tuple[bool, str]:
39
+ """Stage 2: Check if imported modules exist in the registry."""
40
+ try:
41
+ tree = ast.parse(code)
42
+ except SyntaxError:
43
+ return False, "Syntax invalid, cannot check imports."
44
+
45
+ # For simplicity, we just extract 'from module import X' and check X
46
+ # A more robust check would analyze the actual repo path.
47
+ missing_imports = []
48
+ known_pos = self._get_known_assets("page_object")
49
+ known_utils = self._get_known_assets("utility")
50
+ known_clients = self._get_known_assets("api_client")
51
+
52
+ all_known = known_pos | known_utils | known_clients
53
+
54
+ for node in ast.walk(tree):
55
+ if isinstance(node, ast.ImportFrom):
56
+ for name in node.names:
57
+ # Ignore standard library and common 3rd party (pytest, allure, typing, etc.)
58
+ if node.module and not any(node.module.startswith(p) for p in ["pytest", "allure", "typing", "selenium", "playwright", "os", "json", "time"]):
59
+ # This is a naive check; in a real enterprise system, you'd match the import path to `file_path`
60
+ pass
61
+ return True, ""
62
+
63
+ def validate_fixtures(self, code: str) -> Tuple[bool, str]:
64
+ """Stage 3: Check if requested pytest fixtures exist."""
65
+ try:
66
+ tree = ast.parse(code)
67
+ except SyntaxError:
68
+ return False, "Syntax invalid, cannot check fixtures."
69
+
70
+ known_fixtures = self._get_known_assets("fixture")
71
+
72
+ missing = []
73
+ for node in ast.walk(tree):
74
+ if isinstance(node, ast.FunctionDef) and node.name.startswith("test_"):
75
+ # pytest uses argument names to request fixtures
76
+ for arg in node.args.args:
77
+ arg_name = arg.arg
78
+ # Ignore common built-in fixtures
79
+ if arg_name not in ["request", "monkeypatch", "capsys", "tmpdir", "self", "cls"]:
80
+ if known_fixtures and arg_name not in known_fixtures:
81
+ missing.append(f"Fixture '{arg_name}' requested by {node.name} not found in registry.")
82
+
83
+ if missing:
84
+ return False, "\n".join(missing)
85
+ return True, ""
86
+
87
+ def validate_pytest_collection(self, file_path: Path) -> Tuple[bool, str]:
88
+ """Stage 4: Perform a pytest dry-run (collection only)."""
89
+ if not file_path.exists():
90
+ return False, f"File {file_path} does not exist."
91
+
92
+ # Run pytest --collect-only
93
+ try:
94
+ # Note: Requires pytest to be installed in the environment running the server
95
+ result = subprocess.run(
96
+ ["pytest", "--collect-only", str(file_path)],
97
+ capture_output=True,
98
+ text=True,
99
+ cwd=str(self.repo_path)
100
+ )
101
+
102
+ if result.returncode != 0:
103
+ # 5 means no tests collected, which is also an error for us
104
+ if result.returncode == 5:
105
+ return False, "Pytest collected 0 tests."
106
+ return False, f"Pytest collection failed:\n{result.stderr or result.stdout}"
107
+
108
+ return True, ""
109
+ except Exception as e:
110
+ return False, f"Error running pytest collection: {e}"
111
+
112
+ def validate_pipeline(self, code: str, file_path: Path) -> Tuple[bool, str, str]:
113
+ """Run all execution validation stages."""
114
+ logger.info(f"Starting execution validation pipeline for {file_path}")
115
+
116
+ ok, err = self.validate_syntax(code)
117
+ if not ok: return False, "syntax_failed", err
118
+
119
+ ok, err = self.validate_imports(code)
120
+ if not ok: return False, "import_failed", err
121
+
122
+ ok, err = self.validate_fixtures(code)
123
+ if not ok: return False, "fixture_failed", err
124
+
125
+ ok, err = self.validate_pytest_collection(file_path)
126
+ if not ok: return False, "collection_failed", err
127
+
128
+ logger.info(f"Execution validation passed for {file_path}")
129
+ return True, "passed", ""
@@ -0,0 +1,56 @@
1
+ import json
2
+ import logging
3
+ from typing import Dict, Any, Optional
4
+ from knowledge_base.db.client import get_conn
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+ class FeedbackAgent:
9
+ """Agent responsible for capturing and applying 4-level granular feedback."""
10
+
11
+ def capture_feedback(self, level: str, target_id: str, feedback_type: str, user_comment: str, corrected_data: Optional[Dict] = None) -> bool:
12
+ """
13
+ Store granular feedback.
14
+ Level must be one of: 'requirement', 'scenario', 'testcase', 'teststep'.
15
+ """
16
+ if level not in ["requirement", "scenario", "testcase", "teststep"]:
17
+ logger.error(f"Invalid feedback level: {level}")
18
+ return False
19
+
20
+ try:
21
+ with get_conn() as conn:
22
+ with conn.cursor() as cur:
23
+ cur.execute(
24
+ """
25
+ INSERT INTO igel_granular_feedback
26
+ (level, target_id, feedback_type, user_comment, corrected_data)
27
+ VALUES (%s, %s, %s, %s, %s::jsonb)
28
+ """,
29
+ (level, target_id, feedback_type, user_comment, json.dumps(corrected_data) if corrected_data else None)
30
+ )
31
+ conn.commit()
32
+ logger.info(f"Captured {level} feedback for {target_id}")
33
+ return True
34
+ except Exception as e:
35
+ logger.error(f"Failed to capture feedback: {e}")
36
+ return False
37
+
38
+ def get_feedback_for_target(self, target_id: str) -> list:
39
+ """Retrieve historical feedback for a specific target to use as generation context."""
40
+ feedback = []
41
+ try:
42
+ with get_conn() as conn:
43
+ with conn.cursor() as cur:
44
+ cur.execute(
45
+ "SELECT feedback_type, user_comment, corrected_data FROM igel_granular_feedback WHERE target_id = %s",
46
+ (target_id,)
47
+ )
48
+ for row in cur.fetchall():
49
+ feedback.append({
50
+ "type": row[0],
51
+ "comment": row[1],
52
+ "corrected_data": row[2]
53
+ })
54
+ except Exception as e:
55
+ logger.error(f"Failed to get feedback: {e}")
56
+ return feedback
@@ -0,0 +1,113 @@
1
+ """Context fusion agent — Phase 5."""
2
+ from __future__ import annotations
3
+
4
+ import re
5
+
6
+ from knowledge_base.agents.state import AgenticState
7
+
8
+
9
+ def fusion_agent(state: AgenticState) -> AgenticState:
10
+ rag = state.get("rag_chunks", [])
11
+ kg = state.get("kg_entities") or {}
12
+ temporal = state.get("temporal_context") or {}
13
+ memory = state.get("memory_context") or []
14
+ web = state.get("web_context") or {}
15
+ mcp = state.get("mcp_context") or {}
16
+
17
+ registry_keys = list(kg.get("registry_keys") or [])
18
+ ui_paths = list(kg.get("ui_paths") or [])
19
+ procedure_steps = []
20
+ for chunk in rag[:5]:
21
+ content = chunk.get("content", "")
22
+ for line in content.split("\n"):
23
+ if re.match(r"^\s*\d+[\.)]\s", line):
24
+ procedure_steps.append(line.strip())
25
+
26
+ memory_insights = [m.get("content", "") for m in memory if m.get("content")]
27
+ temporal_changes = temporal.get("feature_changes") or []
28
+
29
+ conflicts: list[dict] = list(kg.get("conflicts") or [])
30
+ if not conflicts and rag:
31
+ try:
32
+ from knowledge_base.core.precedence import detect_precedence_conflicts
33
+ pseudo = []
34
+ for i, chunk in enumerate(rag[:8]):
35
+ pseudo.append(type("R", (), {
36
+ "metadata": {"source_type": chunk.get("source_type", "igel_docs")},
37
+ "parent_content": chunk.get("content", ""),
38
+ "file_name": chunk.get("source_name", ""),
39
+ })())
40
+ conflicts = detect_precedence_conflicts(pseudo)
41
+ except Exception:
42
+ pass
43
+ missing: list[str] = []
44
+ if not registry_keys and "configuration" in state.get("query_categories", []):
45
+ missing.append("no_registry_keys")
46
+ if not ui_paths:
47
+ missing.append("no_ui_paths")
48
+ if len(procedure_steps) < 3:
49
+ missing.append("no_procedure_steps")
50
+
51
+ sources_used = []
52
+ for chunk in rag:
53
+ src = chunk.get("source_name") or chunk.get("source_type", "unknown")
54
+ sources_used.append(src)
55
+ for hit in web.get("hits") or []:
56
+ sources_used.append(hit.get("url") or hit.get("title") or "web")
57
+ for hit in mcp.get("hits") or []:
58
+ sources_used.append(f"{hit.get('source', 'mcp')}:{hit.get('title', 'external')}")
59
+
60
+ web_boost = min(0.15, len(web.get("hits") or []) * 0.05)
61
+ mcp_boost = min(0.1, len(mcp.get("hits") or []) * 0.05)
62
+ quality = min(
63
+ 1.0,
64
+ (len(rag) / 5) * 0.35
65
+ + (len(registry_keys) / 5) * 0.25
66
+ + (len(procedure_steps) / 5) * 0.25
67
+ + web_boost
68
+ + mcp_boost,
69
+ )
70
+
71
+ # LLM-assisted context quality when heuristic score is low
72
+ if quality < 0.5 and rag:
73
+ try:
74
+ from knowledge_base.generation.test_generator import _call_gpt
75
+ sample = "\n".join(c.get("content", "")[:200] for c in rag[:3])
76
+ verdict = _call_gpt(
77
+ "Rate context relevance 0-1 for IGEL test generation. Reply with number only.",
78
+ f"Query: {state.get('query', '')}\nContext sample:\n{sample}",
79
+ max_tokens=16,
80
+ temperature=0.0,
81
+ )
82
+ import re
83
+ m = re.search(r"0\.\d+|1\.0|1", verdict)
84
+ if m:
85
+ quality = max(quality, min(1.0, float(m.group())))
86
+ except Exception:
87
+ pass
88
+
89
+ state["fused_context"] = {
90
+ "registry_keys": registry_keys,
91
+ "ui_paths": ui_paths,
92
+ "procedure_steps": procedure_steps[:20],
93
+ "related_tcs": kg.get("related_testcases") or [],
94
+ "related_defects": kg.get("related_defects") or [],
95
+ "memory_insights": memory_insights,
96
+ "temporal_changes": temporal_changes,
97
+ "web_block": web.get("block") or "",
98
+ "web_hits": web.get("hits") or [],
99
+ "mcp_block": mcp.get("block") or "",
100
+ "mcp_hits": mcp.get("hits") or [],
101
+ "conflicts": conflicts,
102
+ "context_quality": quality,
103
+ "missing_signals": missing,
104
+ }
105
+ state["sources_used"] = list(dict.fromkeys(sources_used))
106
+
107
+ state.setdefault("agent_trace", []).append({
108
+ "agent": "FusionAgent",
109
+ "status": "complete",
110
+ "context_quality": quality,
111
+ "conflicts": len(conflicts),
112
+ })
113
+ return state
@@ -0,0 +1,152 @@
1
+ """Agent orchestration graph — Phase 5 (LangGraph with parallel retrieval)."""
2
+ from __future__ import annotations
3
+
4
+ import logging
5
+ import time
6
+ from concurrent.futures import ThreadPoolExecutor, as_completed
7
+
8
+ from knowledge_base.agents.fusion_agent import fusion_agent
9
+ from knowledge_base.agents.intent_agent import intent_agent
10
+ from knowledge_base.agents.kg_agent import kg_agent
11
+ from knowledge_base.agents.memory_agent import memory_agent
12
+ from knowledge_base.agents.reflection_agent import reflection_agent, should_loop_back
13
+ from knowledge_base.agents.retrieval_agent import retrieval_agent
14
+ from knowledge_base.agents.script_agent import script_agent
15
+ from knowledge_base.agents.state import AgenticState, initial_state
16
+ from knowledge_base.agents.temporal_agent import temporal_agent
17
+ from knowledge_base.agents.validation_agent import validation_agent
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ def _run_agent(name: str, fn, state: AgenticState) -> AgenticState:
23
+ t0 = time.perf_counter()
24
+ result = fn(state)
25
+ result.setdefault("agent_trace", []).append({
26
+ "agent": name,
27
+ "status": "parallel_complete",
28
+ "timing_ms": round((time.perf_counter() - t0) * 1000, 1),
29
+ })
30
+ return result
31
+
32
+
33
+ def _merge_parallel_results(base: AgenticState, partial: AgenticState) -> None:
34
+ for key in (
35
+ "rag_chunks", "web_context", "mcp_context", "sources_summary",
36
+ "kg_context_block", "kg_entities", "temporal_context", "memory_context",
37
+ ):
38
+ if key in partial and partial[key]:
39
+ base[key] = partial[key]
40
+ base.setdefault("agent_trace", []).extend(partial.get("agent_trace", []))
41
+
42
+
43
+ def _run_parallel_retrieval(state: AgenticState) -> AgenticState:
44
+ """Run retrieval first, then KG/temporal/memory in parallel."""
45
+ state = retrieval_agent(state)
46
+ base = dict(state)
47
+ agents = [
48
+ ("KGAgent", kg_agent),
49
+ ("TemporalAgent", temporal_agent),
50
+ ("MemoryAgent", memory_agent),
51
+ ]
52
+ with ThreadPoolExecutor(max_workers=3) as pool:
53
+ futures = {pool.submit(fn, dict(base)): name for name, fn in agents}
54
+ for fut in as_completed(futures):
55
+ try:
56
+ partial = fut.result()
57
+ _merge_parallel_results(state, partial)
58
+ except Exception as exc:
59
+ logger.warning("Parallel agent %s failed: %s", futures[fut], exc)
60
+ return state
61
+
62
+
63
+ def run_agentic_pipeline(state: AgenticState) -> AgenticState:
64
+ """Execute full agent pipeline without LangGraph dependency."""
65
+ state = intent_agent(state)
66
+ state = _run_parallel_retrieval(state)
67
+ state = fusion_agent(state)
68
+
69
+ for _ in range(2):
70
+ state = reflection_agent(state)
71
+ if should_loop_back(state):
72
+ state = _run_parallel_retrieval(state)
73
+ state = fusion_agent(state)
74
+ else:
75
+ break
76
+
77
+ state = validation_agent(state)
78
+ if not state.get("validation_passed", True) and len(state.get("validation_errors") or []) > 2:
79
+ conf = state.setdefault("confidence", {})
80
+ conf["publish"] = min(float(conf.get("publish", 0.5)), 0.35)
81
+ conf["route"] = "reject"
82
+ state = script_agent(state)
83
+ return state
84
+
85
+
86
+ def build_graph():
87
+ """
88
+ Build LangGraph workflow when langgraph is installed; else return callable runner.
89
+ """
90
+ try:
91
+ from langgraph.graph import END, StateGraph
92
+
93
+ workflow = StateGraph(AgenticState)
94
+
95
+ workflow.add_node("intent", intent_agent)
96
+ workflow.add_node("retrieval_parallel", _run_parallel_retrieval)
97
+ workflow.add_node("fusion", fusion_agent)
98
+ workflow.add_node("reflection", reflection_agent)
99
+ workflow.add_node("validation", validation_agent)
100
+ workflow.add_node("script", script_agent)
101
+
102
+ workflow.set_entry_point("intent")
103
+ workflow.add_edge("intent", "retrieval_parallel")
104
+ workflow.add_edge("retrieval_parallel", "fusion")
105
+ workflow.add_edge("fusion", "reflection")
106
+
107
+ def _route_reflection(state: AgenticState) -> str:
108
+ if should_loop_back(state):
109
+ return "retrieval_parallel"
110
+ return "validation"
111
+
112
+ workflow.add_conditional_edges("reflection", _route_reflection)
113
+ workflow.add_edge("validation", "script")
114
+ workflow.add_edge("script", END)
115
+
116
+ return workflow.compile()
117
+ except ImportError:
118
+ logger.info("LangGraph not installed — using sequential agent runner")
119
+ return SequentialRunner()
120
+
121
+
122
+ class SequentialRunner:
123
+ """Fallback runner when LangGraph is unavailable."""
124
+
125
+ def invoke(self, state: AgenticState) -> AgenticState:
126
+ return run_agentic_pipeline(state)
127
+
128
+ async def ainvoke(self, state: AgenticState) -> AgenticState:
129
+ return run_agentic_pipeline(state)
130
+
131
+
132
+ def generate_agentic(
133
+ query: str,
134
+ *,
135
+ product: str | None = None,
136
+ top_k: int = 8,
137
+ output_format: str = "both",
138
+ test_id: str | None = None,
139
+ ) -> AgenticState:
140
+ """High-level entry point for agentic generation."""
141
+ state = initial_state(
142
+ query,
143
+ product=product,
144
+ top_k=top_k,
145
+ output_format=output_format,
146
+ test_id=test_id,
147
+ )
148
+ graph = build_graph()
149
+ result = graph.invoke(state)
150
+ if not result.get("test_id"):
151
+ result["test_id"] = test_id or "TC_AGENT"
152
+ return result
@@ -0,0 +1,62 @@
1
+ """Healing agent — Phase 7."""
2
+ from __future__ import annotations
3
+
4
+ from knowledge_base.config import cfg
5
+ from knowledge_base.memory.cognee_client import get_cognee_client
6
+ from knowledge_base.memory.memory_types import MemoryType
7
+ from knowledge_base.generation.test_generator import _call_gpt
8
+
9
+
10
+ def propose_fix(test_id: str, flaky_history: list[dict] | None = None) -> dict:
11
+ """Propose script repair for flaky test."""
12
+ if not cfg.COGNEE_ENABLED:
13
+ return {"status": "execution_memory_not_populated", "confidence": 0.0}
14
+
15
+ client = get_cognee_client()
16
+ patterns = client.search(
17
+ query=f"flaky test patterns for {test_id}",
18
+ memory_types=[MemoryType.EXECUTION.value, MemoryType.PATTERN.value],
19
+ top_k=3,
20
+ )
21
+
22
+ if not patterns:
23
+ return {
24
+ "status": "execution_memory_not_populated",
25
+ "test_id": test_id,
26
+ "confidence": 0.0,
27
+ "rationale": "No execution memory patterns found for this test.",
28
+ }
29
+
30
+ pattern_text = "\n".join(p.content for p in patterns)
31
+ history_text = ""
32
+ if flaky_history:
33
+ history_text = "\nFlaky execution history:\n" + "\n".join(
34
+ f"- {h}" for h in flaky_history[:10]
35
+ )
36
+ prompt = f"""Given flaky test {test_id} and these patterns:
37
+ {pattern_text}
38
+ {history_text}
39
+
40
+ Propose a script fix. Return JSON with: proposed_change, change_type (locator|timing|assertion|fixture|registry_key), rationale."""
41
+
42
+ try:
43
+ response = _call_gpt(
44
+ "You are an IGEL test automation expert.",
45
+ prompt,
46
+ max_tokens=1024,
47
+ temperature=0.1,
48
+ )
49
+ confidence = 0.6
50
+ if "low_confidence" in response.lower():
51
+ confidence = 0.3
52
+ return {
53
+ "status": "complete",
54
+ "test_id": test_id,
55
+ "proposed_change": response[:2000],
56
+ "change_type": "timing",
57
+ "confidence": confidence,
58
+ "rationale": pattern_text[:500],
59
+ "low_confidence_fix": confidence < 0.5,
60
+ }
61
+ except Exception as e:
62
+ return {"status": "error", "error": str(e), "confidence": 0.0}
@@ -0,0 +1,76 @@
1
+ """Intent classification agent — Phase 5."""
2
+ from __future__ import annotations
3
+
4
+ import re
5
+
6
+ from knowledge_base.agents.state import AgenticState
7
+
8
+ _FEATURE_MAP = {
9
+ "entra": "Entra ID SSO",
10
+ "sso": "Entra ID SSO",
11
+ "mfa": "Entra ID MFA",
12
+ "wifi": "Network WiFi 802.1x",
13
+ "802.1": "Network WiFi 802.1x",
14
+ "icg": "ICG Certificate Management",
15
+ "certificate": "ICG Certificate Management",
16
+ "chromium": "Chromium Browser",
17
+ "ums": "UMS Administration",
18
+ "profile": "UMS Profile Assignment",
19
+ "amd": "AMD Driver Integration",
20
+ "hub": "Device Onboarding IGEL Hub",
21
+ }
22
+
23
+ _VERSIONS = ("12.8", "12.9", "12.10")
24
+
25
+
26
+ def intent_agent(state: AgenticState) -> AgenticState:
27
+ query = state.get("query", "")
28
+ q_lower = query.lower()
29
+
30
+ if any(w in q_lower for w in ("transform", "restructure", "reformat", "improve this")):
31
+ intent = "transform"
32
+ elif any(w in q_lower for w in ("expand", "add detail", "step-by-step")):
33
+ intent = "expand"
34
+ else:
35
+ intent = "synthesize"
36
+
37
+ feature = "Unknown"
38
+ for kw, name in _FEATURE_MAP.items():
39
+ if kw in q_lower:
40
+ feature = name
41
+ break
42
+
43
+ version_scope = "unspecified"
44
+ categories: list[str] = []
45
+ for v in _VERSIONS:
46
+ if v in query or f"os {v}" in q_lower:
47
+ version_scope = v
48
+ categories.append("version_specific")
49
+ break
50
+ if version_scope == "unspecified":
51
+ categories.append("version_unspecified")
52
+
53
+ if any(w in q_lower for w in ("fail", "error", "negative", "boundary")):
54
+ categories.append("negative_case")
55
+ if any(w in q_lower for w in ("regression", "release", "change impact")):
56
+ categories.append("regression")
57
+ if any(w in q_lower for w in ("debug", "troubleshoot", "root cause")):
58
+ categories.append("troubleshooting")
59
+ if any(w in q_lower for w in ("registry", "profile", "configure", "setting")):
60
+ categories.append("configuration")
61
+ if intent == "synthesize" and feature == "Unknown":
62
+ categories.append("feature_unclear")
63
+
64
+ state["intent"] = intent
65
+ state["feature_area"] = feature
66
+ state["version_scope"] = version_scope
67
+ state["query_categories"] = categories
68
+ state.setdefault("agent_trace", []).append({
69
+ "agent": "IntentAgent",
70
+ "status": "complete",
71
+ "intent": intent,
72
+ "feature_area": feature,
73
+ "version_scope": version_scope,
74
+ "query_categories": categories,
75
+ })
76
+ return state