igel-qe-core 1.0.3 → 1.0.7

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 (628) hide show
  1. package/dist/cli/index.js +638 -54
  2. package/dist/cli/platform.js +115 -72
  3. package/dist/mcp/server.js +258 -17
  4. package/package.json +4 -4
  5. package/src/__pycache__/__init__.cpython-311.pyc +0 -0
  6. package/src/__pycache__/__init__.cpython-313.pyc +0 -0
  7. package/src/__pycache__/__init__.cpython-314.pyc +0 -0
  8. package/src/agents/__init__.py +3 -0
  9. package/src/agents/__pycache__/__init__.cpython-311.pyc +0 -0
  10. package/src/agents/__pycache__/__init__.cpython-313.pyc +0 -0
  11. package/src/agents/__pycache__/__init__.cpython-314.pyc +0 -0
  12. package/src/agents/__pycache__/automation_design_agent.cpython-311.pyc +0 -0
  13. package/src/agents/__pycache__/automation_design_agent.cpython-313.pyc +0 -0
  14. package/src/agents/__pycache__/automation_design_agent.cpython-314.pyc +0 -0
  15. package/src/agents/__pycache__/code_intelligence_agent.cpython-311.pyc +0 -0
  16. package/src/agents/__pycache__/code_intelligence_agent.cpython-313.pyc +0 -0
  17. package/src/agents/__pycache__/confidence_agent.cpython-311.pyc +0 -0
  18. package/src/agents/__pycache__/confidence_agent.cpython-313.pyc +0 -0
  19. package/src/agents/__pycache__/confidence_agent.cpython-314.pyc +0 -0
  20. package/src/agents/__pycache__/execution_validation_agent.cpython-311.pyc +0 -0
  21. package/src/agents/__pycache__/execution_validation_agent.cpython-313.pyc +0 -0
  22. package/src/agents/__pycache__/execution_validation_agent.cpython-314.pyc +0 -0
  23. package/src/agents/__pycache__/framework_analyzer_agent.cpython-311.pyc +0 -0
  24. package/src/agents/__pycache__/framework_analyzer_agent.cpython-313.pyc +0 -0
  25. package/src/agents/__pycache__/fusion_agent.cpython-314.pyc +0 -0
  26. package/src/agents/__pycache__/graph.cpython-314.pyc +0 -0
  27. package/src/agents/__pycache__/intent_agent.cpython-313.pyc +0 -0
  28. package/src/agents/__pycache__/intent_agent.cpython-314.pyc +0 -0
  29. package/src/agents/__pycache__/kg_agent.cpython-314.pyc +0 -0
  30. package/src/agents/__pycache__/memory_agent.cpython-314.pyc +0 -0
  31. package/src/agents/__pycache__/reflection_agent.cpython-314.pyc +0 -0
  32. package/src/agents/__pycache__/regression_agent.cpython-311.pyc +0 -0
  33. package/src/agents/__pycache__/regression_agent.cpython-313.pyc +0 -0
  34. package/src/agents/__pycache__/requirement_agent.cpython-311.pyc +0 -0
  35. package/src/agents/__pycache__/requirement_agent.cpython-313.pyc +0 -0
  36. package/src/agents/__pycache__/requirement_agent.cpython-314.pyc +0 -0
  37. package/src/agents/__pycache__/retrieval_agent.cpython-314.pyc +0 -0
  38. package/src/agents/__pycache__/scenario_agent.cpython-311.pyc +0 -0
  39. package/src/agents/__pycache__/scenario_agent.cpython-313.pyc +0 -0
  40. package/src/agents/__pycache__/scenario_agent.cpython-314.pyc +0 -0
  41. package/src/agents/__pycache__/script_agent.cpython-314.pyc +0 -0
  42. package/src/agents/__pycache__/script_generator_agent.cpython-311.pyc +0 -0
  43. package/src/agents/__pycache__/script_generator_agent.cpython-313.pyc +0 -0
  44. package/src/agents/__pycache__/script_generator_agent.cpython-314.pyc +0 -0
  45. package/src/agents/__pycache__/state.cpython-314.pyc +0 -0
  46. package/src/agents/__pycache__/temporal_agent.cpython-314.pyc +0 -0
  47. package/src/agents/__pycache__/testcase_agent.cpython-311.pyc +0 -0
  48. package/src/agents/__pycache__/testcase_agent.cpython-313.pyc +0 -0
  49. package/src/agents/__pycache__/testcase_agent.cpython-314.pyc +0 -0
  50. package/src/agents/__pycache__/validation_agent.cpython-311.pyc +0 -0
  51. package/src/agents/__pycache__/validation_agent.cpython-313.pyc +0 -0
  52. package/src/agents/__pycache__/validation_agent.cpython-314.pyc +0 -0
  53. package/src/agents/__pycache__/workflow_engine.cpython-311.pyc +0 -0
  54. package/src/agents/__pycache__/workflow_engine.cpython-313.pyc +0 -0
  55. package/src/agents/__pycache__/workflow_engine.cpython-314.pyc +0 -0
  56. package/{knowledge_base → src}/agents/automation_design_agent.py +14 -17
  57. package/{knowledge_base → src}/agents/code_intelligence_agent.py +2 -2
  58. package/src/agents/confidence_agent.py +114 -0
  59. package/{knowledge_base → src}/agents/execution_validation_agent.py +1 -1
  60. package/src/agents/feedback_agent.py +89 -0
  61. package/src/agents/framework_analyzer_agent.py +43 -0
  62. package/{knowledge_base → src}/agents/fusion_agent.py +3 -3
  63. package/{knowledge_base → src}/agents/graph.py +10 -10
  64. package/{knowledge_base → src}/agents/healing_agent.py +4 -4
  65. package/src/agents/intent_agent.py +30 -0
  66. package/src/agents/internal/__init__.py +3 -0
  67. package/src/agents/internal/__pycache__/__init__.cpython-313.pyc +0 -0
  68. package/src/agents/internal/__pycache__/approval_manager.cpython-313.pyc +0 -0
  69. package/src/agents/internal/__pycache__/question_engine.cpython-313.pyc +0 -0
  70. package/src/agents/internal/approval_manager.py +111 -0
  71. package/src/agents/internal/question_engine.py +111 -0
  72. package/src/agents/internal/workflow_engine.py +28 -0
  73. package/{knowledge_base → src}/agents/kg_agent.py +3 -3
  74. package/{knowledge_base → src}/agents/memory_agent.py +4 -4
  75. package/src/agents/orchestrator/__init__.py +3 -0
  76. package/src/agents/orchestrator/__pycache__/__init__.cpython-313.pyc +0 -0
  77. package/src/agents/orchestrator/__pycache__/orchestrator.cpython-313.pyc +0 -0
  78. package/src/agents/orchestrator/orchestrator.py +63 -0
  79. package/{knowledge_base → src}/agents/rca_agent.py +4 -4
  80. package/{knowledge_base → src}/agents/reflection_agent.py +1 -1
  81. package/{knowledge_base → src}/agents/regression_agent.py +2 -2
  82. package/src/agents/requirement_agent.py +97 -0
  83. package/{knowledge_base → src}/agents/retrieval_agent.py +2 -2
  84. package/{knowledge_base → src}/agents/scenario_agent.py +11 -17
  85. package/{knowledge_base → src}/agents/script_agent.py +6 -6
  86. package/{knowledge_base → src}/agents/script_generator_agent.py +12 -10
  87. package/{knowledge_base → src}/agents/temporal_agent.py +3 -3
  88. package/src/agents/testcase_agent.py +163 -0
  89. package/{knowledge_base → src}/agents/validation_agent.py +1 -1
  90. package/src/agents/workflow_engine.py +109 -0
  91. package/{knowledge_base → src}/alembic/README.md +4 -4
  92. package/{knowledge_base → src}/alembic/env.py +1 -1
  93. package/{knowledge_base → src}/alembic/script.py.mako +1 -1
  94. package/{knowledge_base → src}/api/middleware.py +3 -3
  95. package/{knowledge_base → src}/api/server.py +28 -28
  96. package/{knowledge_base → src}/chunking/chunker.py +3 -3
  97. package/src/cli/__pycache__/__init__.cpython-311.pyc +0 -0
  98. package/src/cli/__pycache__/__init__.cpython-313.pyc +0 -0
  99. package/src/cli/__pycache__/__init__.cpython-314.pyc +0 -0
  100. package/src/cli/__pycache__/workflow_cli.cpython-311.pyc +0 -0
  101. package/src/cli/__pycache__/workflow_cli.cpython-313.pyc +0 -0
  102. package/src/cli/__pycache__/workflow_cli.cpython-314.pyc +0 -0
  103. package/{knowledge_base → src}/cli/feedback_cli.py +10 -10
  104. package/{knowledge_base → src}/cli/generate.py +11 -11
  105. package/src/cli/index.ts +704 -0
  106. package/src/cli/platform.ts +147 -0
  107. package/src/cli/workflow_cli.py +930 -0
  108. package/{knowledge_base → src}/config/__init__.py +1 -1
  109. package/src/config/__pycache__/__init__.cpython-311.pyc +0 -0
  110. package/src/config/__pycache__/__init__.cpython-313.pyc +0 -0
  111. package/src/config/__pycache__/__init__.cpython-314.pyc +0 -0
  112. package/src/config/__pycache__/policy_config.cpython-311.pyc +0 -0
  113. package/src/config/__pycache__/policy_config.cpython-313.pyc +0 -0
  114. package/src/config/__pycache__/settings.cpython-311.pyc +0 -0
  115. package/src/config/__pycache__/settings.cpython-313.pyc +0 -0
  116. package/src/config/__pycache__/settings.cpython-314.pyc +0 -0
  117. package/src/config/policy_config.py +85 -0
  118. package/src/config/policy_rules.yaml +50 -0
  119. package/{knowledge_base → src}/config/settings.py +51 -6
  120. package/{knowledge_base → src}/connectors/__init__.py +1 -1
  121. package/src/connectors/__pycache__/__init__.cpython-311.pyc +0 -0
  122. package/src/connectors/__pycache__/__init__.cpython-313.pyc +0 -0
  123. package/src/connectors/__pycache__/__init__.cpython-314.pyc +0 -0
  124. package/src/connectors/__pycache__/base.cpython-311.pyc +0 -0
  125. package/src/connectors/__pycache__/base.cpython-313.pyc +0 -0
  126. package/src/connectors/__pycache__/base.cpython-314.pyc +0 -0
  127. package/src/connectors/__pycache__/jira_connector.cpython-311.pyc +0 -0
  128. package/src/connectors/__pycache__/jira_connector.cpython-313.pyc +0 -0
  129. package/src/connectors/__pycache__/jira_connector.cpython-314.pyc +0 -0
  130. package/src/connectors/__pycache__/query_bridge.cpython-313.pyc +0 -0
  131. package/src/connectors/__pycache__/query_bridge.cpython-314.pyc +0 -0
  132. package/src/connectors/bitbucket_connector.py +334 -0
  133. package/{knowledge_base → src}/connectors/community_connector.py +6 -6
  134. package/{knowledge_base → src}/connectors/confluence_connector.py +4 -4
  135. package/{knowledge_base → src}/connectors/jira_connector.py +7 -11
  136. package/{knowledge_base → src}/connectors/kb_igel_connector.py +6 -6
  137. package/{knowledge_base → src}/connectors/query_bridge.py +11 -11
  138. package/{knowledge_base → src}/connectors/search_backends.py +1 -1
  139. package/{knowledge_base → src}/connectors/serviceNow_connector.py +2 -2
  140. package/{knowledge_base → src}/connectors/sync_scheduler.py +12 -10
  141. package/{knowledge_base → src}/connectors/teamcity_connector.py +2 -2
  142. package/{knowledge_base → src}/connectors/testRail_connector.py +2 -2
  143. package/{knowledge_base → src}/connectors/web_fetcher.py +1 -1
  144. package/src/connectors/xray_connector.py +337 -0
  145. package/{knowledge_base → src}/core/__init__.py +1 -1
  146. package/src/core/__pycache__/__init__.cpython-311.pyc +0 -0
  147. package/src/core/__pycache__/__init__.cpython-313.pyc +0 -0
  148. package/src/core/__pycache__/__init__.cpython-314.pyc +0 -0
  149. package/src/core/__pycache__/circuit_breaker.cpython-313.pyc +0 -0
  150. package/src/core/__pycache__/circuit_breaker.cpython-314.pyc +0 -0
  151. package/src/core/__pycache__/confidence.cpython-311.pyc +0 -0
  152. package/src/core/__pycache__/confidence.cpython-313.pyc +0 -0
  153. package/src/core/__pycache__/confidence.cpython-314.pyc +0 -0
  154. package/src/core/__pycache__/context_engine.cpython-311.pyc +0 -0
  155. package/src/core/__pycache__/context_engine.cpython-313.pyc +0 -0
  156. package/src/core/__pycache__/evidence_resolver.cpython-311.pyc +0 -0
  157. package/src/core/__pycache__/evidence_resolver.cpython-313.pyc +0 -0
  158. package/src/core/__pycache__/guardrails.cpython-311.pyc +0 -0
  159. package/src/core/__pycache__/guardrails.cpython-313.pyc +0 -0
  160. package/src/core/__pycache__/hooks.cpython-311.pyc +0 -0
  161. package/src/core/__pycache__/hooks.cpython-313.pyc +0 -0
  162. package/src/core/__pycache__/intent_service.cpython-313.pyc +0 -0
  163. package/src/core/__pycache__/llm_executor.cpython-311.pyc +0 -0
  164. package/src/core/__pycache__/llm_executor.cpython-313.pyc +0 -0
  165. package/src/core/__pycache__/model_router.cpython-311.pyc +0 -0
  166. package/src/core/__pycache__/model_router.cpython-313.pyc +0 -0
  167. package/src/core/__pycache__/orchestration_contracts.cpython-311.pyc +0 -0
  168. package/src/core/__pycache__/orchestration_contracts.cpython-313.pyc +0 -0
  169. package/src/core/__pycache__/precedence.cpython-311.pyc +0 -0
  170. package/src/core/__pycache__/precedence.cpython-313.pyc +0 -0
  171. package/src/core/__pycache__/prompt_builder.cpython-311.pyc +0 -0
  172. package/src/core/__pycache__/prompt_builder.cpython-313.pyc +0 -0
  173. package/src/core/__pycache__/prompt_policy_engine.cpython-311.pyc +0 -0
  174. package/src/core/__pycache__/prompt_policy_engine.cpython-313.pyc +0 -0
  175. package/{knowledge_base → src}/core/cache.py +2 -2
  176. package/{knowledge_base → src}/core/confidence.py +2 -2
  177. package/src/core/context_engine.py +138 -0
  178. package/src/core/evidence_resolver.py +72 -0
  179. package/src/core/guardrails.py +22 -0
  180. package/src/core/hooks.py +57 -0
  181. package/src/core/intent_service.py +74 -0
  182. package/src/core/llm_executor.py +138 -0
  183. package/{knowledge_base → src}/core/logging_setup.py +1 -1
  184. package/src/core/model_router.py +246 -0
  185. package/src/core/orchestration_contracts.py +66 -0
  186. package/src/core/persistence_engine.py +159 -0
  187. package/src/core/prompt_builder.py +49 -0
  188. package/src/core/prompt_policy_engine.py +35 -0
  189. package/src/core/traceability_engine.py +56 -0
  190. package/src/db/__pycache__/__init__.cpython-311.pyc +0 -0
  191. package/src/db/__pycache__/__init__.cpython-313.pyc +0 -0
  192. package/src/db/__pycache__/__init__.cpython-314.pyc +0 -0
  193. package/src/db/__pycache__/client.cpython-311.pyc +0 -0
  194. package/src/db/__pycache__/client.cpython-313.pyc +0 -0
  195. package/src/db/__pycache__/client.cpython-314.pyc +0 -0
  196. package/src/db/__pycache__/igel_schema.cpython-311.pyc +0 -0
  197. package/src/db/__pycache__/igel_schema.cpython-313.pyc +0 -0
  198. package/src/db/__pycache__/igel_schema.cpython-314.pyc +0 -0
  199. package/src/db/__pycache__/kg_introspect.cpython-311.pyc +0 -0
  200. package/src/db/__pycache__/kg_introspect.cpython-313.pyc +0 -0
  201. package/{knowledge_base → src}/db/__pycache__/kg_introspect.cpython-314.pyc +0 -0
  202. package/{knowledge_base → src}/db/client.py +1 -1
  203. package/{knowledge_base → src}/db/connector_sync.py +1 -1
  204. package/{knowledge_base → src}/db/feedback_schema.py +2 -2
  205. package/{knowledge_base → src}/db/igel_schema.py +29 -4
  206. package/{knowledge_base → src}/db/kg_introspect.py +1 -1
  207. package/src/db/migrations.py +237 -0
  208. package/{knowledge_base → src}/db/schema.py +6 -6
  209. package/{knowledge_base → src}/deploy/Dockerfile +3 -3
  210. package/{knowledge_base → src}/deploy/feedback_automation.sh +3 -3
  211. package/{knowledge_base → src}/deploy/firecrawl-docker.sh +4 -4
  212. package/{knowledge_base → src}/deploy/igel-testgen.service +2 -2
  213. package/{knowledge_base → src}/deploy/install_reranker.sh +1 -1
  214. package/{knowledge_base → src}/deploy/requirements.txt +1 -2
  215. package/{knowledge_base → src}/deploy/run_server.sh +1 -1
  216. package/{knowledge_base → src}/docs/TEST_GENERATION_GUIDE.md +15 -15
  217. package/src/embeddings/__pycache__/__init__.cpython-311.pyc +0 -0
  218. package/src/embeddings/__pycache__/__init__.cpython-313.pyc +0 -0
  219. package/src/embeddings/__pycache__/__init__.cpython-314.pyc +0 -0
  220. package/src/embeddings/__pycache__/azure_embedder.cpython-311.pyc +0 -0
  221. package/src/embeddings/__pycache__/azure_embedder.cpython-313.pyc +0 -0
  222. package/{knowledge_base → src}/embeddings/__pycache__/azure_embedder.cpython-314.pyc +0 -0
  223. package/{knowledge_base → src}/embeddings/azure_embedder.py +10 -1
  224. package/{knowledge_base → src}/eval/__init__.py +3 -3
  225. package/{knowledge_base → src}/eval/__main__.py +7 -7
  226. package/src/eval/__pycache__/__init__.cpython-311.pyc +0 -0
  227. package/src/eval/__pycache__/__init__.cpython-313.pyc +0 -0
  228. package/src/eval/__pycache__/__init__.cpython-314.pyc +0 -0
  229. package/src/eval/__pycache__/baseline.cpython-311.pyc +0 -0
  230. package/src/eval/__pycache__/baseline.cpython-313.pyc +0 -0
  231. package/src/eval/__pycache__/baseline.cpython-314.pyc +0 -0
  232. package/src/eval/__pycache__/harness.cpython-311.pyc +0 -0
  233. package/src/eval/__pycache__/harness.cpython-313.pyc +0 -0
  234. package/src/eval/__pycache__/harness.cpython-314.pyc +0 -0
  235. package/src/eval/__pycache__/scorers.cpython-311.pyc +0 -0
  236. package/src/eval/__pycache__/scorers.cpython-313.pyc +0 -0
  237. package/src/eval/__pycache__/scorers.cpython-314.pyc +0 -0
  238. package/{knowledge_base → src}/eval/harness.py +6 -6
  239. package/{knowledge_base → src}/feedback/__init__.py +1 -1
  240. package/{knowledge_base → src}/feedback/analytics.py +1 -1
  241. package/{knowledge_base → src}/feedback/applier.py +4 -4
  242. package/{knowledge_base → src}/feedback/curator.py +2 -2
  243. package/{knowledge_base → src}/feedback/handler.py +1 -1
  244. package/src/generation/__pycache__/__init__.cpython-313.pyc +0 -0
  245. package/src/generation/__pycache__/__init__.cpython-314.pyc +0 -0
  246. package/src/generation/__pycache__/input_classifier.cpython-313.pyc +0 -0
  247. package/src/generation/__pycache__/manual_tc_parser.cpython-313.pyc +0 -0
  248. package/src/generation/__pycache__/prompts.cpython-313.pyc +0 -0
  249. package/src/generation/__pycache__/prompts.cpython-314.pyc +0 -0
  250. package/src/generation/__pycache__/test_generator.cpython-313.pyc +0 -0
  251. package/src/generation/__pycache__/test_generator.cpython-314.pyc +0 -0
  252. package/{knowledge_base → src}/generation/input_classifier.py +1 -1
  253. package/{knowledge_base → src}/generation/prompts.py +1 -1
  254. package/{knowledge_base → src}/generation/tc_transformer.py +10 -10
  255. package/{knowledge_base → src}/generation/test_generator.py +56 -10
  256. package/{knowledge_base → src}/graph_db/__init__.py +1 -1
  257. package/{knowledge_base → src}/graph_db/graphiti_client.py +2 -2
  258. package/{knowledge_base → src}/graph_db/kg_traversal.py +3 -3
  259. package/{knowledge_base → src}/graph_db/migrate_kg.py +4 -4
  260. package/{knowledge_base → src}/graph_db/neo4j_client.py +1 -1
  261. package/{knowledge_base → src}/graph_db/temporal_ingest.py +1 -1
  262. package/{knowledge_base → src}/ingestion/kg_extractor.py +6 -6
  263. package/{knowledge_base → src}/ingestion/web_ingest.py +6 -6
  264. package/src/intelligence/__pycache__/__init__.cpython-311.pyc +0 -0
  265. package/src/intelligence/__pycache__/__init__.cpython-313.pyc +0 -0
  266. package/src/intelligence/__pycache__/diff_analyzer.cpython-311.pyc +0 -0
  267. package/src/intelligence/__pycache__/diff_analyzer.cpython-313.pyc +0 -0
  268. package/src/intelligence/__pycache__/routing_engine.cpython-311.pyc +0 -0
  269. package/src/intelligence/__pycache__/routing_engine.cpython-313.pyc +0 -0
  270. package/src/intelligence/diff_analyzer.py +109 -0
  271. package/{knowledge_base → src}/intelligence/execution_ingest.py +3 -3
  272. package/src/intelligence/routing_engine.py +74 -0
  273. package/src/mcp/server.ts +384 -0
  274. package/src/memory/__init__.py +6 -0
  275. package/src/memory/__pycache__/__init__.cpython-314.pyc +0 -0
  276. package/src/memory/__pycache__/cognee_client.cpython-314.pyc +0 -0
  277. package/src/memory/__pycache__/memory_types.cpython-314.pyc +0 -0
  278. package/{knowledge_base → src}/memory/cognee_client.py +3 -3
  279. package/src/models/__pycache__/test_requirement.cpython-311.pyc +0 -0
  280. package/src/models/__pycache__/test_requirement.cpython-313.pyc +0 -0
  281. package/src/models/__pycache__/test_requirement.cpython-314.pyc +0 -0
  282. package/{knowledge_base → src}/models/test_requirement.py +12 -7
  283. package/{knowledge_base → src}/parsers/csv_parser.py +1 -1
  284. package/{knowledge_base → src}/parsers/doc_parser.py +1 -1
  285. package/{knowledge_base → src}/parsers/html_parser.py +1 -1
  286. package/{knowledge_base → src}/parsers/pdf_parser.py +1 -1
  287. package/src/project/__pycache__/__init__.cpython-311.pyc +0 -0
  288. package/src/project/__pycache__/__init__.cpython-313.pyc +0 -0
  289. package/src/project/__pycache__/ai_folder.cpython-311.pyc +0 -0
  290. package/src/project/__pycache__/ai_folder.cpython-313.pyc +0 -0
  291. package/src/project/__pycache__/context_enricher.cpython-313.pyc +0 -0
  292. package/src/project/__pycache__/context_projection_builder.cpython-311.pyc +0 -0
  293. package/src/project/__pycache__/context_projection_builder.cpython-313.pyc +0 -0
  294. package/src/project/__pycache__/context_requirement_sync.cpython-311.pyc +0 -0
  295. package/src/project/__pycache__/context_requirement_sync.cpython-313.pyc +0 -0
  296. package/src/project/ai_folder.py +602 -0
  297. package/src/project/context_enricher.py +333 -0
  298. package/src/project/context_projection_builder.py +167 -0
  299. package/src/project/context_requirement_sync.py +205 -0
  300. package/src/project/init_check.py +214 -0
  301. package/src/prompts/__pycache__/prompt_loader.cpython-313.pyc +0 -0
  302. package/src/prompts/automation_design.md +12 -0
  303. package/src/prompts/policies/automation_generation_policy.md +11 -0
  304. package/src/prompts/policies/generation_instructions.md +24 -0
  305. package/src/prompts/policies/guardrails.md +6 -0
  306. package/src/prompts/policies/traceability_policy.md +9 -0
  307. package/src/prompts/prompt_loader.py +56 -0
  308. package/src/prompts/requirement_understanding.md +17 -0
  309. package/src/prompts/scenario_generator.md +17 -0
  310. package/src/prompts/script_generator.md +13 -0
  311. package/src/prompts/test_case_generator.md +23 -0
  312. package/src/retrieval/__pycache__/__init__.cpython-311.pyc +0 -0
  313. package/src/retrieval/__pycache__/__init__.cpython-313.pyc +0 -0
  314. package/src/retrieval/__pycache__/__init__.cpython-314.pyc +0 -0
  315. package/src/retrieval/__pycache__/knowledge_graph.cpython-311.pyc +0 -0
  316. package/src/retrieval/__pycache__/knowledge_graph.cpython-313.pyc +0 -0
  317. package/src/retrieval/__pycache__/knowledge_graph.cpython-314.pyc +0 -0
  318. package/src/retrieval/__pycache__/retriever.cpython-311.pyc +0 -0
  319. package/src/retrieval/__pycache__/retriever.cpython-313.pyc +0 -0
  320. package/src/retrieval/__pycache__/retriever.cpython-314.pyc +0 -0
  321. package/src/retrieval/__pycache__/unified_query.cpython-313.pyc +0 -0
  322. package/src/retrieval/__pycache__/unified_query.cpython-314.pyc +0 -0
  323. package/{knowledge_base → src}/retrieval/context_fusion.py +3 -3
  324. package/{knowledge_base → src}/retrieval/knowledge_graph.py +4 -4
  325. package/{knowledge_base → src}/retrieval/reranker.py +2 -2
  326. package/{knowledge_base → src}/retrieval/retriever.py +11 -11
  327. package/{knowledge_base → src}/retrieval/unified_query.py +7 -7
  328. package/{knowledge_base → src}/retrieval/web_retriever.py +6 -6
  329. package/{knowledge_base → src}/validators/step_fidelity.py +1 -1
  330. package/src/vision/__init__.py +0 -0
  331. package/{knowledge_base → src}/vision/image_describer.py +1 -1
  332. package/knowledge_base/__pycache__/__init__.cpython-314.pyc +0 -0
  333. package/knowledge_base/agents/__init__.py +0 -6
  334. package/knowledge_base/agents/confidence_agent.py +0 -94
  335. package/knowledge_base/agents/feedback_agent.py +0 -56
  336. package/knowledge_base/agents/intent_agent.py +0 -76
  337. package/knowledge_base/agents/requirement_agent.py +0 -71
  338. package/knowledge_base/agents/testcase_agent.py +0 -111
  339. package/knowledge_base/agents/workflow_engine.py +0 -87
  340. package/knowledge_base/cli/generate_qcapps134.py +0 -391
  341. package/knowledge_base/cli/workflow_cli.py +0 -93
  342. package/knowledge_base/config/.env +0 -100
  343. package/knowledge_base/config/.env.example +0 -75
  344. package/knowledge_base/connectors/bitbucket_connector.py +0 -25
  345. package/knowledge_base/db/__pycache__/__init__.cpython-314.pyc +0 -0
  346. package/knowledge_base/db/__pycache__/client.cpython-314.pyc +0 -0
  347. package/knowledge_base/db/migrations.py +0 -22
  348. package/knowledge_base/embeddings/__pycache__/__init__.cpython-314.pyc +0 -0
  349. package/knowledge_base/ingestion/ingest.py +0 -346
  350. package/knowledge_base/ingestion/ingest_images.py +0 -330
  351. package/knowledge_base/memory/__init__.py +0 -6
  352. package/knowledge_base/memory/ingest_memory.py +0 -60
  353. /package/{knowledge_base → src}/__init__.py +0 -0
  354. /package/{knowledge_base → src}/__pycache__/__init__.cpython-37.pyc +0 -0
  355. /package/{knowledge_base → src}/__pycache__/__init__.cpython-38.pyc +0 -0
  356. /package/{knowledge_base → src}/__pycache__/confidence.cpython-37.pyc +0 -0
  357. /package/{knowledge_base → src}/__pycache__/config.cpython-314.pyc +0 -0
  358. /package/{knowledge_base → src}/__pycache__/config.cpython-37.pyc +0 -0
  359. /package/{knowledge_base → src}/__pycache__/config.cpython-38.pyc +0 -0
  360. /package/{knowledge_base → src}/__pycache__/context_fusion.cpython-314.pyc +0 -0
  361. /package/{knowledge_base → src}/__pycache__/context_fusion.cpython-37.pyc +0 -0
  362. /package/{knowledge_base → src}/__pycache__/feedback_analytics.cpython-37.pyc +0 -0
  363. /package/{knowledge_base → src}/__pycache__/feedback_applier.cpython-37.pyc +0 -0
  364. /package/{knowledge_base → src}/__pycache__/feedback_cli.cpython-37.pyc +0 -0
  365. /package/{knowledge_base → src}/__pycache__/feedback_curator.cpython-37.pyc +0 -0
  366. /package/{knowledge_base → src}/__pycache__/feedback_handler.cpython-37.pyc +0 -0
  367. /package/{knowledge_base → src}/__pycache__/generate.cpython-37.pyc +0 -0
  368. /package/{knowledge_base → src}/__pycache__/generate_qcapps134.cpython-37.pyc +0 -0
  369. /package/{knowledge_base → src}/__pycache__/input_classifier.cpython-314.pyc +0 -0
  370. /package/{knowledge_base → src}/__pycache__/input_classifier.cpython-37.pyc +0 -0
  371. /package/{knowledge_base → src}/__pycache__/kg_extractor.cpython-37.pyc +0 -0
  372. /package/{knowledge_base → src}/__pycache__/knowledge_graph.cpython-314.pyc +0 -0
  373. /package/{knowledge_base → src}/__pycache__/knowledge_graph.cpython-37.pyc +0 -0
  374. /package/{knowledge_base → src}/__pycache__/manual_tc_parser.cpython-314.pyc +0 -0
  375. /package/{knowledge_base → src}/__pycache__/manual_tc_parser.cpython-37.pyc +0 -0
  376. /package/{knowledge_base → src}/__pycache__/precedence.cpython-37.pyc +0 -0
  377. /package/{knowledge_base → src}/__pycache__/prompts.cpython-314.pyc +0 -0
  378. /package/{knowledge_base → src}/__pycache__/prompts.cpython-37.pyc +0 -0
  379. /package/{knowledge_base → src}/__pycache__/reranker.cpython-314.pyc +0 -0
  380. /package/{knowledge_base → src}/__pycache__/reranker.cpython-37.pyc +0 -0
  381. /package/{knowledge_base → src}/__pycache__/retrieval_debug.cpython-314.pyc +0 -0
  382. /package/{knowledge_base → src}/__pycache__/retrieval_debug.cpython-37.pyc +0 -0
  383. /package/{knowledge_base → src}/__pycache__/retriever.cpython-314.pyc +0 -0
  384. /package/{knowledge_base → src}/__pycache__/retriever.cpython-37.pyc +0 -0
  385. /package/{knowledge_base → src}/__pycache__/server.cpython-37.pyc +0 -0
  386. /package/{knowledge_base → src}/__pycache__/tc_transformer.cpython-314.pyc +0 -0
  387. /package/{knowledge_base → src}/__pycache__/tc_transformer.cpython-37.pyc +0 -0
  388. /package/{knowledge_base → src}/__pycache__/test_generator.cpython-314.pyc +0 -0
  389. /package/{knowledge_base → src}/__pycache__/test_generator.cpython-37.pyc +0 -0
  390. /package/{knowledge_base → src}/agents/__pycache__/__init__.cpython-37.pyc +0 -0
  391. /package/{knowledge_base → src}/agents/__pycache__/__init__.cpython-38.pyc +0 -0
  392. /package/{knowledge_base → src}/agents/__pycache__/fusion_agent.cpython-37.pyc +0 -0
  393. /package/{knowledge_base → src}/agents/__pycache__/fusion_agent.cpython-38.pyc +0 -0
  394. /package/{knowledge_base → src}/agents/__pycache__/graph.cpython-37.pyc +0 -0
  395. /package/{knowledge_base → src}/agents/__pycache__/graph.cpython-38.pyc +0 -0
  396. /package/{knowledge_base → src}/agents/__pycache__/healing_agent.cpython-37.pyc +0 -0
  397. /package/{knowledge_base → src}/agents/__pycache__/intent_agent.cpython-37.pyc +0 -0
  398. /package/{knowledge_base → src}/agents/__pycache__/intent_agent.cpython-38.pyc +0 -0
  399. /package/{knowledge_base → src}/agents/__pycache__/kg_agent.cpython-37.pyc +0 -0
  400. /package/{knowledge_base → src}/agents/__pycache__/kg_agent.cpython-38.pyc +0 -0
  401. /package/{knowledge_base → src}/agents/__pycache__/memory_agent.cpython-37.pyc +0 -0
  402. /package/{knowledge_base → src}/agents/__pycache__/memory_agent.cpython-38.pyc +0 -0
  403. /package/{knowledge_base → src}/agents/__pycache__/rca_agent.cpython-37.pyc +0 -0
  404. /package/{knowledge_base → src}/agents/__pycache__/reflection_agent.cpython-37.pyc +0 -0
  405. /package/{knowledge_base → src}/agents/__pycache__/reflection_agent.cpython-38.pyc +0 -0
  406. /package/{knowledge_base → src}/agents/__pycache__/regression_agent.cpython-37.pyc +0 -0
  407. /package/{knowledge_base → src}/agents/__pycache__/retrieval_agent.cpython-37.pyc +0 -0
  408. /package/{knowledge_base → src}/agents/__pycache__/retrieval_agent.cpython-38.pyc +0 -0
  409. /package/{knowledge_base → src}/agents/__pycache__/script_agent.cpython-37.pyc +0 -0
  410. /package/{knowledge_base → src}/agents/__pycache__/script_agent.cpython-38.pyc +0 -0
  411. /package/{knowledge_base → src}/agents/__pycache__/state.cpython-37.pyc +0 -0
  412. /package/{knowledge_base → src}/agents/__pycache__/state.cpython-38.pyc +0 -0
  413. /package/{knowledge_base → src}/agents/__pycache__/temporal_agent.cpython-37.pyc +0 -0
  414. /package/{knowledge_base → src}/agents/__pycache__/temporal_agent.cpython-38.pyc +0 -0
  415. /package/{knowledge_base → src}/agents/__pycache__/validation_agent.cpython-37.pyc +0 -0
  416. /package/{knowledge_base → src}/agents/__pycache__/validation_agent.cpython-38.pyc +0 -0
  417. /package/{knowledge_base → src}/agents/state.py +0 -0
  418. /package/{knowledge_base → src}/alembic/__pycache__/env.cpython-37.pyc +0 -0
  419. /package/{knowledge_base → src}/alembic/__pycache__/env.cpython-38.pyc +0 -0
  420. /package/{knowledge_base → src}/alembic/versions/.gitkeep +0 -0
  421. /package/{knowledge_base → src}/alembic/versions/001_phase0_feedback.py +0 -0
  422. /package/{knowledge_base → src}/alembic/versions/002_feedback_promotions.py +0 -0
  423. /package/{knowledge_base → src}/alembic/versions/003_enterprise_hardening.py +0 -0
  424. /package/{knowledge_base → src}/alembic/versions/__pycache__/001_phase0_feedback.cpython-37.pyc +0 -0
  425. /package/{knowledge_base → src}/alembic/versions/__pycache__/001_phase0_feedback.cpython-38.pyc +0 -0
  426. /package/{knowledge_base → src}/alembic/versions/__pycache__/002_feedback_promotions.cpython-37.pyc +0 -0
  427. /package/{knowledge_base → src}/alembic/versions/__pycache__/002_feedback_promotions.cpython-38.pyc +0 -0
  428. /package/{knowledge_base → src}/api/__init__.py +0 -0
  429. /package/{knowledge_base → src}/api/__pycache__/__init__.cpython-37.pyc +0 -0
  430. /package/{knowledge_base → src}/api/__pycache__/__init__.cpython-38.pyc +0 -0
  431. /package/{knowledge_base → src}/api/__pycache__/middleware.cpython-38.pyc +0 -0
  432. /package/{knowledge_base → src}/api/__pycache__/server.cpython-37.pyc +0 -0
  433. /package/{knowledge_base → src}/api/__pycache__/server.cpython-38.pyc +0 -0
  434. /package/{knowledge_base → src}/chunking/__init__.py +0 -0
  435. /package/{knowledge_base → src}/chunking/__pycache__/__init__.cpython-37.pyc +0 -0
  436. /package/{knowledge_base → src}/chunking/__pycache__/__init__.cpython-38.pyc +0 -0
  437. /package/{knowledge_base → src}/chunking/__pycache__/chunker.cpython-37.pyc +0 -0
  438. /package/{knowledge_base → src}/chunking/__pycache__/chunker.cpython-38.pyc +0 -0
  439. /package/{knowledge_base → src}/chunking/__pycache__/validators.cpython-37.pyc +0 -0
  440. /package/{knowledge_base → src}/chunking/__pycache__/validators.cpython-38.pyc +0 -0
  441. /package/{knowledge_base → src}/chunking/validators.py +0 -0
  442. /package/{knowledge_base → src}/cli/__init__.py +0 -0
  443. /package/{knowledge_base → src}/cli/__pycache__/__init__.cpython-37.pyc +0 -0
  444. /package/{knowledge_base → src}/cli/__pycache__/__init__.cpython-38.pyc +0 -0
  445. /package/{knowledge_base → src}/cli/__pycache__/feedback_cli.cpython-37.pyc +0 -0
  446. /package/{knowledge_base → src}/cli/__pycache__/feedback_cli.cpython-38.pyc +0 -0
  447. /package/{knowledge_base → src}/cli/__pycache__/generate.cpython-37.pyc +0 -0
  448. /package/{knowledge_base → src}/cli/__pycache__/generate.cpython-38.pyc +0 -0
  449. /package/{knowledge_base → src}/cli/__pycache__/generate_qcapps134.cpython-37.pyc +0 -0
  450. /package/{knowledge_base → src}/config/__pycache__/__init__.cpython-37.pyc +0 -0
  451. /package/{knowledge_base → src}/config/__pycache__/__init__.cpython-38.pyc +0 -0
  452. /package/{knowledge_base → src}/config/__pycache__/settings.cpython-37.pyc +0 -0
  453. /package/{knowledge_base → src}/config/__pycache__/settings.cpython-38.pyc +0 -0
  454. /package/{knowledge_base → src}/connectors/__pycache__/__init__.cpython-37.pyc +0 -0
  455. /package/{knowledge_base → src}/connectors/__pycache__/__init__.cpython-38.pyc +0 -0
  456. /package/{knowledge_base → src}/connectors/__pycache__/base.cpython-37.pyc +0 -0
  457. /package/{knowledge_base → src}/connectors/__pycache__/base.cpython-38.pyc +0 -0
  458. /package/{knowledge_base → src}/connectors/__pycache__/bitbucket_connector.cpython-37.pyc +0 -0
  459. /package/{knowledge_base → src}/connectors/__pycache__/bitbucket_connector.cpython-38.pyc +0 -0
  460. /package/{knowledge_base → src}/connectors/__pycache__/community_connector.cpython-38.pyc +0 -0
  461. /package/{knowledge_base → src}/connectors/__pycache__/confluence_connector.cpython-37.pyc +0 -0
  462. /package/{knowledge_base → src}/connectors/__pycache__/confluence_connector.cpython-38.pyc +0 -0
  463. /package/{knowledge_base → src}/connectors/__pycache__/jira_connector.cpython-37.pyc +0 -0
  464. /package/{knowledge_base → src}/connectors/__pycache__/jira_connector.cpython-38.pyc +0 -0
  465. /package/{knowledge_base → src}/connectors/__pycache__/kb_igel_connector.cpython-38.pyc +0 -0
  466. /package/{knowledge_base → src}/connectors/__pycache__/playwright_fetcher.cpython-38.pyc +0 -0
  467. /package/{knowledge_base → src}/connectors/__pycache__/query_bridge.cpython-38.pyc +0 -0
  468. /package/{knowledge_base → src}/connectors/__pycache__/search_backends.cpython-38.pyc +0 -0
  469. /package/{knowledge_base → src}/connectors/__pycache__/serviceNow_connector.cpython-37.pyc +0 -0
  470. /package/{knowledge_base → src}/connectors/__pycache__/serviceNow_connector.cpython-38.pyc +0 -0
  471. /package/{knowledge_base → src}/connectors/__pycache__/sync_scheduler.cpython-37.pyc +0 -0
  472. /package/{knowledge_base → src}/connectors/__pycache__/sync_scheduler.cpython-38.pyc +0 -0
  473. /package/{knowledge_base → src}/connectors/__pycache__/teamcity_connector.cpython-37.pyc +0 -0
  474. /package/{knowledge_base → src}/connectors/__pycache__/teamcity_connector.cpython-38.pyc +0 -0
  475. /package/{knowledge_base → src}/connectors/__pycache__/testRail_connector.cpython-37.pyc +0 -0
  476. /package/{knowledge_base → src}/connectors/__pycache__/testRail_connector.cpython-38.pyc +0 -0
  477. /package/{knowledge_base → src}/connectors/__pycache__/web_fetcher.cpython-38.pyc +0 -0
  478. /package/{knowledge_base → src}/connectors/base.py +0 -0
  479. /package/{knowledge_base → src}/connectors/playwright_fetcher.py +0 -0
  480. /package/{knowledge_base → src}/core/__pycache__/__init__.cpython-37.pyc +0 -0
  481. /package/{knowledge_base → src}/core/__pycache__/__init__.cpython-38.pyc +0 -0
  482. /package/{knowledge_base → src}/core/__pycache__/cache.cpython-38.pyc +0 -0
  483. /package/{knowledge_base → src}/core/__pycache__/circuit_breaker.cpython-38.pyc +0 -0
  484. /package/{knowledge_base → src}/core/__pycache__/confidence.cpython-37.pyc +0 -0
  485. /package/{knowledge_base → src}/core/__pycache__/confidence.cpython-38.pyc +0 -0
  486. /package/{knowledge_base → src}/core/__pycache__/logging_setup.cpython-38.pyc +0 -0
  487. /package/{knowledge_base → src}/core/__pycache__/metrics.cpython-38.pyc +0 -0
  488. /package/{knowledge_base → src}/core/__pycache__/precedence.cpython-37.pyc +0 -0
  489. /package/{knowledge_base → src}/core/__pycache__/precedence.cpython-38.pyc +0 -0
  490. /package/{knowledge_base → src}/core/__pycache__/request_context.cpython-38.pyc +0 -0
  491. /package/{knowledge_base → src}/core/circuit_breaker.py +0 -0
  492. /package/{knowledge_base → src}/core/metrics.py +0 -0
  493. /package/{knowledge_base → src}/core/precedence.py +0 -0
  494. /package/{knowledge_base → src}/core/request_context.py +0 -0
  495. /package/{knowledge_base → src}/db/__init__.py +0 -0
  496. /package/{knowledge_base → src}/db/__pycache__/__init__.cpython-37.pyc +0 -0
  497. /package/{knowledge_base → src}/db/__pycache__/__init__.cpython-38.pyc +0 -0
  498. /package/{knowledge_base → src}/db/__pycache__/client.cpython-37.pyc +0 -0
  499. /package/{knowledge_base → src}/db/__pycache__/client.cpython-38.pyc +0 -0
  500. /package/{knowledge_base → src}/db/__pycache__/connector_sync.cpython-38.pyc +0 -0
  501. /package/{knowledge_base → src}/db/__pycache__/feedback_schema.cpython-37.pyc +0 -0
  502. /package/{knowledge_base → src}/db/__pycache__/feedback_schema.cpython-38.pyc +0 -0
  503. /package/{knowledge_base → src}/db/__pycache__/kg_introspect.cpython-37.pyc +0 -0
  504. /package/{knowledge_base → src}/db/__pycache__/kg_introspect.cpython-38.pyc +0 -0
  505. /package/{knowledge_base → src}/db/__pycache__/schema.cpython-37.pyc +0 -0
  506. /package/{knowledge_base → src}/db/__pycache__/schema.cpython-38.pyc +0 -0
  507. /package/{knowledge_base → src}/embeddings/__init__.py +0 -0
  508. /package/{knowledge_base → src}/embeddings/__pycache__/__init__.cpython-37.pyc +0 -0
  509. /package/{knowledge_base → src}/embeddings/__pycache__/__init__.cpython-38.pyc +0 -0
  510. /package/{knowledge_base → src}/embeddings/__pycache__/azure_embedder.cpython-37.pyc +0 -0
  511. /package/{knowledge_base → src}/embeddings/__pycache__/azure_embedder.cpython-38.pyc +0 -0
  512. /package/{knowledge_base → src}/eval/__pycache__/__init__.cpython-37.pyc +0 -0
  513. /package/{knowledge_base → src}/eval/__pycache__/__init__.cpython-38.pyc +0 -0
  514. /package/{knowledge_base → src}/eval/__pycache__/__main__.cpython-37.pyc +0 -0
  515. /package/{knowledge_base → src}/eval/__pycache__/baseline.cpython-37.pyc +0 -0
  516. /package/{knowledge_base → src}/eval/__pycache__/baseline.cpython-38.pyc +0 -0
  517. /package/{knowledge_base → src}/eval/__pycache__/harness.cpython-37.pyc +0 -0
  518. /package/{knowledge_base → src}/eval/__pycache__/harness.cpython-38.pyc +0 -0
  519. /package/{knowledge_base → src}/eval/__pycache__/scorers.cpython-37.pyc +0 -0
  520. /package/{knowledge_base → src}/eval/__pycache__/scorers.cpython-38.pyc +0 -0
  521. /package/{knowledge_base → src}/eval/baseline.py +0 -0
  522. /package/{knowledge_base → src}/eval/queries_50.json +0 -0
  523. /package/{knowledge_base → src}/eval/scorers.py +0 -0
  524. /package/{knowledge_base → src}/exemplars/README.md +0 -0
  525. /package/{knowledge_base → src}/exemplars/__pycache__/pytest_reference_snippet.cpython-37.pyc +0 -0
  526. /package/{knowledge_base → src}/exemplars/gold_manual_concise_snippet.md +0 -0
  527. /package/{knowledge_base → src}/exemplars/gold_manual_detailed_snippet.md +0 -0
  528. /package/{knowledge_base → src}/exemplars/pytest_reference_snippet.py +0 -0
  529. /package/{knowledge_base → src}/feedback/__pycache__/__init__.cpython-37.pyc +0 -0
  530. /package/{knowledge_base → src}/feedback/__pycache__/__init__.cpython-38.pyc +0 -0
  531. /package/{knowledge_base → src}/feedback/__pycache__/analytics.cpython-37.pyc +0 -0
  532. /package/{knowledge_base → src}/feedback/__pycache__/analytics.cpython-38.pyc +0 -0
  533. /package/{knowledge_base → src}/feedback/__pycache__/applier.cpython-37.pyc +0 -0
  534. /package/{knowledge_base → src}/feedback/__pycache__/applier.cpython-38.pyc +0 -0
  535. /package/{knowledge_base → src}/feedback/__pycache__/curator.cpython-37.pyc +0 -0
  536. /package/{knowledge_base → src}/feedback/__pycache__/curator.cpython-38.pyc +0 -0
  537. /package/{knowledge_base → src}/feedback/__pycache__/handler.cpython-37.pyc +0 -0
  538. /package/{knowledge_base → src}/feedback/__pycache__/handler.cpython-38.pyc +0 -0
  539. /package/{knowledge_base → src}/generation/__init__.py +0 -0
  540. /package/{knowledge_base → src}/generation/__pycache__/__init__.cpython-37.pyc +0 -0
  541. /package/{knowledge_base → src}/generation/__pycache__/__init__.cpython-38.pyc +0 -0
  542. /package/{knowledge_base → src}/generation/__pycache__/input_classifier.cpython-37.pyc +0 -0
  543. /package/{knowledge_base → src}/generation/__pycache__/input_classifier.cpython-38.pyc +0 -0
  544. /package/{knowledge_base → src}/generation/__pycache__/manual_tc_parser.cpython-37.pyc +0 -0
  545. /package/{knowledge_base → src}/generation/__pycache__/manual_tc_parser.cpython-38.pyc +0 -0
  546. /package/{knowledge_base → src}/generation/__pycache__/prompts.cpython-37.pyc +0 -0
  547. /package/{knowledge_base → src}/generation/__pycache__/prompts.cpython-38.pyc +0 -0
  548. /package/{knowledge_base → src}/generation/__pycache__/tc_transformer.cpython-37.pyc +0 -0
  549. /package/{knowledge_base → src}/generation/__pycache__/test_generator.cpython-37.pyc +0 -0
  550. /package/{knowledge_base → src}/generation/__pycache__/test_generator.cpython-38.pyc +0 -0
  551. /package/{knowledge_base → src}/generation/manual_tc_parser.py +0 -0
  552. /package/{knowledge_base → src}/graph_db/__pycache__/__init__.cpython-37.pyc +0 -0
  553. /package/{knowledge_base → src}/graph_db/__pycache__/__init__.cpython-38.pyc +0 -0
  554. /package/{knowledge_base → src}/graph_db/__pycache__/graphiti_client.cpython-37.pyc +0 -0
  555. /package/{knowledge_base → src}/graph_db/__pycache__/kg_traversal.cpython-37.pyc +0 -0
  556. /package/{knowledge_base → src}/graph_db/__pycache__/migrate_kg.cpython-37.pyc +0 -0
  557. /package/{knowledge_base → src}/graph_db/__pycache__/neo4j_client.cpython-37.pyc +0 -0
  558. /package/{knowledge_base → src}/graph_db/__pycache__/neo4j_client.cpython-38.pyc +0 -0
  559. /package/{knowledge_base → src}/graph_db/__pycache__/schema.cpython-37.pyc +0 -0
  560. /package/{knowledge_base → src}/graph_db/__pycache__/temporal_ingest.cpython-37.pyc +0 -0
  561. /package/{knowledge_base → src}/graph_db/schema.py +0 -0
  562. /package/{knowledge_base → src}/ingestion/__init__.py +0 -0
  563. /package/{knowledge_base → src}/ingestion/__pycache__/__init__.cpython-37.pyc +0 -0
  564. /package/{knowledge_base → src}/ingestion/__pycache__/__init__.cpython-38.pyc +0 -0
  565. /package/{knowledge_base → src}/ingestion/__pycache__/ingest.cpython-37.pyc +0 -0
  566. /package/{knowledge_base → src}/ingestion/__pycache__/ingest.cpython-38.pyc +0 -0
  567. /package/{knowledge_base → src}/ingestion/__pycache__/ingest_images.cpython-37.pyc +0 -0
  568. /package/{knowledge_base → src}/ingestion/__pycache__/ingest_images.cpython-38.pyc +0 -0
  569. /package/{knowledge_base → src}/ingestion/__pycache__/kg_extractor.cpython-37.pyc +0 -0
  570. /package/{knowledge_base → src}/ingestion/__pycache__/kg_extractor.cpython-38.pyc +0 -0
  571. /package/{knowledge_base → src}/ingestion/__pycache__/web_ingest.cpython-38.pyc +0 -0
  572. /package/{knowledge_base → src}/intelligence/__init__.py +0 -0
  573. /package/{knowledge_base → src}/intelligence/__pycache__/__init__.cpython-37.pyc +0 -0
  574. /package/{knowledge_base → src}/intelligence/__pycache__/execution_ingest.cpython-37.pyc +0 -0
  575. /package/{knowledge_base → src}/intelligence/__pycache__/predictive_engine.cpython-37.pyc +0 -0
  576. /package/{knowledge_base → src}/intelligence/__pycache__/risk_scorer.cpython-37.pyc +0 -0
  577. /package/{knowledge_base → src}/intelligence/predictive_engine.py +0 -0
  578. /package/{knowledge_base → src}/intelligence/risk_scorer.py +0 -0
  579. /package/{knowledge_base → src}/memory/__pycache__/__init__.cpython-37.pyc +0 -0
  580. /package/{knowledge_base → src}/memory/__pycache__/__init__.cpython-38.pyc +0 -0
  581. /package/{knowledge_base → src}/memory/__pycache__/cognee_client.cpython-37.pyc +0 -0
  582. /package/{knowledge_base → src}/memory/__pycache__/cognee_client.cpython-38.pyc +0 -0
  583. /package/{knowledge_base → src}/memory/__pycache__/ingest_memory.cpython-37.pyc +0 -0
  584. /package/{knowledge_base → src}/memory/__pycache__/memory_types.cpython-37.pyc +0 -0
  585. /package/{knowledge_base → src}/memory/__pycache__/memory_types.cpython-38.pyc +0 -0
  586. /package/{knowledge_base → src}/memory/memory_types.py +0 -0
  587. /package/{knowledge_base → src}/parsers/__init__.py +0 -0
  588. /package/{knowledge_base → src}/parsers/__pycache__/__init__.cpython-37.pyc +0 -0
  589. /package/{knowledge_base → src}/parsers/__pycache__/__init__.cpython-38.pyc +0 -0
  590. /package/{knowledge_base → src}/parsers/__pycache__/csv_parser.cpython-37.pyc +0 -0
  591. /package/{knowledge_base → src}/parsers/__pycache__/csv_parser.cpython-38.pyc +0 -0
  592. /package/{knowledge_base → src}/parsers/__pycache__/doc_parser.cpython-37.pyc +0 -0
  593. /package/{knowledge_base → src}/parsers/__pycache__/doc_parser.cpython-38.pyc +0 -0
  594. /package/{knowledge_base → src}/parsers/__pycache__/html_parser.cpython-38.pyc +0 -0
  595. /package/{knowledge_base → src}/parsers/__pycache__/image_extractor.cpython-37.pyc +0 -0
  596. /package/{knowledge_base → src}/parsers/__pycache__/image_extractor.cpython-38.pyc +0 -0
  597. /package/{knowledge_base → src}/parsers/__pycache__/markdown_parser.cpython-37.pyc +0 -0
  598. /package/{knowledge_base → src}/parsers/__pycache__/markdown_parser.cpython-38.pyc +0 -0
  599. /package/{knowledge_base → src}/parsers/__pycache__/pdf_parser.cpython-37.pyc +0 -0
  600. /package/{knowledge_base → src}/parsers/__pycache__/pdf_parser.cpython-38.pyc +0 -0
  601. /package/{knowledge_base → src}/parsers/image_extractor.py +0 -0
  602. /package/{knowledge_base → src}/parsers/markdown_parser.py +0 -0
  603. /package/{knowledge_base/vision → src/project}/__init__.py +0 -0
  604. /package/{knowledge_base → src}/retrieval/__init__.py +0 -0
  605. /package/{knowledge_base → src}/retrieval/__pycache__/__init__.cpython-37.pyc +0 -0
  606. /package/{knowledge_base → src}/retrieval/__pycache__/__init__.cpython-38.pyc +0 -0
  607. /package/{knowledge_base → src}/retrieval/__pycache__/context_fusion.cpython-37.pyc +0 -0
  608. /package/{knowledge_base → src}/retrieval/__pycache__/context_fusion.cpython-38.pyc +0 -0
  609. /package/{knowledge_base → src}/retrieval/__pycache__/knowledge_graph.cpython-37.pyc +0 -0
  610. /package/{knowledge_base → src}/retrieval/__pycache__/knowledge_graph.cpython-38.pyc +0 -0
  611. /package/{knowledge_base → src}/retrieval/__pycache__/reranker.cpython-37.pyc +0 -0
  612. /package/{knowledge_base → src}/retrieval/__pycache__/reranker.cpython-38.pyc +0 -0
  613. /package/{knowledge_base → src}/retrieval/__pycache__/retrieval_debug.cpython-37.pyc +0 -0
  614. /package/{knowledge_base → src}/retrieval/__pycache__/retrieval_debug.cpython-38.pyc +0 -0
  615. /package/{knowledge_base → src}/retrieval/__pycache__/retriever.cpython-37.pyc +0 -0
  616. /package/{knowledge_base → src}/retrieval/__pycache__/retriever.cpython-38.pyc +0 -0
  617. /package/{knowledge_base → src}/retrieval/__pycache__/unified_query.cpython-38.pyc +0 -0
  618. /package/{knowledge_base → src}/retrieval/__pycache__/web_retriever.cpython-38.pyc +0 -0
  619. /package/{knowledge_base → src}/retrieval/retrieval_debug.py +0 -0
  620. /package/{knowledge_base → src}/validators/__init__.py +0 -0
  621. /package/{knowledge_base → src}/validators/__pycache__/__init__.cpython-314.pyc +0 -0
  622. /package/{knowledge_base → src}/validators/__pycache__/__init__.cpython-37.pyc +0 -0
  623. /package/{knowledge_base → src}/validators/__pycache__/step_fidelity.cpython-314.pyc +0 -0
  624. /package/{knowledge_base → src}/validators/__pycache__/step_fidelity.cpython-37.pyc +0 -0
  625. /package/{knowledge_base → src}/vision/__pycache__/__init__.cpython-37.pyc +0 -0
  626. /package/{knowledge_base → src}/vision/__pycache__/__init__.cpython-38.pyc +0 -0
  627. /package/{knowledge_base → src}/vision/__pycache__/image_describer.cpython-37.pyc +0 -0
  628. /package/{knowledge_base → src}/vision/__pycache__/image_describer.cpython-38.pyc +0 -0
@@ -0,0 +1,602 @@
1
+ """ai_folder.py — .ai/ folder scaffolding and system state cache management.
2
+
3
+ Ownership rules:
4
+ Human-editable (committed to Git):
5
+ .ai/project.yaml — repo metadata, test/page dir layout, framework type
6
+ .ai/context.md — free-text project description used in prompts
7
+ .ai/framework_rules.md — coding conventions and style hints
8
+
9
+ System cache (gitignored, rebuilt from DB on init/status):
10
+ .ai/system/project_state.json — asset counts, requirement counts, last sync
11
+ .ai/system/sync_state.json — last indexed commit and file list
12
+ .ai/system/generation_history.json — last 50 generation records
13
+ .ai/system/model_preferences.json — task→model routing snapshot from DB
14
+
15
+ Key invariant: .ai/system/*.json files are ONLY written by rebuild_system_state_from_db().
16
+ They are never written during generation. The model router reads model_preferences.json
17
+ as a local read-through cache; the DB (igel_generation_history) is always authoritative.
18
+ """
19
+ from __future__ import annotations
20
+
21
+ import json
22
+ import logging
23
+ from dataclasses import asdict, is_dataclass
24
+ from pathlib import Path
25
+ from typing import Any
26
+
27
+ import yaml
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+ # Markers used when walking up the directory tree to find the repo root
32
+ _ROOT_MARKERS = ["pyproject.toml", "setup.py", "setup.cfg", "conftest.py", ".git"]
33
+
34
+ _AI_SYSTEM_DIR_NAME = ".ai/system"
35
+ _GITIGNORE_ENTRIES = [
36
+ ".ai/system/",
37
+ ".ai/system/*",
38
+ ]
39
+
40
+ # ── repo root detection ────────────────────────────────────────────────────────
41
+
42
+ def detect_repo_root(start: Path | None = None) -> Path:
43
+ """Walk up from start (default: cwd) until a repo-root marker is found.
44
+
45
+ Returns the directory containing the marker, or the original start directory
46
+ if no marker is found (graceful degradation).
47
+ """
48
+ current = (start or Path.cwd()).resolve()
49
+ for candidate in [current, *current.parents]:
50
+ if any((candidate / m).exists() for m in _ROOT_MARKERS):
51
+ return candidate
52
+ logger.warning("Could not detect repo root from %s; using cwd", current)
53
+ return current
54
+
55
+
56
+ def detect_framework_layout(repo_root: Path) -> dict:
57
+ """Auto-detect common automation framework directories.
58
+
59
+ Returns a dict of role → relative-path for directories that actually exist.
60
+ """
61
+ candidates = {
62
+ "tests_dir": ["tests", "test", "specs"],
63
+ "pages_dir": ["pages", "page_objects", "pom"],
64
+ "fixtures_dir": ["fixtures", "conftest", "test_fixtures"],
65
+ "utils_dir": ["utils", "helpers", "utilities"],
66
+ "api_dir": ["api_clients", "api", "services"],
67
+ "data_dir": ["testdata", "test_data", "data"],
68
+ }
69
+ layout: dict[str, str] = {}
70
+ for role, names in candidates.items():
71
+ for name in names:
72
+ candidate = repo_root / name
73
+ if candidate.is_dir():
74
+ layout[role] = name
75
+ break
76
+ return layout
77
+
78
+
79
+ # ── scaffold ───────────────────────────────────────────────────────────────────
80
+
81
+ def scaffold_ai_folder(repo_root: Path) -> None:
82
+ """Create the .ai/ folder tree with stub files (idempotent).
83
+
84
+ Human-editable files are created with helpful placeholder content if they
85
+ don't already exist. System files are created as empty JSON objects.
86
+ Adds .ai/system/ to .gitignore.
87
+ """
88
+ ai_dir = repo_root / ".ai"
89
+ system_dir = ai_dir / "system"
90
+ context_dir = ai_dir / "context"
91
+ framework_dir = ai_dir / "framework"
92
+ policy_dir = ai_dir / "policy"
93
+ governance_dir = ai_dir / "governance"
94
+ feedback_dir = ai_dir / "feedback"
95
+ artifacts_dir = ai_dir / "artifacts"
96
+ system_dir.mkdir(parents=True, exist_ok=True)
97
+ context_dir.mkdir(parents=True, exist_ok=True)
98
+ framework_dir.mkdir(parents=True, exist_ok=True)
99
+ policy_dir.mkdir(parents=True, exist_ok=True)
100
+ governance_dir.mkdir(parents=True, exist_ok=True)
101
+ feedback_dir.mkdir(parents=True, exist_ok=True)
102
+ (artifacts_dir / "requirements").mkdir(parents=True, exist_ok=True)
103
+ (artifacts_dir / "automation-plans").mkdir(parents=True, exist_ok=True)
104
+ (artifacts_dir / "index").mkdir(parents=True, exist_ok=True)
105
+
106
+ layout = detect_framework_layout(repo_root)
107
+
108
+ # Human-editable stubs (only created if absent; never overwritten)
109
+ _write_if_absent(
110
+ ai_dir / "project.yaml",
111
+ yaml.dump(
112
+ {
113
+ "repo_name": repo_root.name,
114
+ "framework_type": "pytest",
115
+ "tests_dir": layout.get("tests_dir", "tests"),
116
+ "pages_dir": layout.get("pages_dir", "pages"),
117
+ "fixtures_dir": layout.get("fixtures_dir", "fixtures"),
118
+ "utils_dir": layout.get("utils_dir", "utils"),
119
+ "api_dir": layout.get("api_dir", "api_clients"),
120
+ },
121
+ default_flow_style=False,
122
+ ),
123
+ )
124
+ _write_if_absent(
125
+ ai_dir / "context.md",
126
+ f"# {repo_root.name} — IGEL QE Project Context\n\n"
127
+ "Describe the product under test, key features, and any domain knowledge\n"
128
+ "the AI should use when generating test cases and automation scripts.\n",
129
+ )
130
+ _write_if_absent(
131
+ ai_dir / "framework_rules.md",
132
+ "# Automation Framework Rules\n\n"
133
+ "Add coding conventions, naming patterns, fixture usage rules,\n"
134
+ "and any constraints the script generator must respect.\n\n"
135
+ "Examples:\n"
136
+ "- Page objects must inherit from `BasePage`\n"
137
+ "- All tests must use the `browser` fixture from `conftest.py`\n"
138
+ "- Use `assert_that()` not bare `assert` for readability\n",
139
+ )
140
+
141
+ # Structured context and framework metadata
142
+ _write_if_absent(
143
+ context_dir / "project.md",
144
+ f"# {repo_root.name} Project Context\n\n"
145
+ "Document business domain context and terminology here.\n",
146
+ )
147
+ _write_if_absent(
148
+ context_dir / "domain.md",
149
+ "# Domain Notes\n\n"
150
+ "Capture product domain behaviors, assumptions, and edge cases.\n",
151
+ )
152
+ _write_if_absent(
153
+ context_dir / "constraints.yaml",
154
+ yaml.dump(
155
+ {
156
+ "missing_asset_policy": {
157
+ "create": False,
158
+ "propose": True,
159
+ "require_review": True,
160
+ }
161
+ },
162
+ default_flow_style=False,
163
+ ),
164
+ )
165
+ _write_if_absent(
166
+ framework_dir / "manifest.yaml",
167
+ yaml.dump(
168
+ {
169
+ "framework": "pytest",
170
+ "paths": {
171
+ "tests": layout.get("tests_dir", "tests"),
172
+ "pages": layout.get("pages_dir", "pages"),
173
+ "fixtures": layout.get("fixtures_dir", "fixtures"),
174
+ "utils": layout.get("utils_dir", "utils"),
175
+ },
176
+ },
177
+ default_flow_style=False,
178
+ ),
179
+ )
180
+ _write_if_absent(policy_dir / "profiles.yaml", "default_profile: safe-default\n")
181
+ _write_if_absent(
182
+ governance_dir / "approval_rules.yaml",
183
+ "require_human_approval: true\n"
184
+ "min_confidence_for_auto_publish: 0.8\n",
185
+ )
186
+ _write_if_absent(
187
+ governance_dir / "generation_rules.yaml",
188
+ "enforce_policy_engine: true\n"
189
+ "enforce_agent_guardrails: true\n",
190
+ )
191
+ _write_if_absent(feedback_dir / "README.md", "Store feedback exports and reconciliation notes.\n")
192
+
193
+ # Artifact index stubs
194
+ _write_if_absent(artifacts_dir / "index" / "by_jira.json", "{}\n")
195
+ _write_if_absent(artifacts_dir / "index" / "by_test_reqid.json", "{}\n")
196
+
197
+ # System state stubs (empty objects — rebuilt from DB by rebuild_system_state_from_db)
198
+ for name in ("project_state", "sync_state", "generation_history", "model_preferences"):
199
+ _write_if_absent(system_dir / f"{name}.json", "{}\n")
200
+
201
+ # Gitignore
202
+ _update_gitignore(repo_root)
203
+
204
+ logger.info("Scaffolded .ai/ folder at %s", ai_dir)
205
+
206
+
207
+ def _write_if_absent(path: Path, content: str) -> None:
208
+ if not path.exists():
209
+ path.write_text(content, encoding="utf-8")
210
+ logger.debug("Created %s", path)
211
+
212
+
213
+ def _update_gitignore(repo_root: Path) -> None:
214
+ gitignore = repo_root / ".gitignore"
215
+ existing = gitignore.read_text(encoding="utf-8") if gitignore.exists() else ""
216
+ additions = [e for e in _GITIGNORE_ENTRIES if e not in existing]
217
+ if additions:
218
+ with gitignore.open("a", encoding="utf-8") as f:
219
+ f.write("\n# IGEL QE Agent — auto-managed system state\n")
220
+ for entry in additions:
221
+ f.write(f"{entry}\n")
222
+ logger.info("Updated .gitignore with .ai/system/ entries")
223
+
224
+
225
+ # ── project.yaml read/write ────────────────────────────────────────────────────
226
+
227
+ def read_project_yaml(repo_root: Path) -> dict:
228
+ path = repo_root / ".ai" / "project.yaml"
229
+ if not path.exists():
230
+ return {}
231
+ try:
232
+ with path.open(encoding="utf-8") as f:
233
+ return yaml.safe_load(f) or {}
234
+ except Exception as e:
235
+ logger.warning("Failed to read project.yaml: %s", e)
236
+ return {}
237
+
238
+
239
+ def write_project_yaml(repo_root: Path, data: dict) -> None:
240
+ path = repo_root / ".ai" / "project.yaml"
241
+ path.parent.mkdir(parents=True, exist_ok=True)
242
+ with path.open("w", encoding="utf-8") as f:
243
+ yaml.dump(data, f, default_flow_style=False)
244
+
245
+
246
+ def artifact_requirement_dir(repo_root: Path, jira_key: str, test_reqid: str | None = None) -> Path:
247
+ """Return .ai artifact path for a requirement/test_reqid."""
248
+ reqid = (test_reqid or jira_key).strip()
249
+ return repo_root / ".ai" / "artifacts" / "requirements" / jira_key / reqid
250
+
251
+
252
+ def write_testcase_artifacts(
253
+ repo_root: Path,
254
+ jira_key: str,
255
+ generated_cases: list,
256
+ approved_cases: list,
257
+ *,
258
+ test_reqid: str | None = None,
259
+ requirement_hash: str | None = None,
260
+ framework_hash: str | None = None,
261
+ ) -> dict:
262
+ """Write generated and approved testcase artifacts for deterministic script input reuse."""
263
+ req_dir = artifact_requirement_dir(repo_root, jira_key, test_reqid)
264
+ req_dir.mkdir(parents=True, exist_ok=True)
265
+
266
+ gen_payload = {
267
+ "jira_key": jira_key,
268
+ "test_reqid": test_reqid or jira_key,
269
+ "count": len(generated_cases),
270
+ "cases": [_to_dict(tc) for tc in generated_cases],
271
+ }
272
+ approved_payload = {
273
+ "jira_key": jira_key,
274
+ "test_reqid": test_reqid or jira_key,
275
+ "count": len(approved_cases),
276
+ "cases": [_to_dict(tc) for tc in approved_cases],
277
+ "staleness": {
278
+ "requirement_hash": requirement_hash,
279
+ "framework_hash": framework_hash,
280
+ "approved_content_hash": compute_cases_content_hash(approved_cases),
281
+ },
282
+ }
283
+
284
+ _write_system_json(req_dir / "testcases.generated.json", gen_payload)
285
+ _write_system_json(req_dir / "testcases.approved.json", approved_payload)
286
+
287
+ # Keep index files for fast lookup
288
+ idx_jira = repo_root / ".ai" / "artifacts" / "index" / "by_jira.json"
289
+ idx_reqid = repo_root / ".ai" / "artifacts" / "index" / "by_test_reqid.json"
290
+ _merge_index(idx_jira, jira_key, str(req_dir))
291
+ _merge_index(idx_reqid, test_reqid or jira_key, str(req_dir))
292
+
293
+ return {
294
+ "artifact_dir": str(req_dir),
295
+ "generated_count": len(generated_cases),
296
+ "approved_count": len(approved_cases),
297
+ }
298
+
299
+
300
+ def read_approved_testcase_artifact(repo_root: Path, jira_key: str, test_reqid: str | None = None) -> dict:
301
+ req_dir = artifact_requirement_dir(repo_root, jira_key, test_reqid)
302
+ path = req_dir / "testcases.approved.json"
303
+ if not path.exists():
304
+ return {}
305
+ try:
306
+ return json.loads(path.read_text(encoding="utf-8"))
307
+ except Exception as e:
308
+ logger.warning("Failed to read approved testcase artifact %s: %s", path, e)
309
+ return {}
310
+
311
+
312
+ def write_requirement_plan_artifact(
313
+ repo_root: Path,
314
+ jira_key: str,
315
+ scenarios_with_rules: list,
316
+ resolved_context: Any,
317
+ source_report: Any,
318
+ *,
319
+ test_reqid: str | None = None,
320
+ requirement_hash: str | None = None,
321
+ ) -> dict:
322
+ """Persist requirement-planning output (scenarios/business rules + resolved
323
+ context + source report) so generate_test_cases can reuse it without re-planning."""
324
+ req_dir = artifact_requirement_dir(repo_root, jira_key, test_reqid)
325
+ req_dir.mkdir(parents=True, exist_ok=True)
326
+
327
+ scenarios_payload = [_to_dict(sr) for sr in scenarios_with_rules]
328
+ payload = {
329
+ "jira_key": jira_key,
330
+ "test_reqid": test_reqid or jira_key,
331
+ "scenario_count": len(scenarios_with_rules),
332
+ "scenarios": scenarios_payload,
333
+ "resolved_context": _to_dict(resolved_context),
334
+ "source_report": _to_dict(source_report),
335
+ "staleness": {
336
+ "requirement_hash": requirement_hash,
337
+ "plan_content_hash": _json_hash(scenarios_payload),
338
+ },
339
+ }
340
+ _write_system_json(req_dir / "plan.json", payload)
341
+
342
+ idx_jira = repo_root / ".ai" / "artifacts" / "index" / "by_jira.json"
343
+ idx_reqid = repo_root / ".ai" / "artifacts" / "index" / "by_test_reqid.json"
344
+ _merge_index(idx_jira, jira_key, str(req_dir))
345
+ _merge_index(idx_reqid, test_reqid or jira_key, str(req_dir))
346
+
347
+ return {"artifact_dir": str(req_dir), "scenario_count": len(scenarios_with_rules)}
348
+
349
+
350
+ def read_plan_artifact(repo_root: Path, jira_key: str, test_reqid: str | None = None) -> dict:
351
+ req_dir = artifact_requirement_dir(repo_root, jira_key, test_reqid)
352
+ path = req_dir / "plan.json"
353
+ if not path.exists():
354
+ return {}
355
+ try:
356
+ return json.loads(path.read_text(encoding="utf-8"))
357
+ except Exception as e:
358
+ logger.warning("Failed to read plan artifact %s: %s", path, e)
359
+ return {}
360
+
361
+
362
+ def write_approval_artifact(
363
+ repo_root: Path,
364
+ jira_key: str,
365
+ stage: str,
366
+ payload: dict,
367
+ *,
368
+ test_reqid: str | None = None,
369
+ ) -> dict:
370
+ """Persist approval status for a workflow stage.
371
+
372
+ Example stages: testcase_plan, automation_plan.
373
+ """
374
+ req_dir = artifact_requirement_dir(repo_root, jira_key, test_reqid)
375
+ req_dir.mkdir(parents=True, exist_ok=True)
376
+ safe_stage = stage.strip().replace(" ", "_").lower()
377
+ path = req_dir / f"approval.{safe_stage}.json"
378
+ _write_system_json(path, payload)
379
+ return {"artifact_path": str(path), "stage": safe_stage}
380
+
381
+
382
+ def read_approval_artifact(
383
+ repo_root: Path,
384
+ jira_key: str,
385
+ stage: str,
386
+ *,
387
+ test_reqid: str | None = None,
388
+ ) -> dict:
389
+ req_dir = artifact_requirement_dir(repo_root, jira_key, test_reqid)
390
+ safe_stage = stage.strip().replace(" ", "_").lower()
391
+ path = req_dir / f"approval.{safe_stage}.json"
392
+ if not path.exists():
393
+ return {}
394
+ try:
395
+ return json.loads(path.read_text(encoding="utf-8"))
396
+ except Exception as e:
397
+ logger.warning("Failed to read approval artifact %s: %s", path, e)
398
+ return {}
399
+
400
+
401
+ def artifact_automation_plan_dir(repo_root: Path, jira_key: str, test_reqid: str | None = None) -> Path:
402
+ """Return .ai artifact path for an automation plan."""
403
+ reqid = (test_reqid or jira_key).strip()
404
+ return repo_root / ".ai" / "artifacts" / "automation-plans" / jira_key / reqid
405
+
406
+
407
+ def write_automation_plan_artifact(
408
+ repo_root: Path,
409
+ jira_key: str,
410
+ plan: Any,
411
+ *,
412
+ test_reqid: str | None = None,
413
+ approved_content_hash: str | None = None,
414
+ ) -> dict:
415
+ """Persist a designed AutomationPlan so generate_automation can reuse it without redesigning."""
416
+ plan_dir = artifact_automation_plan_dir(repo_root, jira_key, test_reqid)
417
+ plan_dir.mkdir(parents=True, exist_ok=True)
418
+ payload = {
419
+ "jira_key": jira_key,
420
+ "test_reqid": test_reqid or jira_key,
421
+ "plan": _to_dict(plan),
422
+ "staleness": {"approved_content_hash": approved_content_hash},
423
+ }
424
+ _write_system_json(plan_dir / "plan.json", payload)
425
+ return {"artifact_dir": str(plan_dir)}
426
+
427
+
428
+ def read_automation_plan_artifact(repo_root: Path, jira_key: str, test_reqid: str | None = None) -> dict:
429
+ path = artifact_automation_plan_dir(repo_root, jira_key, test_reqid) / "plan.json"
430
+ if not path.exists():
431
+ return {}
432
+ try:
433
+ return json.loads(path.read_text(encoding="utf-8"))
434
+ except Exception as e:
435
+ logger.warning("Failed to read automation plan artifact %s: %s", path, e)
436
+ return {}
437
+
438
+
439
+ def _to_dict(obj: Any) -> dict:
440
+ if hasattr(obj, "model_dump"):
441
+ return obj.model_dump()
442
+ if is_dataclass(obj) and not isinstance(obj, type):
443
+ return asdict(obj)
444
+ if isinstance(obj, dict):
445
+ return obj
446
+ return {"value": str(obj)}
447
+
448
+
449
+ def _json_hash(data: Any) -> str:
450
+ import hashlib
451
+
452
+ raw = json.dumps(data, sort_keys=True, default=str).encode("utf-8")
453
+ return hashlib.sha256(raw).hexdigest()
454
+
455
+
456
+ def compute_cases_content_hash(cases: list) -> str:
457
+ """Deterministic content hash of a list of test-case-like objects, for staleness comparisons."""
458
+ return _json_hash([_to_dict(c) for c in cases])
459
+
460
+
461
+ def _merge_index(path: Path, key: str, value: str) -> None:
462
+ path.parent.mkdir(parents=True, exist_ok=True)
463
+ existing = {}
464
+ if path.exists():
465
+ try:
466
+ existing = json.loads(path.read_text(encoding="utf-8"))
467
+ except Exception:
468
+ existing = {}
469
+ existing[key] = value
470
+ path.write_text(json.dumps(existing, indent=2) + "\n", encoding="utf-8")
471
+
472
+
473
+ # ── system state (DB read-through cache) ──────────────────────────────────────
474
+
475
+ def rebuild_system_state_from_db(repo_root: Path) -> dict:
476
+ """Query the DB and write all .ai/system/*.json cache files.
477
+
478
+ This is the ONLY function that writes to .ai/system/.
479
+ It must be called explicitly (from igel-qe init or igel-qe status).
480
+ It is never called during test generation.
481
+ Returns a summary dict for display.
482
+ """
483
+ system_dir = repo_root / ".ai" / "system"
484
+ system_dir.mkdir(parents=True, exist_ok=True)
485
+
486
+ summary: dict[str, Any] = {}
487
+
488
+ try:
489
+ from src.db.client import get_conn
490
+
491
+ with get_conn() as conn:
492
+ with conn.cursor() as cur:
493
+ # Project state
494
+ project_state = _query_project_state(cur)
495
+ summary["project_state"] = project_state
496
+ _write_system_json(system_dir / "project_state.json", project_state)
497
+
498
+ # Sync state
499
+ sync_state = _query_sync_state(cur)
500
+ summary["sync_state"] = sync_state
501
+ _write_system_json(system_dir / "sync_state.json", sync_state)
502
+
503
+ # Generation history (last 50 rows)
504
+ gen_history = _query_generation_history(cur)
505
+ summary["generation_history_count"] = len(gen_history)
506
+ _write_system_json(system_dir / "generation_history.json", {"records": gen_history})
507
+
508
+ # Model preferences (task→best model from history)
509
+ model_prefs = _build_model_preferences(cur)
510
+ summary["model_preferences"] = model_prefs
511
+ _write_system_json(system_dir / "model_preferences.json", model_prefs)
512
+
513
+ logger.info("Rebuilt .ai/system/ state from DB")
514
+ except Exception as e:
515
+ logger.error("Failed to rebuild system state: %s", e)
516
+ summary["error"] = str(e)
517
+
518
+ return summary
519
+
520
+
521
+ def _query_project_state(cur) -> dict:
522
+ state: dict[str, Any] = {}
523
+ for table, key in [
524
+ ("igel_asset_registry", "asset_count"),
525
+ ("igel_requirements", "requirement_count"),
526
+ ("igel_generated_testcases", "testcase_count"),
527
+ ("igel_automation_scripts", "script_count"),
528
+ ]:
529
+ try:
530
+ cur.execute(f"SELECT COUNT(*) FROM {table}")
531
+ row = cur.fetchone()
532
+ state[key] = row[0] if row else 0
533
+ except Exception:
534
+ state[key] = 0
535
+ return state
536
+
537
+
538
+ def _query_sync_state(cur) -> dict:
539
+ try:
540
+ cur.execute("""
541
+ SELECT source, last_synced_at, status
542
+ FROM connector_sync_state
543
+ ORDER BY last_synced_at DESC NULLS LAST
544
+ """)
545
+ rows = cur.fetchall()
546
+ return {
547
+ "connectors": [
548
+ {"source": r[0], "last_synced_at": str(r[1]) if r[1] else None, "status": r[2]}
549
+ for r in rows
550
+ ]
551
+ }
552
+ except Exception:
553
+ return {}
554
+
555
+
556
+ def _query_generation_history(cur) -> list:
557
+ try:
558
+ cur.execute("""
559
+ SELECT jira_key, action, model_used, task_type, tokens_in, tokens_out,
560
+ duration_ms, quality_score, routed_by, created_at
561
+ FROM igel_generation_history
562
+ ORDER BY created_at DESC
563
+ LIMIT 50
564
+ """)
565
+ cols = ["jira_key", "action", "model_used", "task_type", "tokens_in",
566
+ "tokens_out", "duration_ms", "quality_score", "routed_by", "created_at"]
567
+ return [dict(zip(cols, [str(v) if v is not None else None for v in row])) for row in cur.fetchall()]
568
+ except Exception:
569
+ return []
570
+
571
+
572
+ def _build_model_preferences(cur) -> dict:
573
+ """Aggregate igel_generation_history to get the best-performing model per task_type."""
574
+ try:
575
+ cur.execute("""
576
+ SELECT task_type, model_used,
577
+ AVG(quality_score) AS avg_quality,
578
+ COUNT(*) AS call_count
579
+ FROM igel_generation_history
580
+ WHERE task_type IS NOT NULL AND quality_score IS NOT NULL
581
+ GROUP BY task_type, model_used
582
+ ORDER BY task_type, avg_quality DESC NULLS LAST
583
+ """)
584
+ prefs: dict[str, dict] = {}
585
+ for task_type, model_used, avg_quality, call_count in cur.fetchall():
586
+ # First row per task_type is the best (ORDER BY avg_quality DESC)
587
+ if task_type not in prefs:
588
+ prefs[task_type] = {
589
+ "recommended_model": model_used,
590
+ "avg_quality": round(float(avg_quality), 4) if avg_quality else None,
591
+ "call_count": call_count,
592
+ }
593
+ return prefs
594
+ except Exception:
595
+ return {}
596
+
597
+
598
+ def _write_system_json(path: Path, data: Any) -> None:
599
+ try:
600
+ path.write_text(json.dumps(data, indent=2, default=str) + "\n", encoding="utf-8")
601
+ except Exception as e:
602
+ logger.warning("Failed to write %s: %s", path, e)