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,755 @@
1
+ """
2
+ Prompt templates for IGEL test case generation.
3
+
4
+ Provides:
5
+ build_system_prompt() → static IGEL expert system prompt
6
+ assemble_context_window() → fit KB chunks into token budget
7
+ build_markdown_user_prompt() → prompt for detailed markdown test doc
8
+ build_python_user_prompt() → prompt for pytest Python file
9
+ """
10
+ from __future__ import annotations
11
+
12
+ import logging
13
+ from dataclasses import dataclass
14
+
15
+ from knowledge_base.config import cfg
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+ MAX_CONTEXT_TOKENS = int(getattr(cfg, "CONTEXT_TOKEN_BUDGET", 8000))
20
+ _CHARS_PER_TOKEN = 3.8 # conservative estimate, avoids importing tiktoken here
21
+
22
+ # Exact import block generated tests must use — injected verbatim into Python prompt
23
+ _REQUIRED_IMPORTS = """\
24
+ import time, allure
25
+ import pytest
26
+ from core.api.UMS import UMS
27
+ from core.api.ums_wums_api import UMSWUMSApi
28
+ from core.api.auth_token import UMSAuthTokenService
29
+ from core.ssh.ssh import SSHClient
30
+ from core.ui.ui_automation_text import OcrUiInteractor
31
+ from bussiness.page_login import ums_login
32
+ from config.read_config import ums_cred, device_cred, otp_secrets_cred, root_path
33
+ from core.ssh.my_logger import logger
34
+ from bussiness.onepassword_otp import OTPGenerator"""
35
+
36
+
37
+ # ── Data Model ────────────────────────────────────────────────────────────────
38
+
39
+ @dataclass
40
+ class PromptContext:
41
+ topic: str
42
+ test_id: str
43
+ feature_area: str
44
+ product: str | None
45
+ context_chunks: list # list[SearchResult] — avoid circular import
46
+ token_budget: int = MAX_CONTEXT_TOKENS
47
+ kg_context_block: str = ""
48
+ image_context_block: str = ""
49
+ web_context_block: str = ""
50
+ mcp_context_block: str = ""
51
+ memory_context_block: str = ""
52
+ temporal_context_block: str = ""
53
+ skip_assemble_window: bool = False
54
+
55
+
56
+ # ── Public API ────────────────────────────────────────────────────────────────
57
+
58
+ def build_system_prompt() -> str:
59
+ return _SYSTEM_PROMPT
60
+
61
+
62
+ def assemble_context_window(
63
+ results: list,
64
+ token_budget: int = MAX_CONTEXT_TOKENS,
65
+ ) -> tuple[list, int]:
66
+ """
67
+ Fit retrieved parent_content chunks into the token budget.
68
+ Prioritises higher rrf_score results. Truncates last chunk at word boundary if needed.
69
+ Returns (selected_results, estimated_tokens_used).
70
+ """
71
+ reserve = 800 # headroom for prompt template text
72
+ available = token_budget - reserve
73
+
74
+ def _rank_key(r) -> tuple[float, float]:
75
+ rr = getattr(r, "rerank_score", None)
76
+ if rr is not None:
77
+ return (-float(rr), -float(getattr(r, "rrf_score", 0.0)))
78
+ return (-float(getattr(r, "rrf_score", 0.0)), 0.0)
79
+
80
+ ordered = sorted(results, key=_rank_key)
81
+
82
+ selected = []
83
+ used = 0
84
+
85
+ for result in ordered:
86
+ chunk_tokens = _estimate_tokens(result.parent_content)
87
+ if used + chunk_tokens <= available:
88
+ selected.append(result)
89
+ used += chunk_tokens
90
+ elif available - used > 200:
91
+ # Truncate at word boundary to fill remaining space
92
+ remaining_chars = int((available - used) * _CHARS_PER_TOKEN)
93
+ truncated_content = _truncate_at_word(result.parent_content, remaining_chars)
94
+ # Create a shallow copy with truncated content
95
+ import copy
96
+ r = copy.copy(result)
97
+ r.parent_content = truncated_content + "\n[...truncated]"
98
+ selected.append(r)
99
+ used += _estimate_tokens(truncated_content)
100
+ break
101
+ else:
102
+ break
103
+
104
+ logger.debug("Context window: %d chunks, ~%d tokens", len(selected), used)
105
+ return selected, used
106
+
107
+
108
+ def build_markdown_user_prompt(ctx: PromptContext) -> str:
109
+ if ctx.skip_assemble_window:
110
+ selected = list(ctx.context_chunks)
111
+ tokens_used = sum(_estimate_tokens(r.parent_content) for r in selected)
112
+ else:
113
+ selected, tokens_used = assemble_context_window(ctx.context_chunks, ctx.token_budget)
114
+
115
+ prefix_parts: list[str] = []
116
+ if getattr(ctx, "kg_context_block", "") and ctx.kg_context_block.strip():
117
+ prefix_parts.append(ctx.kg_context_block.strip())
118
+ if getattr(ctx, "image_context_block", "") and ctx.image_context_block.strip():
119
+ prefix_parts.append(ctx.image_context_block.strip())
120
+ if getattr(ctx, "web_context_block", "") and ctx.web_context_block.strip():
121
+ prefix_parts.append(ctx.web_context_block.strip())
122
+ if getattr(ctx, "mcp_context_block", "") and ctx.mcp_context_block.strip():
123
+ prefix_parts.append(ctx.mcp_context_block.strip())
124
+ if getattr(ctx, "memory_context_block", "") and ctx.memory_context_block.strip():
125
+ prefix_parts.append(ctx.memory_context_block.strip())
126
+ if getattr(ctx, "temporal_context_block", "") and ctx.temporal_context_block.strip():
127
+ prefix_parts.append(ctx.temporal_context_block.strip())
128
+
129
+ context_block = _format_context_block(selected)
130
+ if prefix_parts:
131
+ context_block = "\n\n".join(prefix_parts) + "\n\n" + context_block
132
+
133
+ sources = kb_sources_for_prompt(selected)
134
+ sources_short = ", ".join(dict.fromkeys(r.file_name for r in selected)) or "IGEL documentation"
135
+
136
+ return f"""Generate a JIRA-level detailed IGEL test case document using the knowledge base context below.
137
+
138
+ TEST REQUEST
139
+ ============
140
+ Test ID : {ctx.test_id}
141
+ Topic : {ctx.topic}
142
+ Feature Area : {ctx.feature_area}
143
+ Product : {ctx.product or "IGEL OS 12"}
144
+ KB Sources : {sources_short}
145
+ KB traceability (IDs; same as SOURCE n / KB_REF in context): {sources}
146
+
147
+ KNOWLEDGE BASE CONTEXT
148
+ ======================
149
+ {context_block}
150
+
151
+ INSTRUCTIONS
152
+ ============
153
+ Using the context above, generate a complete JIRA-style test case. Match the exact level of
154
+ detail shown in IGEL JIRA tickets — specific TC Setup navigation paths, exact CLI commands,
155
+ precise expected results with exact UI element names.
156
+
157
+ The user's ask may be short (e.g. "SSO test steps"); ALWAYS produce the FULL detailed document
158
+ below — never a summary-only or bullet sketch. Depth must reflect what the KB passages support.
159
+
160
+ EXECUTABLE STEP QUALITY (NON-NEGOTIABLE)
161
+ ----------------------------------------
162
+ - Each TEST DATA sub-step must state WHO does WHAT WHERE: product surface (UMS Web, device session,
163
+ SSH shell, browser), exact control names, literal values to set or type.
164
+ - Every EXPECTED RESULT must name a concrete check (exact strings, exit code, journal line,
165
+ screenshot-level detail). If the KB gives an exact log pattern or UI label, reproduce it verbatim.
166
+ - Do NOT use filler phrases alone as expected results (e.g. "Pass", "OK", "Works as expected").
167
+ - Copy navigation paths, CLI, registry-style keys, file paths, and URLs from SOURCE/KB_REF blocks
168
+ when present; do not substitute generic equivalents.
169
+ - If the KB does not contain enough detail for a safe step, omit that step and note in
170
+ Additional Information that the KB did not specify it — do not guess.
171
+
172
+ OUTPUT FORMAT
173
+ =============
174
+
175
+ # {ctx.test_id}: {ctx.topic}
176
+
177
+ ## Key Details
178
+ | Field | Value |
179
+ |-------|-------|
180
+ | JIRA ID | {ctx.test_id} |
181
+ | Category | (infer from feature area and context) |
182
+ | Priority | High |
183
+ | Type | (Integration / Functional / Hardware-dependent — infer from context) |
184
+ | Feature Area | {ctx.feature_area} |
185
+ | Product | {ctx.product or "IGEL OS 12"} |
186
+ | Source Documents | {sources_short} |
187
+
188
+ ## Description
189
+ (2-3 sentences: what feature is tested, what this test validates, why it matters)
190
+
191
+ ## Additional Information
192
+ (Key technical notes as bullet points — include:
193
+ - default values and what they mean
194
+ - important config file paths like /etc/chromium-browser/... or /var/log/...
195
+ - policy names and parameter names from context
196
+ - any warnings or platform-specific notes from context)
197
+
198
+ ## Requirements
199
+ - IGEL OS version: (from context)
200
+ - UMS version: (from context)
201
+ - (any app version requirements from context)
202
+
203
+ ## Preconditions
204
+ (Bullet list — be specific. Example: "IGEL OS 12 device registered in UMS with online status confirmed in UMS console")
205
+
206
+ ## TC Setup — Configuration Navigation Paths
207
+ (List all UMS/device configuration steps using the exact path format:
208
+ `TC Setup > [Section] > [SubSection] > [Setting] = [value]`
209
+ Example: `TC Setup: Apps > Zoom > Zoom Sessions > Session Name = "Test_Session"`)
210
+
211
+ ## Test Details
212
+
213
+ ### Test Step Table
214
+ Three columns: **STEP** | **TEST DATA** | **EXPECTED RESULT**
215
+
216
+ | # | STEP | TEST DATA | EXPECTED RESULT |
217
+ |---|------|-----------|-----------------|
218
+
219
+ For each step:
220
+ - STEP: Brief title of what is being verified (e.g., "Check Hardware Video Acceleration")
221
+ - TEST DATA: Numbered sub-steps with exact actions. Include:
222
+ * TC Setup navigation paths: `TC Setup: Apps > [App] > [Setting] = true/false`
223
+ * Exact CLI commands with full syntax: `ps ax | grep process-name`
224
+ * Exact file paths: `/var/log/user/app.log`
225
+ * Specific URLs for verification: `chrome://media-internals`
226
+ * Policy/config values: `HardwareAccelerationModeEnabled`
227
+ - EXPECTED RESULT: Specific verifiable outcomes. Include:
228
+ * Exact UI elements visible (e.g., "Home, Chat, Meetings, Contacts tabs visible")
229
+ * Exact log output expected (e.g., "journalctl shows no errors for process X")
230
+ * Specific commands and their expected output
231
+ * Pass/fail criterion with exact wording
232
+
233
+ Generate as many test steps as the KB context and KG entities justify — do not pad with
234
+ vague or invented steps. Each step must have at least 2 concrete sub-steps in TEST DATA.
235
+ If no manual TC is provided, derive all steps from the Knowledge Base passages and KG nodes
236
+ retrieved above; use the exact registry keys, UI paths, and CLI commands found there.
237
+
238
+ ## Cleanup
239
+ | Step | Action | Command/Navigation | Verification |
240
+ |------|--------|--------------------|-------------|
241
+ (Specific cleanup steps — detach profiles, reboot, verify clean state)
242
+
243
+ ## Troubleshooting
244
+ | # | Issue | Symptoms | Root Cause | Fix |
245
+ |---|-------|----------|------------|-----|
246
+ (Minimum 3 specific issues from context — include exact diagnostic commands)
247
+
248
+ Generate the complete document now. Use specific IGEL terminology, exact navigation paths,
249
+ real CLI commands, and concrete expected values. Never write "TBD" or "[add here]"."""
250
+
251
+
252
+ def format_kb_context_excerpt_for_python(results: list, max_chars: int = 7500) -> str:
253
+ """Ground pytest generation in the same KB text as markdown (truncated for token limits)."""
254
+ if not results:
255
+ return "(No KB chunks — do not invent product steps.)"
256
+ body = _format_context_block(results)
257
+ if len(body) <= max_chars:
258
+ return body
259
+ truncated = _truncate_at_word(body, max_chars)
260
+ return (
261
+ truncated
262
+ + "\n\n[...KB excerpt truncated for token budget; strings and paths above remain "
263
+ "authoritative for implementation.]\n"
264
+ )
265
+
266
+
267
+ def build_python_user_prompt(ctx: PromptContext, markdown_content: str) -> str:
268
+ test_id_upper = ctx.test_id.upper()
269
+ slug = _slugify(ctx.topic)
270
+ filename = f"test_{ctx.test_id}_{slug}.py"
271
+ # Extract step count hint from markdown — use actual count, no artificial floor
272
+ step_count = markdown_content.lower().count("#### step") or markdown_content.lower().count("| # |") or 0
273
+
274
+ kb_excerpt = format_kb_context_excerpt_for_python(ctx.context_chunks)
275
+ extra_context = []
276
+ if getattr(ctx, "kg_context_block", "") and ctx.kg_context_block.strip():
277
+ extra_context.append(ctx.kg_context_block.strip())
278
+ if getattr(ctx, "web_context_block", "") and ctx.web_context_block.strip():
279
+ extra_context.append(ctx.web_context_block.strip())
280
+ if getattr(ctx, "mcp_context_block", "") and ctx.mcp_context_block.strip():
281
+ extra_context.append(ctx.mcp_context_block.strip())
282
+ extra_block = "\n\n".join(extra_context)
283
+
284
+ return f"""Generate a Python pytest file for the following IGEL test case.
285
+
286
+ KNOWLEDGE BASE CONTEXT (PostgreSQL RAG — ground truth; implement only behavior supported here)
287
+ ================================================================================
288
+ {extra_block + chr(10) + chr(10) if extra_block else ""}{kb_excerpt}
289
+
290
+ SPECIFICATION (from markdown test case or topic summary)
291
+ =========================================================
292
+ {markdown_content[:4000]}
293
+
294
+ Implement step logic that matches BOTH the specification table AND the KB context above: use the
295
+ same navigation strings, shell commands, file paths, policy names, and on-screen text the KB shows.
296
+ Do not add product-specific steps absent from the KB. Steps must be executable with this project's
297
+ fixtures (UMS, WUMS, SSH, OCR) — no vague asserts.
298
+
299
+ STRICT REQUIREMENTS — follow exactly, no deviations
300
+ =====================================================
301
+
302
+ 1. FILE NAME: {filename}
303
+
304
+ 2. MODULE DOCSTRING (copy this template exactly):
305
+ \"\"\"
306
+ Test ID : {ctx.test_id}
307
+ Title : {ctx.topic}
308
+ Feature : {ctx.feature_area}
309
+ Product : {ctx.product or "IGEL OS 12"}
310
+ Description: [1-sentence description from specification above]
311
+ Author : IGEL QA Automation (AI-Generated)
312
+ \"\"\"
313
+
314
+ 3. IMPORTS — copy these verbatim, do not add or remove any:
315
+ {_REQUIRED_IMPORTS}
316
+
317
+ 4. MODULE-LEVEL (after imports):
318
+ click = OcrUiInteractor()
319
+
320
+ 5. HELPER FUNCTIONS:
321
+ def get_ssh():
322
+ return SSHClient(host=device_cred["host"], user=device_cred["user"],
323
+ pwd=device_cred["pwd"], port=device_cred["port"])
324
+
325
+ def _assign(ums, wums, device, profile_key, default_name, api_config):
326
+ profile = ums.get_profile_details(api_config.get(profile_key, default_name))
327
+ wums.assign_object(device["id"], profile["id"], "profile")
328
+ return profile
329
+
330
+ def _detach(ums, wums, device, profile_key, default_name, api_config):
331
+ profile = ums.get_profile_details(api_config.get(profile_key, default_name))
332
+ wums.detach_profile(device["id"], profile["id"])
333
+
334
+ 6. STEP FUNCTIONS — generate {step_count if step_count > 0 else "one step per test scenario found in"} the specification above + 1 cleanup:
335
+ - Decorator: @allure.step("{test_id_upper} SN: [short description]")
336
+ - Signature: def {test_id_upper}_stepN(api_config, browser): -> bool
337
+ - Body pattern:
338
+ try:
339
+ ums = UMS(ums_cred["base_url"], ums_cred["username"], ums_cred["password"])
340
+ wums = UMSWUMSApi(ums_cred["weburl"], ums_cred["username"], ums_cred["password"])
341
+ dev = ums.get_vm_details(device_cred["hostname"])
342
+ [step implementation from specification]
343
+ return True / return result_bool
344
+ except Exception as e:
345
+ logger.error(f"{test_id_upper}_stepN: {{e}}"); return False
346
+
347
+ - Cleanup: @allure.step("{test_id_upper} Cleanup: [description]")
348
+ def {test_id_upper}_cleanup(api_config): -> bool
349
+
350
+ 7. TEST FUNCTIONS — one per step, SINGLE LINE each:
351
+ @allure.feature("{ctx.feature_area}")
352
+ @allure.severity(allure.severity_level.CRITICAL)
353
+ def test_{ctx.test_id}_step1(api_config, browser_instance): assert {test_id_upper}_step1(api_config, browser_instance)
354
+
355
+ @allure.feature("{ctx.feature_area}")
356
+ @allure.severity(allure.severity_level.CRITICAL)
357
+ def test_{ctx.test_id}_step2(api_config, browser_instance): assert {test_id_upper}_step2(api_config, browser_instance)
358
+
359
+ [continue for each step, then:]
360
+
361
+ @allure.feature("{ctx.feature_area}")
362
+ @allure.severity(allure.severity_level.MINOR)
363
+ def test_{ctx.test_id}_cleanup(api_config): assert {test_id_upper}_cleanup(api_config)
364
+
365
+ 8. RULES:
366
+ - ALL configurable values from api_config dict — NEVER hardcode IPs, passwords, or secrets
367
+ - Use ums_cred["base_url"], ums_cred["weburl"], device_cred — for hosts/URLs not in those dicts,
368
+ use string literals ONLY when they appear verbatim in the KB context (e.g. chrome:// URLs,
369
+ fixed IGEL paths). Never use example.com or guessed tenant URLs.
370
+ - Use click.is_text_present_on_screen() and click.click_text_on_screen() for OCR checks — pass
371
+ the exact visible strings from KB/spec, not paraphrases
372
+ - Use ssh.exec("command") with the exact commands from KB/spec (full flags/paths)
373
+ - Every step function returns bool; each step must encode a concrete observable check
374
+ - No TODO comments, no placeholder text, no "verify success" without a named check
375
+ - No additional imports beyond the verbatim block above
376
+
377
+ Generate the complete Python file now. Output raw Python only — no markdown fences."""
378
+
379
+
380
+ # ── Internal Helpers ──────────────────────────────────────────────────────────
381
+
382
+ def _estimate_tokens(text: str) -> int:
383
+ return int(len(text) / _CHARS_PER_TOKEN)
384
+
385
+
386
+ def _truncate_at_word(text: str, max_chars: int) -> str:
387
+ if len(text) <= max_chars:
388
+ return text
389
+ truncated = text[:max_chars]
390
+ last_space = truncated.rfind(" ")
391
+ return truncated[:last_space] if last_space > 0 else truncated
392
+
393
+
394
+ def kb_trace_lines(results: list) -> list[str]:
395
+ """One trace string per retrieved parent context (same order as SOURCE n / KB_REF)."""
396
+ lines: list[str] = []
397
+ for i, r in enumerate(results, start=1):
398
+ doc = getattr(r, "document_id", "") or "—"
399
+ parent = getattr(r, "parent_chunk_id", "") or "—"
400
+ child = getattr(r, "child_chunk_id", "") or "—"
401
+ sec = getattr(r, "section_title", "") or "—"
402
+ fn = getattr(r, "file_name", "") or "—"
403
+ lines.append(
404
+ f"[KB_REF {i}] file={fn} | section={sec} | document_id={doc} | "
405
+ f"parent_chunk_id={parent} | child_chunk_id={child}"
406
+ )
407
+ return lines
408
+
409
+
410
+ def kb_sources_for_prompt(results: list) -> str:
411
+ """Compact ID list for the prompt header (same KB_REF order as context blocks)."""
412
+ if not results:
413
+ return "IGEL documentation"
414
+ return "; ".join(kb_trace_lines(results))
415
+
416
+
417
+ def format_kb_retrieval_references_markdown(results: list) -> str:
418
+ """Appendix for generated markdown: exact chunk traceability for cross-checking the KB."""
419
+ if not results:
420
+ return ""
421
+ rows = [
422
+ "| KB_REF | File | Section | document_id | parent_chunk_id | child_chunk_id | RRF | Rerank |",
423
+ "|--------|------|---------|-------------|-----------------|----------------|-----|--------|",
424
+ ]
425
+ for i, r in enumerate(results, start=1):
426
+ rr = getattr(r, "rerank_score", None)
427
+ rr_s = f"{rr:.4f}" if rr is not None else "—"
428
+ sec = (getattr(r, "section_title", None) or "").replace("|", "\\|")
429
+ fn = (getattr(r, "file_name", None) or "").replace("|", "\\|")
430
+ rows.append(
431
+ f"| {i} | {fn} | {sec} | `{getattr(r, 'document_id', '')}` | "
432
+ f"`{getattr(r, 'parent_chunk_id', '')}` | `{getattr(r, 'child_chunk_id', '')}` | "
433
+ f"{getattr(r, 'rrf_score', 0.0):.4f} | {rr_s} |"
434
+ )
435
+ note = (
436
+ "\n*These rows match the `SOURCE n` / `KB_REF` blocks in the knowledge base context "
437
+ "sent to the model. Use `parent_chunk_id` / `document_id` to locate rows in PostgreSQL "
438
+ "(`kb_parent_chunks`, `kb_documents`).*\n"
439
+ )
440
+ return "## KB retrieval traceability\n\n" + "\n".join(rows) + note
441
+
442
+
443
+ def format_kb_retrieval_references_python_comment(results: list) -> str:
444
+ """Trailing comment block for generated pytest files (traceability)."""
445
+ if not results:
446
+ return ""
447
+ lines = ["# --- KB retrieval references (cross-check in DB / ingest logs) ---"]
448
+ for i, r in enumerate(results, start=1):
449
+ lines.append(
450
+ f"# [KB_REF {i}] file={getattr(r, 'file_name', '')!r} "
451
+ f"section={getattr(r, 'section_title', '')!r} "
452
+ f"document_id={getattr(r, 'document_id', '')!r} "
453
+ f"parent_chunk_id={getattr(r, 'parent_chunk_id', '')!r} "
454
+ f"child_chunk_id={getattr(r, 'child_chunk_id', '')!r}"
455
+ )
456
+ return "\n\n" + "\n".join(lines) + "\n"
457
+
458
+
459
+ def _format_context_block(results: list) -> str:
460
+ if not results:
461
+ return "(No relevant KB content found)"
462
+ parts = []
463
+ for i, r in enumerate(results, start=1):
464
+ rr_tail = (
465
+ f" | Rerank: {r.rerank_score:.4f}"
466
+ if getattr(r, "rerank_score", None) is not None
467
+ else ""
468
+ )
469
+ parts.append(
470
+ f"=== SOURCE {i} (KB_REF={i}) | {r.section_title or r.file_name} ===\n"
471
+ f"document_id={r.document_id}\n"
472
+ f"parent_chunk_id={r.parent_chunk_id}\n"
473
+ f"child_chunk_id={r.child_chunk_id}\n"
474
+ f"Product: {r.product} | File: {r.file_name} | Section: {r.section_title or '—'} | "
475
+ f"Type: {r.chunk_type} | Relevance_RRF: {r.rrf_score:.4f}{rr_tail}\n\n"
476
+ f"{r.parent_content.strip()}"
477
+ )
478
+ return "\n\n" + "\n\n---\n\n".join(parts) + "\n"
479
+
480
+
481
+ def _slugify(text: str) -> str:
482
+ import re
483
+ slug = text.lower()
484
+ slug = re.sub(r"[^a-z0-9\s]", "", slug)
485
+ slug = re.sub(r"\s+", "_", slug.strip())
486
+ return slug[:50]
487
+
488
+
489
+ # ── Gold / partial TC modes (fidelity-first) ─────────────────────────────────
490
+
491
+ TRANSFORM_SYSTEM_ADDON = """
492
+
493
+ MODE: MANUAL TEST CASE TRANSFORMATION (not authoring)
494
+ ======================================================
495
+ The user supplied an official IGEL manual test. Your job is to REPACKAGE it into the template format
496
+ and (when asked) pytest structure — NOT to invent new scenarios, edge cases, or extra steps.
497
+ Preserve step count and order. Use supplementary KB text only to clarify terms already present.
498
+ """
499
+
500
+ EXPAND_SYSTEM_ADDON = """
501
+
502
+ MODE: PARTIAL TEST CASE EXPANSION
503
+ =================================
504
+ The user supplied an incomplete JIRA/manual TC. Keep every original step and phrase intact in the output.
505
+ Add ONLY missing expected results, preconditions, or clarifying sub-steps where the description implies them.
506
+ Use KB context to ground new text. Do not replace or remove original steps.
507
+ """
508
+
509
+
510
+ def load_pytest_exemplar(max_chars: int = 6000) -> str:
511
+ """Few-shot excerpt from a known-good generated/hand-written pytest file."""
512
+ from pathlib import Path
513
+ p = Path(__file__).resolve().parent / "exemplars" / "pytest_reference_snippet.py"
514
+ if not p.exists():
515
+ return ""
516
+ text = p.read_text(encoding="utf-8", errors="replace")
517
+ if len(text) <= max_chars:
518
+ return text
519
+ return text[:max_chars] + "\n# [...truncated exemplar]\n"
520
+
521
+
522
+ def format_parsed_steps_table(steps: list) -> str:
523
+ """Markdown table from ParsedStep list."""
524
+ if not steps:
525
+ return "(no parsed steps)"
526
+ rows = [
527
+ "| # | Step | Test Data | Expected Result |",
528
+ "|---|------|-----------|-----------------|",
529
+ ]
530
+ for s in steps:
531
+ def _cell(x: str, lim: int) -> str:
532
+ t = (x or "").replace("\n", " ").replace("|", "\\|").strip()
533
+ return t[:lim] + ("…" if len(t) > lim else "")
534
+
535
+ rows.append(
536
+ f"| {_cell(s.step_id, 12)} | {_cell(s.step_title, 80)} | "
537
+ f"{_cell(s.test_data, 220)} | {_cell(s.expected_result, 120)} |"
538
+ )
539
+ return "\n".join(rows)
540
+
541
+
542
+ def build_transform_markdown_user_prompt(
543
+ *,
544
+ test_id: str,
545
+ feature_area: str,
546
+ product: str | None,
547
+ source_tc_full: str,
548
+ supplementary_context: str,
549
+ detail_note: str,
550
+ ) -> str:
551
+ return f"""Convert the OFFICIAL IGEL manual test case below into the project's JIRA-style Markdown template.
552
+
553
+ CRITICAL — FIDELITY FIRST
554
+ =========================
555
+ - The ORIGINAL MANUAL TEST CASE section is the SOURCE OF TRUTH.
556
+ - Preserve EVERY step's intent, order, and scope. Do NOT add scenarios, negative tests, or steps not in the source.
557
+ - Do NOT remove steps. Do NOT merge unless the source explicitly combines them in one line.
558
+ - Refine wording only for readability; keep TC Setup paths, CLI, URLs, registry keys, and expected outcomes aligned with the source.
559
+ - The final Test Step Table must allow 1:1 traceability to the original step list.
560
+
561
+ Detail target: {detail_note}
562
+
563
+ ORIGINAL MANUAL TEST CASE
564
+ =========================
565
+ {source_tc_full.strip()}
566
+
567
+ SUPPLEMENTARY KB CONTEXT (use only to clarify terms present in the source; never add unrelated test ideas)
568
+ ==================================================================================
569
+ {supplementary_context.strip() if supplementary_context.strip() else "(none)"}
570
+
571
+ OUTPUT METADATA (use in Key Details)
572
+ ====================================
573
+ Test ID : {test_id}
574
+ Feature Area : {feature_area}
575
+ Product : {product or "IGEL OS 12"}
576
+
577
+ Produce: Key Details, Description, Preconditions, TC Setup, Test Step Table (STEP | TEST DATA | EXPECTED RESULT),
578
+ Additional Information, Requirements, Cleanup, Troubleshooting — following the same section expectations as standard generation.
579
+ """
580
+
581
+ def build_expand_markdown_user_prompt(
582
+ *,
583
+ test_id: str,
584
+ topic: str,
585
+ feature_area: str,
586
+ product: str | None,
587
+ source_tc_full: str,
588
+ parsed_steps_table: str,
589
+ kb_context_block: str,
590
+ kg_image_prefix: str,
591
+ detail_note: str,
592
+ ) -> str:
593
+ prefix = kg_image_prefix.strip()
594
+ body = kb_context_block.strip()
595
+ context = f"{prefix}\n\n{body}".strip() if prefix else body
596
+ return f"""Expand this PARTIAL IGEL test case into a complete JIRA-style Markdown document.
597
+
598
+ RULES
599
+ =====
600
+ - Reproduce EVERY original line/step from the partial TC; keep titles and actions verbatim where possible.
601
+ - Fill gaps: missing Expected Results, Preconditions, or TC Setup paths using ONLY the knowledge context below.
602
+ - If KB does not support a detail, write "Not specified in KB — manual confirmation required" instead of inventing.
603
+ - Do not add unrelated scenarios.
604
+
605
+ Detail target: {detail_note}
606
+
607
+ PARTIAL TEST CASE (raw)
608
+ =======================
609
+ {source_tc_full.strip()}
610
+
611
+ PARSED STEPS (reference)
612
+ ========================
613
+ {parsed_steps_table}
614
+
615
+ TOPIC / SUMMARY
616
+ ===============
617
+ {topic}
618
+
619
+ KNOWLEDGE CONTEXT (RAG + KG + images)
620
+ =====================================
621
+ {context if context else "(no retrieval — expand from source only)"}
622
+
623
+ OUTPUT METADATA
624
+ ===============
625
+ Test ID : {test_id}
626
+ Feature Area : {feature_area}
627
+ Product : {product or "IGEL OS 12"}
628
+
629
+ Generate the full Markdown document with the standard sections and a complete Test Step Table.
630
+ """
631
+
632
+ def build_transform_python_user_prompt(
633
+ *,
634
+ test_id: str,
635
+ topic: str,
636
+ feature_area: str,
637
+ product: str | None,
638
+ markdown_spec: str,
639
+ exemplar_py: str,
640
+ ) -> str:
641
+ """Python generation after transform markdown — reuses structure from build_python_user_prompt."""
642
+ slug = _slugify(topic)
643
+ filename = f"test_{test_id}_{slug}.py"
644
+ test_id_upper = test_id.upper()
645
+ step_count = max(markdown_spec.lower().count("#### step"), markdown_spec.count("|") // 3, 3)
646
+
647
+ exemplar_block = exemplar_py.strip() if exemplar_py.strip() else "(see standard import pattern in instructions)"
648
+
649
+ return f"""Generate a Python pytest file that implements EXACTLY the manual flow in the specification below.
650
+
651
+ FIDELITY
652
+ ========
653
+ - Implement one step function per logical step in the Markdown spec (same order). Do not add exploratory or negative tests.
654
+ - Each step should reflect the Test Data and Expected Result from the spec.
655
+ - Use api_config / ums_cred / device_cred — never hardcode secrets.
656
+
657
+ REFERENCE EXAMPLE (shape and style only — do not copy unrelated scenarios)
658
+ ==========================================================================
659
+ ```python
660
+ {exemplar_block[:5500]}
661
+ ```
662
+
663
+ SPECIFICATION
664
+ =============
665
+ {markdown_spec[:6500]}
666
+
667
+ STRICT REQUIREMENTS
668
+ ===================
669
+ 1. FILE NAME: {filename}
670
+
671
+ 2. MODULE DOCSTRING:
672
+ \"\"\"
673
+ Test ID : {test_id}
674
+ Title : {topic}
675
+ Feature : {feature_area}
676
+ Product : {product or "IGEL OS 12"}
677
+ Description: Mapped from official IGEL manual TC (fidelity mode)
678
+ Author : IGEL QA Automation (AI-Generated)
679
+ \"\"\"
680
+
681
+ 3. IMPORTS — copy verbatim:
682
+ {_REQUIRED_IMPORTS}
683
+
684
+ 4. After imports: click = OcrUiInteractor()
685
+
686
+ 5. Helpers: get_ssh(), _assign(...), _detach(...) as in standard generator.
687
+
688
+ 6. Generate approximately {step_count} step functions + 1 cleanup. Each step returns bool.
689
+
690
+ 7. TEST FUNCTIONS: single-line assert per step; @allure.feature("{feature_area}")
691
+
692
+ Output raw Python only — no markdown fences.
693
+ """
694
+
695
+
696
+ # ── System Prompt ─────────────────────────────────────────────────────────────
697
+
698
+ _SYSTEM_PROMPT = """\
699
+ You are a senior IGEL QA automation engineer with deep expertise in testing IGEL products.
700
+ Your job is to generate precise, complete, and executable test cases based ONLY on the
701
+ documentation context provided. Never invent steps, settings, or expected values not
702
+ explicitly present in the context.
703
+
704
+ IGEL PRODUCT KNOWLEDGE
705
+ ======================
706
+ - UMS (Universal Management Suite): Central device management server. REST API on HTTPS port 8443.
707
+ URL pattern: https://<ums-ip>:8443/umsapi/v3/. Used to manage profiles, assign them to devices,
708
+ and issue commands (reboot, factory reset). Web UI at https://<ums-ip>:8443/webapp/.
709
+ - IGEL OS 12: Linux-based thin client operating system. SSH accessible as root on port 22.
710
+ Device can be controlled via UMS API (profiles) and directly via SSH commands.
711
+ - COSMOS: Cloud-based management platform for IGEL devices (cloud alternative to on-prem UMS).
712
+ - ICG (IGEL Cloud Gateway): Secure reverse proxy allowing UMS to communicate with devices
713
+ outside the corporate network without VPN.
714
+ - IMI (IGEL Management Interface): REST API for programmatic UMS control (token-based auth).
715
+ - SSO Providers: Entra ID (Microsoft Azure AD), Okta, PingOne, Omnissa Horizon.
716
+
717
+ TEST AUTOMATION FRAMEWORK
718
+ =========================
719
+ - Python + pytest with Allure reporting
720
+ - UMS class: core.api.UMS — manages device/profile assignments via REST
721
+ - UMSWUMSApi class: core.api.ums_wums_api — assign/detach profiles, device operations
722
+ - SSHClient: core.ssh.ssh — execute shell commands on IGEL device via SSH
723
+ - OcrUiInteractor (click): core.ui.ui_automation_text — OCR-based screen validation and interaction
724
+ - ums_login: bussiness.page_login — Playwright browser automation for UMS Web UI
725
+ - OTPGenerator: bussiness.onepassword_otp — TOTP generation for MFA flows
726
+ - Configuration: config.read_config — ums_cred, device_cred, otp_secrets_cred, root_path
727
+ - api_config: loaded from testdata/sso/api_config.yaml["igel"] — profile names, usernames, etc.
728
+
729
+ GENERATION RULES
730
+ ================
731
+ 1. Use ONLY the provided KB context passages. If a step is not in the context, do not include it.
732
+ 2. ALL configurable values (profile names, URLs, usernames) come from api_config["key"] or
733
+ ums_cred/device_cred dicts. NEVER hardcode actual IPs, passwords, or credentials.
734
+ 3. For markdown: follow the template structure exactly with all required sections and tables.
735
+ 4. For Python: step functions MUST return bool; test functions MUST be single-line assert calls.
736
+ 5. Be specific: use actual IGEL terminology, SSH commands, and OCR check patterns from context.
737
+ 6. Cleanup steps are mandatory — always detach profiles and reboot the device.
738
+
739
+ DETAILED & EXECUTABLE STEPS (MANDATORY)
740
+ =======================================
741
+ - Answer the user's topic with the MOST DETAILED test flow the KB allows — whether they asked for
742
+ "high-level steps", "test steps", or "detailed steps", always expand into full executable steps.
743
+ - Every step MUST be something a tester can run without interpretation: exact menu paths, exact CLI
744
+ with full syntax, exact file paths, exact policy/parameter names, exact UI strings to look for.
745
+ - FORBIDDEN vague wording: "verify it works", "ensure proper behavior", "check configuration",
746
+ "validate the setup", "confirm success", "test the feature" without naming WHAT is observed WHERE.
747
+ - REQUIRED: each EXPECTED RESULT ties to an observable (visible label, log line, command output,
748
+ HTTP status, file content snippet, API field) copied from or clearly implied by the KB context.
749
+ - URLs and URI schemes: ONLY use URLs, deep links, and browser/chrome internal URLs that appear in
750
+ the KB context (or standard patterns documented there, e.g. UMS port 8443 paths). NEVER invent
751
+ placeholder URLs (no example.com, no made-up tenant hostnames). For tenant-specific endpoints,
752
+ express hosts via ums_cred / api_config in generated code; in markdown describe the pattern.
753
+ - General platform knowledge may clarify HOW to run a command already in context, but must not add
754
+ new product-specific claims or paths not supported by the retrieved passages.
755
+ """