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.
- package/dist/cli/index.js +38 -0
- package/dist/mcp/server.js +104 -0
- package/knowledge_base/__init__.py +3 -0
- package/knowledge_base/__pycache__/__init__.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/__pycache__/confidence.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/config.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/config.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/config.cpython-38.pyc +0 -0
- package/knowledge_base/__pycache__/context_fusion.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/context_fusion.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/feedback_analytics.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/feedback_applier.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/feedback_cli.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/feedback_curator.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/feedback_handler.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/generate.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/generate_qcapps134.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/input_classifier.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/input_classifier.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/kg_extractor.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/knowledge_graph.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/knowledge_graph.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/manual_tc_parser.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/manual_tc_parser.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/precedence.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/prompts.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/prompts.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/reranker.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/reranker.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/retrieval_debug.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/retrieval_debug.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/retriever.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/retriever.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/server.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/tc_transformer.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/tc_transformer.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/test_generator.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/test_generator.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__init__.py +6 -0
- package/knowledge_base/agents/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/fusion_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/fusion_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/graph.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/graph.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/healing_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/intent_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/intent_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/kg_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/kg_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/memory_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/memory_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/rca_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/reflection_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/reflection_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/regression_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/retrieval_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/retrieval_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/script_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/script_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/state.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/state.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/temporal_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/temporal_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/validation_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/validation_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/automation_design_agent.py +123 -0
- package/knowledge_base/agents/code_intelligence_agent.py +147 -0
- package/knowledge_base/agents/confidence_agent.py +94 -0
- package/knowledge_base/agents/execution_validation_agent.py +129 -0
- package/knowledge_base/agents/feedback_agent.py +56 -0
- package/knowledge_base/agents/fusion_agent.py +113 -0
- package/knowledge_base/agents/graph.py +152 -0
- package/knowledge_base/agents/healing_agent.py +62 -0
- package/knowledge_base/agents/intent_agent.py +76 -0
- package/knowledge_base/agents/kg_agent.py +91 -0
- package/knowledge_base/agents/memory_agent.py +62 -0
- package/knowledge_base/agents/rca_agent.py +53 -0
- package/knowledge_base/agents/reflection_agent.py +62 -0
- package/knowledge_base/agents/regression_agent.py +81 -0
- package/knowledge_base/agents/requirement_agent.py +71 -0
- package/knowledge_base/agents/retrieval_agent.py +66 -0
- package/knowledge_base/agents/scenario_agent.py +81 -0
- package/knowledge_base/agents/script_agent.py +121 -0
- package/knowledge_base/agents/script_generator_agent.py +77 -0
- package/knowledge_base/agents/state.py +53 -0
- package/knowledge_base/agents/temporal_agent.py +48 -0
- package/knowledge_base/agents/testcase_agent.py +111 -0
- package/knowledge_base/agents/validation_agent.py +49 -0
- package/knowledge_base/agents/workflow_engine.py +87 -0
- package/knowledge_base/alembic/README.md +104 -0
- package/knowledge_base/alembic/__pycache__/env.cpython-37.pyc +0 -0
- package/knowledge_base/alembic/__pycache__/env.cpython-38.pyc +0 -0
- package/knowledge_base/alembic/env.py +76 -0
- package/knowledge_base/alembic/script.py.mako +5 -0
- package/knowledge_base/alembic/versions/.gitkeep +26 -0
- package/knowledge_base/alembic/versions/001_phase0_feedback.py +122 -0
- package/knowledge_base/alembic/versions/002_feedback_promotions.py +60 -0
- package/knowledge_base/alembic/versions/003_enterprise_hardening.py +74 -0
- package/knowledge_base/alembic/versions/__pycache__/001_phase0_feedback.cpython-37.pyc +0 -0
- package/knowledge_base/alembic/versions/__pycache__/001_phase0_feedback.cpython-38.pyc +0 -0
- package/knowledge_base/alembic/versions/__pycache__/002_feedback_promotions.cpython-37.pyc +0 -0
- package/knowledge_base/alembic/versions/__pycache__/002_feedback_promotions.cpython-38.pyc +0 -0
- package/knowledge_base/api/__init__.py +1 -0
- package/knowledge_base/api/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/api/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/api/__pycache__/middleware.cpython-38.pyc +0 -0
- package/knowledge_base/api/__pycache__/server.cpython-37.pyc +0 -0
- package/knowledge_base/api/__pycache__/server.cpython-38.pyc +0 -0
- package/knowledge_base/api/middleware.py +78 -0
- package/knowledge_base/api/server.py +778 -0
- package/knowledge_base/chunking/__init__.py +0 -0
- package/knowledge_base/chunking/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/chunking/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/chunking/__pycache__/chunker.cpython-37.pyc +0 -0
- package/knowledge_base/chunking/__pycache__/chunker.cpython-38.pyc +0 -0
- package/knowledge_base/chunking/__pycache__/validators.cpython-37.pyc +0 -0
- package/knowledge_base/chunking/__pycache__/validators.cpython-38.pyc +0 -0
- package/knowledge_base/chunking/chunker.py +402 -0
- package/knowledge_base/chunking/validators.py +144 -0
- package/knowledge_base/cli/__init__.py +1 -0
- package/knowledge_base/cli/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/cli/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/cli/__pycache__/feedback_cli.cpython-37.pyc +0 -0
- package/knowledge_base/cli/__pycache__/feedback_cli.cpython-38.pyc +0 -0
- package/knowledge_base/cli/__pycache__/generate.cpython-37.pyc +0 -0
- package/knowledge_base/cli/__pycache__/generate.cpython-38.pyc +0 -0
- package/knowledge_base/cli/__pycache__/generate_qcapps134.cpython-37.pyc +0 -0
- package/knowledge_base/cli/feedback_cli.py +121 -0
- package/knowledge_base/cli/generate.py +308 -0
- package/knowledge_base/cli/generate_qcapps134.py +391 -0
- package/knowledge_base/config/.env +100 -0
- package/knowledge_base/config/.env.example +75 -0
- package/knowledge_base/config/__init__.py +5 -0
- package/knowledge_base/config/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/config/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/config/__pycache__/settings.cpython-37.pyc +0 -0
- package/knowledge_base/config/__pycache__/settings.cpython-38.pyc +0 -0
- package/knowledge_base/config/settings.py +280 -0
- package/knowledge_base/connectors/__init__.py +5 -0
- package/knowledge_base/connectors/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/base.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/base.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/bitbucket_connector.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/bitbucket_connector.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/community_connector.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/confluence_connector.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/confluence_connector.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/jira_connector.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/jira_connector.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/kb_igel_connector.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/playwright_fetcher.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/query_bridge.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/search_backends.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/serviceNow_connector.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/serviceNow_connector.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/sync_scheduler.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/sync_scheduler.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/teamcity_connector.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/teamcity_connector.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/testRail_connector.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/testRail_connector.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/web_fetcher.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/base.py +44 -0
- package/knowledge_base/connectors/bitbucket_connector.py +25 -0
- package/knowledge_base/connectors/community_connector.py +112 -0
- package/knowledge_base/connectors/confluence_connector.py +165 -0
- package/knowledge_base/connectors/jira_connector.py +174 -0
- package/knowledge_base/connectors/kb_igel_connector.py +145 -0
- package/knowledge_base/connectors/playwright_fetcher.py +50 -0
- package/knowledge_base/connectors/query_bridge.py +170 -0
- package/knowledge_base/connectors/search_backends.py +368 -0
- package/knowledge_base/connectors/serviceNow_connector.py +25 -0
- package/knowledge_base/connectors/sync_scheduler.py +111 -0
- package/knowledge_base/connectors/teamcity_connector.py +25 -0
- package/knowledge_base/connectors/testRail_connector.py +25 -0
- package/knowledge_base/connectors/web_fetcher.py +280 -0
- package/knowledge_base/core/__init__.py +8 -0
- package/knowledge_base/core/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/core/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/core/__pycache__/cache.cpython-38.pyc +0 -0
- package/knowledge_base/core/__pycache__/circuit_breaker.cpython-38.pyc +0 -0
- package/knowledge_base/core/__pycache__/confidence.cpython-37.pyc +0 -0
- package/knowledge_base/core/__pycache__/confidence.cpython-38.pyc +0 -0
- package/knowledge_base/core/__pycache__/logging_setup.cpython-38.pyc +0 -0
- package/knowledge_base/core/__pycache__/metrics.cpython-38.pyc +0 -0
- package/knowledge_base/core/__pycache__/precedence.cpython-37.pyc +0 -0
- package/knowledge_base/core/__pycache__/precedence.cpython-38.pyc +0 -0
- package/knowledge_base/core/__pycache__/request_context.cpython-38.pyc +0 -0
- package/knowledge_base/core/cache.py +98 -0
- package/knowledge_base/core/circuit_breaker.py +33 -0
- package/knowledge_base/core/confidence.py +254 -0
- package/knowledge_base/core/logging_setup.py +39 -0
- package/knowledge_base/core/metrics.py +63 -0
- package/knowledge_base/core/precedence.py +354 -0
- package/knowledge_base/core/request_context.py +54 -0
- package/knowledge_base/db/__init__.py +0 -0
- package/knowledge_base/db/__pycache__/__init__.cpython-314.pyc +0 -0
- package/knowledge_base/db/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/db/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/db/__pycache__/client.cpython-314.pyc +0 -0
- package/knowledge_base/db/__pycache__/client.cpython-37.pyc +0 -0
- package/knowledge_base/db/__pycache__/client.cpython-38.pyc +0 -0
- package/knowledge_base/db/__pycache__/connector_sync.cpython-38.pyc +0 -0
- package/knowledge_base/db/__pycache__/feedback_schema.cpython-37.pyc +0 -0
- package/knowledge_base/db/__pycache__/feedback_schema.cpython-38.pyc +0 -0
- package/knowledge_base/db/__pycache__/kg_introspect.cpython-314.pyc +0 -0
- package/knowledge_base/db/__pycache__/kg_introspect.cpython-37.pyc +0 -0
- package/knowledge_base/db/__pycache__/kg_introspect.cpython-38.pyc +0 -0
- package/knowledge_base/db/__pycache__/schema.cpython-37.pyc +0 -0
- package/knowledge_base/db/__pycache__/schema.cpython-38.pyc +0 -0
- package/knowledge_base/db/client.py +100 -0
- package/knowledge_base/db/connector_sync.py +43 -0
- package/knowledge_base/db/feedback_schema.py +548 -0
- package/knowledge_base/db/igel_schema.py +150 -0
- package/knowledge_base/db/kg_introspect.py +116 -0
- package/knowledge_base/db/migrations.py +22 -0
- package/knowledge_base/db/schema.py +649 -0
- package/knowledge_base/deploy/Dockerfile +23 -0
- package/knowledge_base/deploy/feedback_automation.sh +18 -0
- package/knowledge_base/deploy/firecrawl-docker.sh +50 -0
- package/knowledge_base/deploy/igel-testgen.service +26 -0
- package/knowledge_base/deploy/install_reranker.sh +92 -0
- package/knowledge_base/deploy/requirements.txt +68 -0
- package/knowledge_base/deploy/run_server.sh +35 -0
- package/knowledge_base/docs/TEST_GENERATION_GUIDE.md +174 -0
- package/knowledge_base/embeddings/__init__.py +0 -0
- package/knowledge_base/embeddings/__pycache__/__init__.cpython-314.pyc +0 -0
- package/knowledge_base/embeddings/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/embeddings/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/embeddings/__pycache__/azure_embedder.cpython-314.pyc +0 -0
- package/knowledge_base/embeddings/__pycache__/azure_embedder.cpython-37.pyc +0 -0
- package/knowledge_base/embeddings/__pycache__/azure_embedder.cpython-38.pyc +0 -0
- package/knowledge_base/embeddings/azure_embedder.py +99 -0
- package/knowledge_base/eval/__init__.py +33 -0
- package/knowledge_base/eval/__main__.py +172 -0
- package/knowledge_base/eval/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/eval/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/eval/__pycache__/__main__.cpython-37.pyc +0 -0
- package/knowledge_base/eval/__pycache__/baseline.cpython-37.pyc +0 -0
- package/knowledge_base/eval/__pycache__/baseline.cpython-38.pyc +0 -0
- package/knowledge_base/eval/__pycache__/harness.cpython-37.pyc +0 -0
- package/knowledge_base/eval/__pycache__/harness.cpython-38.pyc +0 -0
- package/knowledge_base/eval/__pycache__/scorers.cpython-37.pyc +0 -0
- package/knowledge_base/eval/__pycache__/scorers.cpython-38.pyc +0 -0
- package/knowledge_base/eval/baseline.py +213 -0
- package/knowledge_base/eval/harness.py +400 -0
- package/knowledge_base/eval/queries_50.json +302 -0
- package/knowledge_base/eval/scorers.py +494 -0
- package/knowledge_base/exemplars/README.md +7 -0
- package/knowledge_base/exemplars/__pycache__/pytest_reference_snippet.cpython-37.pyc +0 -0
- package/knowledge_base/exemplars/gold_manual_concise_snippet.md +8 -0
- package/knowledge_base/exemplars/gold_manual_detailed_snippet.md +7 -0
- package/knowledge_base/exemplars/pytest_reference_snippet.py +37 -0
- package/knowledge_base/feedback/__init__.py +10 -0
- package/knowledge_base/feedback/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/analytics.cpython-37.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/analytics.cpython-38.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/applier.cpython-37.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/applier.cpython-38.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/curator.cpython-37.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/curator.cpython-38.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/handler.cpython-37.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/handler.cpython-38.pyc +0 -0
- package/knowledge_base/feedback/analytics.py +72 -0
- package/knowledge_base/feedback/applier.py +93 -0
- package/knowledge_base/feedback/curator.py +49 -0
- package/knowledge_base/feedback/handler.py +151 -0
- package/knowledge_base/generation/__init__.py +5 -0
- package/knowledge_base/generation/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/generation/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/generation/__pycache__/input_classifier.cpython-37.pyc +0 -0
- package/knowledge_base/generation/__pycache__/input_classifier.cpython-38.pyc +0 -0
- package/knowledge_base/generation/__pycache__/manual_tc_parser.cpython-37.pyc +0 -0
- package/knowledge_base/generation/__pycache__/manual_tc_parser.cpython-38.pyc +0 -0
- package/knowledge_base/generation/__pycache__/prompts.cpython-37.pyc +0 -0
- package/knowledge_base/generation/__pycache__/prompts.cpython-38.pyc +0 -0
- package/knowledge_base/generation/__pycache__/tc_transformer.cpython-37.pyc +0 -0
- package/knowledge_base/generation/__pycache__/test_generator.cpython-37.pyc +0 -0
- package/knowledge_base/generation/__pycache__/test_generator.cpython-38.pyc +0 -0
- package/knowledge_base/generation/input_classifier.py +148 -0
- package/knowledge_base/generation/manual_tc_parser.py +180 -0
- package/knowledge_base/generation/prompts.py +755 -0
- package/knowledge_base/generation/tc_transformer.py +368 -0
- package/knowledge_base/generation/test_generator.py +553 -0
- package/knowledge_base/graph_db/__init__.py +5 -0
- package/knowledge_base/graph_db/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/graph_db/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/graph_db/__pycache__/graphiti_client.cpython-37.pyc +0 -0
- package/knowledge_base/graph_db/__pycache__/kg_traversal.cpython-37.pyc +0 -0
- package/knowledge_base/graph_db/__pycache__/migrate_kg.cpython-37.pyc +0 -0
- package/knowledge_base/graph_db/__pycache__/neo4j_client.cpython-37.pyc +0 -0
- package/knowledge_base/graph_db/__pycache__/neo4j_client.cpython-38.pyc +0 -0
- package/knowledge_base/graph_db/__pycache__/schema.cpython-37.pyc +0 -0
- package/knowledge_base/graph_db/__pycache__/temporal_ingest.cpython-37.pyc +0 -0
- package/knowledge_base/graph_db/graphiti_client.py +127 -0
- package/knowledge_base/graph_db/kg_traversal.py +192 -0
- package/knowledge_base/graph_db/migrate_kg.py +93 -0
- package/knowledge_base/graph_db/neo4j_client.py +116 -0
- package/knowledge_base/graph_db/schema.py +22 -0
- package/knowledge_base/graph_db/temporal_ingest.py +59 -0
- package/knowledge_base/ingestion/__init__.py +1 -0
- package/knowledge_base/ingestion/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/ingestion/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/ingestion/__pycache__/ingest.cpython-37.pyc +0 -0
- package/knowledge_base/ingestion/__pycache__/ingest.cpython-38.pyc +0 -0
- package/knowledge_base/ingestion/__pycache__/ingest_images.cpython-37.pyc +0 -0
- package/knowledge_base/ingestion/__pycache__/ingest_images.cpython-38.pyc +0 -0
- package/knowledge_base/ingestion/__pycache__/kg_extractor.cpython-37.pyc +0 -0
- package/knowledge_base/ingestion/__pycache__/kg_extractor.cpython-38.pyc +0 -0
- package/knowledge_base/ingestion/__pycache__/web_ingest.cpython-38.pyc +0 -0
- package/knowledge_base/ingestion/ingest.py +346 -0
- package/knowledge_base/ingestion/ingest_images.py +330 -0
- package/knowledge_base/ingestion/kg_extractor.py +358 -0
- package/knowledge_base/ingestion/web_ingest.py +83 -0
- package/knowledge_base/intelligence/__init__.py +1 -0
- package/knowledge_base/intelligence/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/intelligence/__pycache__/execution_ingest.cpython-37.pyc +0 -0
- package/knowledge_base/intelligence/__pycache__/predictive_engine.cpython-37.pyc +0 -0
- package/knowledge_base/intelligence/__pycache__/risk_scorer.cpython-37.pyc +0 -0
- package/knowledge_base/intelligence/execution_ingest.py +34 -0
- package/knowledge_base/intelligence/predictive_engine.py +7 -0
- package/knowledge_base/intelligence/risk_scorer.py +8 -0
- package/knowledge_base/memory/__init__.py +6 -0
- package/knowledge_base/memory/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/memory/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/memory/__pycache__/cognee_client.cpython-37.pyc +0 -0
- package/knowledge_base/memory/__pycache__/cognee_client.cpython-38.pyc +0 -0
- package/knowledge_base/memory/__pycache__/ingest_memory.cpython-37.pyc +0 -0
- package/knowledge_base/memory/__pycache__/memory_types.cpython-37.pyc +0 -0
- package/knowledge_base/memory/__pycache__/memory_types.cpython-38.pyc +0 -0
- package/knowledge_base/memory/cognee_client.py +164 -0
- package/knowledge_base/memory/ingest_memory.py +60 -0
- package/knowledge_base/memory/memory_types.py +23 -0
- package/knowledge_base/models/test_requirement.py +84 -0
- package/knowledge_base/parsers/__init__.py +0 -0
- package/knowledge_base/parsers/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/csv_parser.cpython-37.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/csv_parser.cpython-38.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/doc_parser.cpython-37.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/doc_parser.cpython-38.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/html_parser.cpython-38.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/image_extractor.cpython-37.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/image_extractor.cpython-38.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/markdown_parser.cpython-37.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/markdown_parser.cpython-38.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/pdf_parser.cpython-37.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/pdf_parser.cpython-38.pyc +0 -0
- package/knowledge_base/parsers/csv_parser.py +126 -0
- package/knowledge_base/parsers/doc_parser.py +176 -0
- package/knowledge_base/parsers/html_parser.py +151 -0
- package/knowledge_base/parsers/image_extractor.py +370 -0
- package/knowledge_base/parsers/markdown_parser.py +116 -0
- package/knowledge_base/parsers/pdf_parser.py +178 -0
- package/knowledge_base/retrieval/__init__.py +1 -0
- package/knowledge_base/retrieval/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/context_fusion.cpython-37.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/context_fusion.cpython-38.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/knowledge_graph.cpython-37.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/knowledge_graph.cpython-38.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/reranker.cpython-37.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/reranker.cpython-38.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/retrieval_debug.cpython-37.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/retrieval_debug.cpython-38.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/retriever.cpython-37.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/retriever.cpython-38.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/unified_query.cpython-38.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/web_retriever.cpython-38.pyc +0 -0
- package/knowledge_base/retrieval/context_fusion.py +264 -0
- package/knowledge_base/retrieval/knowledge_graph.py +267 -0
- package/knowledge_base/retrieval/reranker.py +308 -0
- package/knowledge_base/retrieval/retrieval_debug.py +69 -0
- package/knowledge_base/retrieval/retriever.py +885 -0
- package/knowledge_base/retrieval/unified_query.py +189 -0
- package/knowledge_base/retrieval/web_retriever.py +337 -0
- package/knowledge_base/validators/__init__.py +1 -0
- package/knowledge_base/validators/__pycache__/__init__.cpython-314.pyc +0 -0
- package/knowledge_base/validators/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/validators/__pycache__/step_fidelity.cpython-314.pyc +0 -0
- package/knowledge_base/validators/__pycache__/step_fidelity.cpython-37.pyc +0 -0
- package/knowledge_base/validators/step_fidelity.py +88 -0
- package/knowledge_base/vision/__init__.py +0 -0
- package/knowledge_base/vision/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/vision/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/vision/__pycache__/image_describer.cpython-37.pyc +0 -0
- package/knowledge_base/vision/__pycache__/image_describer.cpython-38.pyc +0 -0
- package/knowledge_base/vision/image_describer.py +202 -0
- package/package.json +31 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Knowledge graph agent — enriches retrieval_agent KG context (no duplicate fetch)."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import re
|
|
5
|
+
import time
|
|
6
|
+
|
|
7
|
+
from knowledge_base.agents.state import AgenticState
|
|
8
|
+
from knowledge_base.config import cfg
|
|
9
|
+
from knowledge_base.db.client import get_conn
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def kg_agent(state: AgenticState) -> AgenticState:
|
|
13
|
+
t0 = time.perf_counter()
|
|
14
|
+
query = state.get("query", "")
|
|
15
|
+
kg_block = state.get("kg_context_block") or ""
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
text = kg_block
|
|
19
|
+
keys = re.findall(r"\b(app\.[a-z0-9]+(?:\.[a-z0-9_]+)+)\b", text, re.I)
|
|
20
|
+
paths = re.findall(r"TC\s*Setup[^•\n]{5,120}", text, re.I)
|
|
21
|
+
|
|
22
|
+
verified_keys = []
|
|
23
|
+
for k in dict.fromkeys(keys)[:30]:
|
|
24
|
+
status = "confirmed" if _kg_has_entity("registry_key", k) else "unverified"
|
|
25
|
+
verified_keys.append({"key": k, "confidence": status})
|
|
26
|
+
|
|
27
|
+
related_tcs, related_defects = _fetch_related_entities(query)
|
|
28
|
+
|
|
29
|
+
state["kg_entities"] = {
|
|
30
|
+
"registry_keys": verified_keys,
|
|
31
|
+
"ui_paths": [{"path": p.strip(), "confidence": "confirmed"} for p in dict.fromkeys(paths)[:20]],
|
|
32
|
+
"related_testcases": related_tcs,
|
|
33
|
+
"related_defects": related_defects,
|
|
34
|
+
"feature_relationships": [],
|
|
35
|
+
"backend": cfg.KG_BACKEND,
|
|
36
|
+
}
|
|
37
|
+
status = "complete"
|
|
38
|
+
except Exception as e:
|
|
39
|
+
state["kg_entities"] = {}
|
|
40
|
+
status = "error"
|
|
41
|
+
state.setdefault("agent_trace", []).append({
|
|
42
|
+
"agent": "KGAgent", "status": "error", "reason": str(e),
|
|
43
|
+
})
|
|
44
|
+
return state
|
|
45
|
+
|
|
46
|
+
ents = len(state["kg_entities"].get("registry_keys", [])) + len(state["kg_entities"].get("ui_paths", []))
|
|
47
|
+
state.setdefault("agent_trace", []).append({
|
|
48
|
+
"agent": "KGAgent",
|
|
49
|
+
"status": status,
|
|
50
|
+
"backend": cfg.KG_BACKEND,
|
|
51
|
+
"entities_found": ents,
|
|
52
|
+
"timing_ms": round((time.perf_counter() - t0) * 1000, 1),
|
|
53
|
+
})
|
|
54
|
+
return state
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _kg_has_entity(node_type: str, value: str) -> bool:
|
|
58
|
+
with get_conn() as conn:
|
|
59
|
+
with conn.cursor() as cur:
|
|
60
|
+
cur.execute(
|
|
61
|
+
"SELECT 1 FROM knowledge_graph_nodes WHERE node_type=%s AND normalized=%s LIMIT 1",
|
|
62
|
+
(node_type, value.lower()[:2000]),
|
|
63
|
+
)
|
|
64
|
+
return cur.fetchone() is not None
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _fetch_related_entities(query: str) -> tuple[list, list]:
|
|
68
|
+
tcs: list[dict] = []
|
|
69
|
+
defects: list[dict] = []
|
|
70
|
+
tokens = [t for t in re.findall(r"\w{4,}", query.lower())[:5]]
|
|
71
|
+
if not tokens:
|
|
72
|
+
return tcs, defects
|
|
73
|
+
pattern = "%" + "%".join(tokens[:2]) + "%"
|
|
74
|
+
with get_conn() as conn:
|
|
75
|
+
with conn.cursor() as cur:
|
|
76
|
+
cur.execute(
|
|
77
|
+
"""
|
|
78
|
+
SELECT node_type, value FROM knowledge_graph_nodes
|
|
79
|
+
WHERE node_type IN ('testcase', 'defect', 'error_code')
|
|
80
|
+
AND (normalized ILIKE %s OR value ILIKE %s)
|
|
81
|
+
LIMIT 10
|
|
82
|
+
""",
|
|
83
|
+
(pattern, pattern),
|
|
84
|
+
)
|
|
85
|
+
for node_type, value in cur.fetchall():
|
|
86
|
+
item = {"id": value, "title": value}
|
|
87
|
+
if node_type == "testcase":
|
|
88
|
+
tcs.append(item)
|
|
89
|
+
else:
|
|
90
|
+
defects.append(item)
|
|
91
|
+
return tcs, defects
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Memory agent — Phase 4/5 Cognee search."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from knowledge_base.agents.state import AgenticState
|
|
5
|
+
from knowledge_base.config import cfg
|
|
6
|
+
from knowledge_base.memory.cognee_client import get_cognee_client
|
|
7
|
+
from knowledge_base.memory.memory_types import MemoryType
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def memory_agent(state: AgenticState) -> AgenticState:
|
|
11
|
+
if not cfg.COGNEE_ENABLED:
|
|
12
|
+
state["memory_context"] = []
|
|
13
|
+
state.setdefault("agent_trace", []).append({
|
|
14
|
+
"agent": "MemoryAgent", "status": "skipped", "reason": "COGNEE_ENABLED=false",
|
|
15
|
+
})
|
|
16
|
+
return state
|
|
17
|
+
|
|
18
|
+
query = state.get("query", "")
|
|
19
|
+
feature = state.get("feature_area", "Unknown")
|
|
20
|
+
categories = state.get("query_categories", [])
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
client = get_cognee_client()
|
|
24
|
+
types = [MemoryType.FEEDBACK.value, MemoryType.PATTERN.value]
|
|
25
|
+
if "troubleshooting" in categories or "regression" in categories:
|
|
26
|
+
types.append(MemoryType.EXECUTION.value)
|
|
27
|
+
|
|
28
|
+
results = client.search(
|
|
29
|
+
query=f"{feature} {query}",
|
|
30
|
+
memory_types=types,
|
|
31
|
+
feature_area=feature,
|
|
32
|
+
top_k=5,
|
|
33
|
+
min_relevance=0.5,
|
|
34
|
+
)
|
|
35
|
+
state["memory_context"] = [
|
|
36
|
+
{
|
|
37
|
+
"memory_id": m.memory_id,
|
|
38
|
+
"memory_type": m.memory_type.value,
|
|
39
|
+
"content": m.content,
|
|
40
|
+
"feature_area": m.feature_area,
|
|
41
|
+
"relevance_score": m.relevance_score,
|
|
42
|
+
"applied_at": m.applied_at,
|
|
43
|
+
"curator": m.curator,
|
|
44
|
+
}
|
|
45
|
+
for m in results
|
|
46
|
+
if m.feature_area == feature or feature == "Unknown"
|
|
47
|
+
]
|
|
48
|
+
status = "complete"
|
|
49
|
+
except Exception as e:
|
|
50
|
+
state["memory_context"] = []
|
|
51
|
+
status = "error"
|
|
52
|
+
state.setdefault("agent_trace", []).append({
|
|
53
|
+
"agent": "MemoryAgent", "status": "error", "reason": str(e),
|
|
54
|
+
})
|
|
55
|
+
return state
|
|
56
|
+
|
|
57
|
+
state.setdefault("agent_trace", []).append({
|
|
58
|
+
"agent": "MemoryAgent",
|
|
59
|
+
"status": status,
|
|
60
|
+
"memories_retrieved": len(state["memory_context"]),
|
|
61
|
+
})
|
|
62
|
+
return state
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""RCA agent — Phase 7."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from knowledge_base.config import cfg
|
|
5
|
+
from knowledge_base.graph_db.kg_traversal import traverse_failure_path
|
|
6
|
+
from knowledge_base.memory.cognee_client import get_cognee_client
|
|
7
|
+
from knowledge_base.memory.memory_types import MemoryType
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def analyze_failure(test_id: str, failure_log: str) -> dict:
|
|
11
|
+
"""Traverse KG + memory to find root cause chain."""
|
|
12
|
+
if cfg.KG_BACKEND == "neo4j":
|
|
13
|
+
chain_result = traverse_failure_path(test_id)
|
|
14
|
+
else:
|
|
15
|
+
chain_result = {"status": "insufficient_graph_data", "chain": [], "missing": ["neo4j_primary"]}
|
|
16
|
+
|
|
17
|
+
similar = []
|
|
18
|
+
if cfg.COGNEE_ENABLED:
|
|
19
|
+
client = get_cognee_client()
|
|
20
|
+
memories = client.search(
|
|
21
|
+
query=f"{test_id} {failure_log[:200]}",
|
|
22
|
+
memory_types=[MemoryType.EXECUTION.value],
|
|
23
|
+
top_k=3,
|
|
24
|
+
)
|
|
25
|
+
similar = [{"content": m.content, "score": m.relevance_score} for m in memories]
|
|
26
|
+
|
|
27
|
+
if chain_result.get("status") == "insufficient_graph_data" and not similar:
|
|
28
|
+
return {
|
|
29
|
+
"status": "insufficient_graph_data",
|
|
30
|
+
"root_cause_chain": [],
|
|
31
|
+
"similar_failures": [],
|
|
32
|
+
"missing": chain_result.get("missing", []),
|
|
33
|
+
"confidence": 0.2,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
summary = _build_summary(chain_result, similar, failure_log)
|
|
37
|
+
return {
|
|
38
|
+
"status": "complete",
|
|
39
|
+
"test_id": test_id,
|
|
40
|
+
"root_cause_chain": chain_result.get("root_cause_chain") or chain_result.get("chain", []),
|
|
41
|
+
"similar_failures": similar,
|
|
42
|
+
"suggested_fix": summary,
|
|
43
|
+
"confidence": 0.7 if chain_result.get("root_cause_chain") else 0.4,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _build_summary(chain_result: dict, similar: list, failure_log: str) -> str:
|
|
48
|
+
chain = chain_result.get("root_cause_chain") or chain_result.get("chain") or []
|
|
49
|
+
if chain:
|
|
50
|
+
return f"Failure path: {' → '.join(str(c) for c in chain[:6])}"
|
|
51
|
+
if similar:
|
|
52
|
+
return f"Similar past failure pattern: {similar[0]['content'][:200]}"
|
|
53
|
+
return f"Analyze failure log manually: {failure_log[:300]}"
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Reflection agent — Phase 5."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from knowledge_base.agents.state import AgenticState
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def reflection_agent(state: AgenticState) -> AgenticState:
|
|
8
|
+
fused = state.get("fused_context") or {}
|
|
9
|
+
categories = state.get("query_categories", [])
|
|
10
|
+
version = state.get("version_scope", "unspecified")
|
|
11
|
+
temporal = state.get("temporal_context") or {}
|
|
12
|
+
intent = state.get("intent", "synthesize")
|
|
13
|
+
rag = state.get("rag_chunks", [])
|
|
14
|
+
|
|
15
|
+
notes: list[str] = []
|
|
16
|
+
procedure_steps = fused.get("procedure_steps") or []
|
|
17
|
+
|
|
18
|
+
if not fused.get("registry_keys") and "configuration" in categories:
|
|
19
|
+
notes.append("no_registry_keys")
|
|
20
|
+
if not fused.get("ui_paths"):
|
|
21
|
+
notes.append("no_ui_paths")
|
|
22
|
+
if len(procedure_steps) < 3:
|
|
23
|
+
notes.append("no_procedure_steps")
|
|
24
|
+
if version == "unspecified" and "version_specific" in categories:
|
|
25
|
+
notes.append("version_unconfirmed")
|
|
26
|
+
if version != "unspecified" and temporal.get("status") == "skipped":
|
|
27
|
+
notes.append("no_temporal_context")
|
|
28
|
+
if intent == "synthesize" and "negative_case" not in categories:
|
|
29
|
+
if not any("fail" in s.lower() or "error" in s.lower() for s in procedure_steps):
|
|
30
|
+
notes.append("no_negative_case_material")
|
|
31
|
+
if fused.get("context_quality", 0) < 0.5:
|
|
32
|
+
notes.append("low_context_quality")
|
|
33
|
+
if len(fused.get("conflicts") or []) > 2:
|
|
34
|
+
notes.append("unresolved_conflicts")
|
|
35
|
+
|
|
36
|
+
count = state.get("reflection_count", 0) + 1
|
|
37
|
+
state["reflection_count"] = count
|
|
38
|
+
|
|
39
|
+
if count >= 2:
|
|
40
|
+
state["force_to_validation"] = True
|
|
41
|
+
state["reflection_notes"] = []
|
|
42
|
+
state.setdefault("agent_trace", []).append({
|
|
43
|
+
"agent": "ReflectionAgent",
|
|
44
|
+
"status": "max_loops_reached",
|
|
45
|
+
"forced_to_validation": True,
|
|
46
|
+
})
|
|
47
|
+
else:
|
|
48
|
+
state["force_to_validation"] = False
|
|
49
|
+
state["reflection_notes"] = notes
|
|
50
|
+
state.setdefault("agent_trace", []).append({
|
|
51
|
+
"agent": "ReflectionAgent",
|
|
52
|
+
"status": "complete",
|
|
53
|
+
"reflection_notes": notes,
|
|
54
|
+
"loop": count,
|
|
55
|
+
})
|
|
56
|
+
return state
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def should_loop_back(state: AgenticState) -> bool:
|
|
60
|
+
if state.get("force_to_validation"):
|
|
61
|
+
return False
|
|
62
|
+
return bool(state.get("reflection_notes"))
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import List, Dict, Any, Set
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from knowledge_base.db.client import get_conn
|
|
5
|
+
from knowledge_base.agents.code_intelligence_agent import CodeIntelligenceAgent
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
class BitbucketSyncAgent:
|
|
10
|
+
"""Agent responsible for performing Delta Syncs from Bitbucket."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, repo_path: Path):
|
|
13
|
+
self.repo_path = repo_path
|
|
14
|
+
self.code_agent = CodeIntelligenceAgent(repo_path)
|
|
15
|
+
|
|
16
|
+
def sync_changed_files(self, changed_files: List[Path]) -> int:
|
|
17
|
+
"""Only index the specifically changed files (Delta Sync)."""
|
|
18
|
+
indexed = 0
|
|
19
|
+
for file in changed_files:
|
|
20
|
+
if not file.exists():
|
|
21
|
+
logger.info(f"File {file} deleted, removing from registry.")
|
|
22
|
+
rel_path = str(file.relative_to(self.repo_path))
|
|
23
|
+
with get_conn() as conn:
|
|
24
|
+
with conn.cursor() as cur:
|
|
25
|
+
cur.execute("DELETE FROM igel_asset_registry WHERE file_path = %s", (rel_path,))
|
|
26
|
+
conn.commit()
|
|
27
|
+
else:
|
|
28
|
+
indexed += self.code_agent.index_file(file)
|
|
29
|
+
|
|
30
|
+
return indexed
|
|
31
|
+
|
|
32
|
+
class RegressionAgent:
|
|
33
|
+
"""Agent responsible for determining impact of code changes."""
|
|
34
|
+
|
|
35
|
+
def analyze_impact(self, changed_files: List[Path], repo_path: Path) -> Dict[str, Any]:
|
|
36
|
+
"""Find requirements, test cases, and scripts affected by the changed files."""
|
|
37
|
+
impact = {
|
|
38
|
+
"affected_requirements": set(),
|
|
39
|
+
"affected_scripts": set(),
|
|
40
|
+
"affected_assets": set()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
with get_conn() as conn:
|
|
45
|
+
with conn.cursor() as cur:
|
|
46
|
+
for file in changed_files:
|
|
47
|
+
rel_path = str(file.relative_to(repo_path))
|
|
48
|
+
|
|
49
|
+
# 1. Find all assets in this file
|
|
50
|
+
cur.execute("SELECT id, name FROM igel_asset_registry WHERE file_path = %s", (rel_path,))
|
|
51
|
+
assets = cur.fetchall()
|
|
52
|
+
for asset_id, asset_name in assets:
|
|
53
|
+
impact["affected_assets"].add(asset_name)
|
|
54
|
+
|
|
55
|
+
# 2. Find all requirements mapped to this asset
|
|
56
|
+
cur.execute(
|
|
57
|
+
"""
|
|
58
|
+
SELECT r.jira_key
|
|
59
|
+
FROM igel_requirements r
|
|
60
|
+
JOIN igel_asset_mappings m ON r.id = m.requirement_id
|
|
61
|
+
WHERE m.asset_id = %s
|
|
62
|
+
""",
|
|
63
|
+
(asset_id,)
|
|
64
|
+
)
|
|
65
|
+
for req_row in cur.fetchall():
|
|
66
|
+
impact["affected_requirements"].add(req_row[0])
|
|
67
|
+
|
|
68
|
+
# 3. Find if this file itself is an automation script
|
|
69
|
+
cur.execute("SELECT script_path FROM igel_automation_scripts WHERE script_path = %s", (rel_path,))
|
|
70
|
+
if cur.fetchone():
|
|
71
|
+
impact["affected_scripts"].add(rel_path)
|
|
72
|
+
|
|
73
|
+
except Exception as e:
|
|
74
|
+
logger.error(f"Failed to analyze impact: {e}")
|
|
75
|
+
|
|
76
|
+
# Convert sets to lists for JSON serialization
|
|
77
|
+
return {
|
|
78
|
+
"affected_requirements": list(impact["affected_requirements"]),
|
|
79
|
+
"affected_scripts": list(impact["affected_scripts"]),
|
|
80
|
+
"affected_assets": list(impact["affected_assets"])
|
|
81
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Dict, Any
|
|
4
|
+
from openai import AzureOpenAI
|
|
5
|
+
from knowledge_base.config import cfg
|
|
6
|
+
from knowledge_base.models.test_requirement import RequirementUnderstanding, TestRequirement
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
_SYSTEM_PROMPT = """You are an expert IGEL Quality Engineering Architect.
|
|
11
|
+
Your task is to analyze a raw Jira/Xray Test Requirement and extract critical domain understanding.
|
|
12
|
+
You must extract actors, entities, explicit business rules, validations, constraints, and dependencies.
|
|
13
|
+
Output MUST be valid JSON matching this schema:
|
|
14
|
+
{
|
|
15
|
+
"actors": ["string"],
|
|
16
|
+
"entities": ["string"],
|
|
17
|
+
"business_rules": ["string"],
|
|
18
|
+
"validations": ["string"],
|
|
19
|
+
"constraints": ["string"],
|
|
20
|
+
"dependencies": ["string"]
|
|
21
|
+
}
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
_llm_client: AzureOpenAI | None = None
|
|
25
|
+
|
|
26
|
+
def _get_llm_client() -> AzureOpenAI:
|
|
27
|
+
global _llm_client
|
|
28
|
+
if _llm_client is None:
|
|
29
|
+
_llm_client = AzureOpenAI(
|
|
30
|
+
api_key=cfg.AZURE_API_KEY,
|
|
31
|
+
azure_endpoint=cfg.AZURE_ENDPOINT,
|
|
32
|
+
api_version=cfg.AZURE_API_VERSION,
|
|
33
|
+
)
|
|
34
|
+
return _llm_client
|
|
35
|
+
|
|
36
|
+
def extract_understanding(requirement: TestRequirement) -> RequirementUnderstanding:
|
|
37
|
+
"""Analyze a requirement and extract its core semantic understanding."""
|
|
38
|
+
client = _get_llm_client()
|
|
39
|
+
|
|
40
|
+
user_prompt = f"Requirement Key: {requirement.jira_key}\nSummary: {requirement.summary}\nDescription: {requirement.description or 'None'}\n"
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
response = client.chat.completions.create(
|
|
44
|
+
model=cfg.AZURE_DEPLOYMENT,
|
|
45
|
+
messages=[
|
|
46
|
+
{"role": "system", "content": _SYSTEM_PROMPT},
|
|
47
|
+
{"role": "user", "content": user_prompt},
|
|
48
|
+
],
|
|
49
|
+
response_format={"type": "json_object"},
|
|
50
|
+
temperature=0.1,
|
|
51
|
+
max_tokens=1500,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
content = response.choices[0].message.content or "{}"
|
|
55
|
+
data = json.loads(content)
|
|
56
|
+
|
|
57
|
+
understanding = RequirementUnderstanding(
|
|
58
|
+
actors=data.get("actors", []),
|
|
59
|
+
entities=data.get("entities", []),
|
|
60
|
+
business_rules=data.get("business_rules", []),
|
|
61
|
+
validations=data.get("validations", []),
|
|
62
|
+
constraints=data.get("constraints", []),
|
|
63
|
+
dependencies=data.get("dependencies", [])
|
|
64
|
+
)
|
|
65
|
+
logger.info(f"Successfully extracted understanding for {requirement.jira_key}")
|
|
66
|
+
return understanding
|
|
67
|
+
|
|
68
|
+
except Exception as e:
|
|
69
|
+
logger.error(f"Failed to extract understanding for {requirement.jira_key}: {e}")
|
|
70
|
+
# Return empty understanding on failure to not block the pipeline
|
|
71
|
+
return RequirementUnderstanding()
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Retrieval agent — Phase 5 (RAG + EKG + Web + MCP)."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from knowledge_base.agents.state import AgenticState
|
|
5
|
+
from knowledge_base.retrieval.unified_query import unified_query
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def retrieval_agent(state: AgenticState) -> AgenticState:
|
|
9
|
+
query = state.get("query", "")
|
|
10
|
+
top_k = state.get("top_k", 8)
|
|
11
|
+
product = state.get("product")
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
uq = unified_query(query=query, top_k=top_k, product=product)
|
|
15
|
+
bundle = uq.rag
|
|
16
|
+
chunks = []
|
|
17
|
+
for r in bundle.results:
|
|
18
|
+
chunks.append({
|
|
19
|
+
"chunk_id": r.child_chunk_id,
|
|
20
|
+
"content": r.parent_content,
|
|
21
|
+
"source_type": (r.metadata.get("source_type") if r.metadata else None) or "igel_docs",
|
|
22
|
+
"source_name": r.file_name,
|
|
23
|
+
"version_tag": None,
|
|
24
|
+
"rrf_score": r.rrf_score,
|
|
25
|
+
"rerank_score": r.rerank_score,
|
|
26
|
+
})
|
|
27
|
+
state["rag_chunks"] = chunks
|
|
28
|
+
state["web_context"] = {
|
|
29
|
+
"block": uq.web_block,
|
|
30
|
+
"hits": [
|
|
31
|
+
{"url": h.url, "title": h.title, "source_type": h.source_type, "score": h.score}
|
|
32
|
+
for h in uq.web_hits
|
|
33
|
+
],
|
|
34
|
+
}
|
|
35
|
+
state["mcp_context"] = {
|
|
36
|
+
"block": uq.mcp.block,
|
|
37
|
+
"hits": [
|
|
38
|
+
{"source": h.source, "title": h.title, "url": h.url, "score": h.score}
|
|
39
|
+
for h in uq.mcp.hits
|
|
40
|
+
],
|
|
41
|
+
"sources_queried": uq.mcp.sources_queried,
|
|
42
|
+
}
|
|
43
|
+
state["sources_summary"] = uq.sources_summary
|
|
44
|
+
state["kg_context_block"] = bundle.kg_context.text_block
|
|
45
|
+
status = "complete" if chunks else "no_results"
|
|
46
|
+
top_score = chunks[0]["rrf_score"] if chunks else 0
|
|
47
|
+
except Exception as e:
|
|
48
|
+
state["rag_chunks"] = []
|
|
49
|
+
state["web_context"] = {"block": "", "hits": []}
|
|
50
|
+
state["mcp_context"] = {"block": "", "hits": [], "sources_queried": []}
|
|
51
|
+
status = "error"
|
|
52
|
+
top_score = 0
|
|
53
|
+
state.setdefault("agent_trace", []).append({
|
|
54
|
+
"agent": "RetrievalAgent", "status": "error", "reason": str(e),
|
|
55
|
+
})
|
|
56
|
+
return state
|
|
57
|
+
|
|
58
|
+
state.setdefault("agent_trace", []).append({
|
|
59
|
+
"agent": "RetrievalAgent",
|
|
60
|
+
"status": status,
|
|
61
|
+
"chunks_retrieved": len(state["rag_chunks"]),
|
|
62
|
+
"web_hits": len(state["web_context"]["hits"]),
|
|
63
|
+
"mcp_hits": len(state["mcp_context"]["hits"]),
|
|
64
|
+
"top_score": top_score,
|
|
65
|
+
})
|
|
66
|
+
return state
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
from typing import List, Dict, Any
|
|
4
|
+
from openai import AzureOpenAI
|
|
5
|
+
from knowledge_base.config import cfg
|
|
6
|
+
from knowledge_base.models.test_requirement import (
|
|
7
|
+
TestRequirement,
|
|
8
|
+
TestStep,
|
|
9
|
+
BusinessRule,
|
|
10
|
+
ScenarioWithRules
|
|
11
|
+
)
|
|
12
|
+
from knowledge_base.agents.requirement_agent import _get_llm_client
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
_SYSTEM_PROMPT = """You are an expert IGEL Quality Engineering Architect.
|
|
17
|
+
Your task is to take a specific Scenario (a test step from a Jira requirement) and generate an exhaustive list of Business Rules for it.
|
|
18
|
+
Business rules dictate exactly what MUST be tested (positive, negative, and edge cases).
|
|
19
|
+
Consider the requirement's overall understanding context when generating rules.
|
|
20
|
+
Output MUST be valid JSON matching this schema:
|
|
21
|
+
{
|
|
22
|
+
"business_rules": [
|
|
23
|
+
{
|
|
24
|
+
"rule_type": "positive" | "negative" | "edge",
|
|
25
|
+
"description": "string"
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def generate_business_rules(requirement: TestRequirement, step: TestStep) -> ScenarioWithRules:
|
|
32
|
+
"""Analyze a scenario (test step) and extract exhaustive business rules."""
|
|
33
|
+
client = _get_llm_client()
|
|
34
|
+
|
|
35
|
+
# Construct context from the requirement's understanding if available
|
|
36
|
+
context_str = ""
|
|
37
|
+
if requirement.understanding:
|
|
38
|
+
context_str = f"Context (Actors): {', '.join(requirement.understanding.actors)}\n"
|
|
39
|
+
context_str += f"Context (Entities): {', '.join(requirement.understanding.entities)}\n"
|
|
40
|
+
context_str += f"Context (Constraints): {', '.join(requirement.understanding.constraints)}\n"
|
|
41
|
+
|
|
42
|
+
user_prompt = f"Requirement: {requirement.summary}\n{context_str}\n"
|
|
43
|
+
user_prompt += f"Scenario (Step {step.step_number}):\nAction: {step.action}\nData: {step.test_data or 'N/A'}\nExpected: {step.expected_result or 'N/A'}\n"
|
|
44
|
+
user_prompt += "\nGenerate exhaustive business rules for this scenario."
|
|
45
|
+
|
|
46
|
+
try:
|
|
47
|
+
response = client.chat.completions.create(
|
|
48
|
+
model=cfg.AZURE_DEPLOYMENT,
|
|
49
|
+
messages=[
|
|
50
|
+
{"role": "system", "content": _SYSTEM_PROMPT},
|
|
51
|
+
{"role": "user", "content": user_prompt},
|
|
52
|
+
],
|
|
53
|
+
response_format={"type": "json_object"},
|
|
54
|
+
temperature=0.2,
|
|
55
|
+
max_tokens=2000,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
content = response.choices[0].message.content or "{}"
|
|
59
|
+
data = json.loads(content)
|
|
60
|
+
|
|
61
|
+
rules = []
|
|
62
|
+
for r in data.get("business_rules", []):
|
|
63
|
+
if isinstance(r, dict) and "rule_type" in r and "description" in r:
|
|
64
|
+
rules.append(BusinessRule(
|
|
65
|
+
rule_type=r["rule_type"],
|
|
66
|
+
description=r["description"]
|
|
67
|
+
))
|
|
68
|
+
|
|
69
|
+
logger.info(f"Generated {len(rules)} business rules for step {step.step_number}")
|
|
70
|
+
return ScenarioWithRules(scenario=step, business_rules=rules)
|
|
71
|
+
|
|
72
|
+
except Exception as e:
|
|
73
|
+
logger.error(f"Failed to generate business rules for step {step.step_number}: {e}")
|
|
74
|
+
return ScenarioWithRules(scenario=step, business_rules=[])
|
|
75
|
+
|
|
76
|
+
def generate_all_scenarios(requirement: TestRequirement) -> List[ScenarioWithRules]:
|
|
77
|
+
"""Process all steps in a requirement to generate comprehensive business rules."""
|
|
78
|
+
scenarios = []
|
|
79
|
+
for step in requirement.steps:
|
|
80
|
+
scenarios.append(generate_business_rules(requirement, step))
|
|
81
|
+
return scenarios
|