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,494 @@
|
|
|
1
|
+
"""
|
|
2
|
+
5-Dimension Scoring for Test Case Generation Quality
|
|
3
|
+
====================================================
|
|
4
|
+
Each scorer returns a score [0.0, 1.0] and detailed feedback.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import ast
|
|
9
|
+
import re
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class ScoreDimension:
|
|
16
|
+
"""Single dimension score with feedback."""
|
|
17
|
+
name: str
|
|
18
|
+
score: float # 0.0 to 1.0
|
|
19
|
+
feedback: list[str] = field(default_factory=list)
|
|
20
|
+
metadata: dict[str, Any] = field(default_factory=dict)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class EvaluationResult:
|
|
25
|
+
"""Complete evaluation result with all 5 dimensions."""
|
|
26
|
+
query: str
|
|
27
|
+
retrieval: ScoreDimension
|
|
28
|
+
domain: ScoreDimension
|
|
29
|
+
structural: ScoreDimension
|
|
30
|
+
executability: ScoreDimension
|
|
31
|
+
publish: ScoreDimension
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def overall_score(self) -> float:
|
|
35
|
+
"""Weighted average: publish is composite of the other 4."""
|
|
36
|
+
return (
|
|
37
|
+
self.retrieval.score * 0.25 +
|
|
38
|
+
self.domain.score * 0.25 +
|
|
39
|
+
self.structural.score * 0.25 +
|
|
40
|
+
self.executability.score * 0.25
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def passed(self) -> bool:
|
|
45
|
+
"""Pass if all dimensions >= 0.6 and overall >= 0.7."""
|
|
46
|
+
return (
|
|
47
|
+
self.retrieval.score >= 0.6 and
|
|
48
|
+
self.domain.score >= 0.6 and
|
|
49
|
+
self.structural.score >= 0.6 and
|
|
50
|
+
self.executability.score >= 0.6 and
|
|
51
|
+
self.overall_score >= 0.7
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# ── Retrieval Confidence Scorer ──────────────────────────────────────────────
|
|
56
|
+
|
|
57
|
+
class RetrievalScorer:
|
|
58
|
+
"""Score retrieval quality: Did we find relevant chunks?"""
|
|
59
|
+
|
|
60
|
+
def score(
|
|
61
|
+
self,
|
|
62
|
+
query: str,
|
|
63
|
+
retrieved_chunks: list,
|
|
64
|
+
retrieval_metadata: dict,
|
|
65
|
+
) -> ScoreDimension:
|
|
66
|
+
"""
|
|
67
|
+
Scoring criteria:
|
|
68
|
+
- Number of chunks retrieved (more = better signal, up to 10)
|
|
69
|
+
- RRF scores (higher = better relevance)
|
|
70
|
+
- Rerank scores if available
|
|
71
|
+
- Diversity (chunks from different documents)
|
|
72
|
+
"""
|
|
73
|
+
feedback = []
|
|
74
|
+
score = 0.0
|
|
75
|
+
|
|
76
|
+
if not retrieved_chunks:
|
|
77
|
+
return ScoreDimension(
|
|
78
|
+
name="retrieval_confidence",
|
|
79
|
+
score=0.0,
|
|
80
|
+
feedback=["CRITICAL: No chunks retrieved"],
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# Criterion 1: Number of chunks (max score 0.3)
|
|
84
|
+
chunk_count = len(retrieved_chunks)
|
|
85
|
+
chunk_score = min(chunk_count / 10.0, 1.0) * 0.3
|
|
86
|
+
score += chunk_score
|
|
87
|
+
feedback.append(f"Retrieved {chunk_count} chunks (score: {chunk_score:.2f})")
|
|
88
|
+
|
|
89
|
+
# Criterion 2: RRF scores (max score 0.4)
|
|
90
|
+
rrf_scores = [
|
|
91
|
+
getattr(c, 'rrf_score', 0.0) for c in retrieved_chunks
|
|
92
|
+
]
|
|
93
|
+
if rrf_scores:
|
|
94
|
+
avg_rrf = sum(rrf_scores) / len(rrf_scores)
|
|
95
|
+
# RRF scores typically range 0-0.1, normalize to 0-1
|
|
96
|
+
rrf_normalized = min(avg_rrf * 10, 1.0)
|
|
97
|
+
rrf_component = rrf_normalized * 0.4
|
|
98
|
+
score += rrf_component
|
|
99
|
+
feedback.append(
|
|
100
|
+
f"Avg RRF score: {avg_rrf:.4f} (normalized: {rrf_normalized:.2f}, "
|
|
101
|
+
f"component: {rrf_component:.2f})"
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# Criterion 3: Rerank scores if available (max score 0.3)
|
|
105
|
+
rerank_scores = [
|
|
106
|
+
getattr(c, 'rerank_score', None) for c in retrieved_chunks
|
|
107
|
+
]
|
|
108
|
+
rerank_scores = [s for s in rerank_scores if s is not None]
|
|
109
|
+
if rerank_scores:
|
|
110
|
+
avg_rerank = sum(rerank_scores) / len(rerank_scores)
|
|
111
|
+
rerank_component = min(avg_rerank, 1.0) * 0.3
|
|
112
|
+
score += rerank_component
|
|
113
|
+
feedback.append(
|
|
114
|
+
f"Avg rerank score: {avg_rerank:.2f} (component: {rerank_component:.2f})"
|
|
115
|
+
)
|
|
116
|
+
else:
|
|
117
|
+
feedback.append("No reranking applied (missing 0.3 score)")
|
|
118
|
+
score += 0.0 # penalty for no reranking
|
|
119
|
+
|
|
120
|
+
return ScoreDimension(
|
|
121
|
+
name="retrieval_confidence",
|
|
122
|
+
score=min(score, 1.0),
|
|
123
|
+
feedback=feedback,
|
|
124
|
+
metadata={
|
|
125
|
+
"chunk_count": chunk_count,
|
|
126
|
+
"rrf_scores": rrf_scores,
|
|
127
|
+
"rerank_scores": rerank_scores,
|
|
128
|
+
},
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# ── Domain Confidence Scorer ──────────────────────────────────────────────────
|
|
133
|
+
|
|
134
|
+
class DomainScorer:
|
|
135
|
+
"""Score domain validity: Are entities (registry keys, UI paths) validated?"""
|
|
136
|
+
|
|
137
|
+
def __init__(self, kg_client=None):
|
|
138
|
+
"""kg_client: optional KG client to verify entities against graph."""
|
|
139
|
+
self.kg_client = kg_client
|
|
140
|
+
|
|
141
|
+
def score(
|
|
142
|
+
self,
|
|
143
|
+
markdown_output: str,
|
|
144
|
+
python_output: str | None,
|
|
145
|
+
retrieved_chunks: list,
|
|
146
|
+
kg_entities: dict | None = None,
|
|
147
|
+
) -> ScoreDimension:
|
|
148
|
+
"""
|
|
149
|
+
Scoring criteria:
|
|
150
|
+
- Registry keys present and verified against KG
|
|
151
|
+
- UI paths present and verified against KG
|
|
152
|
+
- No hallucinated entities
|
|
153
|
+
- Product consistency
|
|
154
|
+
"""
|
|
155
|
+
feedback = []
|
|
156
|
+
score = 1.0 # start at 1.0, deduct for issues
|
|
157
|
+
|
|
158
|
+
combined = markdown_output + "\n" + (python_output or "")
|
|
159
|
+
|
|
160
|
+
# Extract registry keys
|
|
161
|
+
registry_keys = re.findall(r'\bapp\.[a-z0-9_]+(?:\.[a-z0-9_]+)*', combined, re.I)
|
|
162
|
+
registry_keys = list(set(registry_keys))
|
|
163
|
+
|
|
164
|
+
# Extract UI paths (TC Setup > ...)
|
|
165
|
+
ui_paths = re.findall(
|
|
166
|
+
r'TC Setup\s*>\s*(?:[^>\n]+\s*>\s*)*[^>\n]+',
|
|
167
|
+
combined,
|
|
168
|
+
re.I
|
|
169
|
+
)
|
|
170
|
+
ui_paths = list(set(ui_paths))
|
|
171
|
+
|
|
172
|
+
feedback.append(f"Found {len(registry_keys)} registry keys")
|
|
173
|
+
feedback.append(f"Found {len(ui_paths)} UI paths")
|
|
174
|
+
|
|
175
|
+
# If KG client available, verify entities
|
|
176
|
+
if self.kg_client and kg_entities:
|
|
177
|
+
verified_keys = kg_entities.get('registry_keys', [])
|
|
178
|
+
verified_paths = kg_entities.get('ui_paths', [])
|
|
179
|
+
|
|
180
|
+
# Check registry keys
|
|
181
|
+
unverified_keys = [
|
|
182
|
+
k for k in registry_keys
|
|
183
|
+
if k.lower() not in [v.lower() for v in verified_keys]
|
|
184
|
+
]
|
|
185
|
+
if unverified_keys:
|
|
186
|
+
penalty = len(unverified_keys) * 0.1
|
|
187
|
+
score -= penalty
|
|
188
|
+
feedback.append(
|
|
189
|
+
f"WARNING: {len(unverified_keys)} unverified registry keys "
|
|
190
|
+
f"(penalty: -{penalty:.2f}): {unverified_keys[:3]}"
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# Check UI paths
|
|
194
|
+
unverified_paths = [
|
|
195
|
+
p for p in ui_paths
|
|
196
|
+
if not any(p.lower() in v.lower() or v.lower() in p.lower() for v in verified_paths)
|
|
197
|
+
]
|
|
198
|
+
if unverified_paths:
|
|
199
|
+
penalty = len(unverified_paths) * 0.1
|
|
200
|
+
score -= penalty
|
|
201
|
+
feedback.append(
|
|
202
|
+
f"WARNING: {len(unverified_paths)} unverified UI paths "
|
|
203
|
+
f"(penalty: -{penalty:.2f})"
|
|
204
|
+
)
|
|
205
|
+
else:
|
|
206
|
+
# No KG verification — partial penalty
|
|
207
|
+
if registry_keys or ui_paths:
|
|
208
|
+
score -= 0.2
|
|
209
|
+
feedback.append(
|
|
210
|
+
"WARNING: No KG verification available (penalty: -0.2)"
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
# Check for common hallucination patterns
|
|
214
|
+
hallucination_patterns = [
|
|
215
|
+
r'http://example\.com',
|
|
216
|
+
r'TODO:',
|
|
217
|
+
r'PLACEHOLDER',
|
|
218
|
+
r'\[insert.*?\]',
|
|
219
|
+
]
|
|
220
|
+
for pattern in hallucination_patterns:
|
|
221
|
+
if re.search(pattern, combined, re.I):
|
|
222
|
+
score -= 0.15
|
|
223
|
+
feedback.append(f"HALLUCINATION: Found pattern '{pattern}' (penalty: -0.15)")
|
|
224
|
+
|
|
225
|
+
return ScoreDimension(
|
|
226
|
+
name="domain_confidence",
|
|
227
|
+
score=max(score, 0.0),
|
|
228
|
+
feedback=feedback,
|
|
229
|
+
metadata={
|
|
230
|
+
"registry_keys": registry_keys,
|
|
231
|
+
"ui_paths": ui_paths,
|
|
232
|
+
},
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
# ── Structural Completeness Scorer ────────────────────────────────────────────
|
|
237
|
+
|
|
238
|
+
class StructuralScorer:
|
|
239
|
+
"""Score structural quality: Does TC have all required sections?"""
|
|
240
|
+
|
|
241
|
+
def score(
|
|
242
|
+
self,
|
|
243
|
+
markdown_output: str,
|
|
244
|
+
python_output: str | None,
|
|
245
|
+
) -> ScoreDimension:
|
|
246
|
+
"""
|
|
247
|
+
Scoring criteria:
|
|
248
|
+
- Preconditions section exists
|
|
249
|
+
- Steps table exists with >= 3 steps
|
|
250
|
+
- Each step has test data and expected result
|
|
251
|
+
- Cleanup/teardown mentioned
|
|
252
|
+
- Markdown follows template structure
|
|
253
|
+
"""
|
|
254
|
+
feedback = []
|
|
255
|
+
score = 0.0
|
|
256
|
+
|
|
257
|
+
# Criterion 1: Preconditions (0.2)
|
|
258
|
+
if re.search(r'##\s*Preconditions?', markdown_output, re.I):
|
|
259
|
+
score += 0.2
|
|
260
|
+
feedback.append("✓ Preconditions section present (+0.2)")
|
|
261
|
+
else:
|
|
262
|
+
feedback.append("✗ Missing preconditions section")
|
|
263
|
+
|
|
264
|
+
# Criterion 2: Steps table (0.3)
|
|
265
|
+
steps_match = re.search(
|
|
266
|
+
r'\|\s*#\s*\|\s*STEP\s*\|.*?\n\|[-|\s]+\n(.*?)(?=\n##|\Z)',
|
|
267
|
+
markdown_output,
|
|
268
|
+
re.DOTALL | re.I
|
|
269
|
+
)
|
|
270
|
+
if steps_match:
|
|
271
|
+
table_body = steps_match.group(1)
|
|
272
|
+
step_rows = [
|
|
273
|
+
row.strip() for row in table_body.split('\n')
|
|
274
|
+
if row.strip() and not row.strip().startswith('|---')
|
|
275
|
+
]
|
|
276
|
+
step_count = len(step_rows)
|
|
277
|
+
|
|
278
|
+
if step_count >= 3:
|
|
279
|
+
score += 0.3
|
|
280
|
+
feedback.append(f"✓ Steps table with {step_count} steps (+0.3)")
|
|
281
|
+
else:
|
|
282
|
+
partial = (step_count / 3) * 0.3
|
|
283
|
+
score += partial
|
|
284
|
+
feedback.append(
|
|
285
|
+
f"✗ Only {step_count} steps (expected >= 3, partial: +{partial:.2f})"
|
|
286
|
+
)
|
|
287
|
+
else:
|
|
288
|
+
feedback.append("✗ Missing steps table")
|
|
289
|
+
|
|
290
|
+
# Criterion 3: Expected results (0.2)
|
|
291
|
+
expected_count = len(re.findall(r'expected result', markdown_output, re.I))
|
|
292
|
+
if expected_count >= 3:
|
|
293
|
+
score += 0.2
|
|
294
|
+
feedback.append(f"✓ Expected results present ({expected_count} mentions, +0.2)")
|
|
295
|
+
else:
|
|
296
|
+
partial = (expected_count / 3) * 0.2
|
|
297
|
+
score += partial
|
|
298
|
+
feedback.append(
|
|
299
|
+
f"✗ Few expected results ({expected_count} mentions, +{partial:.2f})"
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
# Criterion 4: Cleanup/teardown (0.15)
|
|
303
|
+
if re.search(r'\b(cleanup|teardown|reboot|reset)\b', markdown_output, re.I):
|
|
304
|
+
score += 0.15
|
|
305
|
+
feedback.append("✓ Cleanup mentioned (+0.15)")
|
|
306
|
+
else:
|
|
307
|
+
feedback.append("✗ No cleanup/teardown mentioned")
|
|
308
|
+
|
|
309
|
+
# Criterion 5: Python structure if available (0.15)
|
|
310
|
+
if python_output:
|
|
311
|
+
has_steps = bool(re.findall(r'def\s+\w+_step\d+\s*\(', python_output))
|
|
312
|
+
has_cleanup = 'def.*cleanup' in python_output.lower()
|
|
313
|
+
|
|
314
|
+
if has_steps:
|
|
315
|
+
score += 0.1
|
|
316
|
+
feedback.append("✓ Python has step functions (+0.1)")
|
|
317
|
+
if has_cleanup:
|
|
318
|
+
score += 0.05
|
|
319
|
+
feedback.append("✓ Python has cleanup (+0.05)")
|
|
320
|
+
|
|
321
|
+
return ScoreDimension(
|
|
322
|
+
name="structural_completeness",
|
|
323
|
+
score=min(score, 1.0),
|
|
324
|
+
feedback=feedback,
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
# ── Executability Scorer ──────────────────────────────────────────────────────
|
|
329
|
+
|
|
330
|
+
class ExecutabilityScorer:
|
|
331
|
+
"""Score Python script quality: Does it parse, import, pass lint?"""
|
|
332
|
+
|
|
333
|
+
def score(
|
|
334
|
+
self,
|
|
335
|
+
python_output: str | None,
|
|
336
|
+
) -> ScoreDimension:
|
|
337
|
+
"""
|
|
338
|
+
Scoring criteria:
|
|
339
|
+
- Python parses (AST valid)
|
|
340
|
+
- Required imports present (pytest, allure, etc.)
|
|
341
|
+
- Fixture usage correct
|
|
342
|
+
- Registry key operations use proper helpers
|
|
343
|
+
- No bare asserts (use proper assertions)
|
|
344
|
+
"""
|
|
345
|
+
feedback = []
|
|
346
|
+
score = 0.0
|
|
347
|
+
|
|
348
|
+
if not python_output:
|
|
349
|
+
return ScoreDimension(
|
|
350
|
+
name="script_executability",
|
|
351
|
+
score=0.0,
|
|
352
|
+
feedback=["No Python output to score"],
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
# Criterion 1: Valid Python syntax (0.3)
|
|
356
|
+
try:
|
|
357
|
+
ast.parse(python_output)
|
|
358
|
+
score += 0.3
|
|
359
|
+
feedback.append("✓ Valid Python syntax (+0.3)")
|
|
360
|
+
except SyntaxError as e:
|
|
361
|
+
feedback.append(f"✗ Syntax error: {e}")
|
|
362
|
+
return ScoreDimension(
|
|
363
|
+
name="script_executability",
|
|
364
|
+
score=0.0,
|
|
365
|
+
feedback=feedback,
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
# Criterion 2: Required imports (0.25)
|
|
369
|
+
required_imports = ['pytest', 'allure']
|
|
370
|
+
present_imports = []
|
|
371
|
+
for imp in required_imports:
|
|
372
|
+
if f'import {imp}' in python_output or f'from {imp}' in python_output:
|
|
373
|
+
present_imports.append(imp)
|
|
374
|
+
|
|
375
|
+
import_score = (len(present_imports) / len(required_imports)) * 0.25
|
|
376
|
+
score += import_score
|
|
377
|
+
if len(present_imports) == len(required_imports):
|
|
378
|
+
feedback.append(f"✓ All required imports present (+0.25)")
|
|
379
|
+
else:
|
|
380
|
+
missing = set(required_imports) - set(present_imports)
|
|
381
|
+
feedback.append(
|
|
382
|
+
f"✗ Missing imports: {missing} (+{import_score:.2f})"
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
# Criterion 3: Fixture usage (0.2)
|
|
386
|
+
common_fixtures = ['ums_cred', 'device_cred', 'api_config']
|
|
387
|
+
used_fixtures = [f for f in common_fixtures if f in python_output]
|
|
388
|
+
if used_fixtures:
|
|
389
|
+
score += 0.2
|
|
390
|
+
feedback.append(f"✓ Uses fixtures: {used_fixtures} (+0.2)")
|
|
391
|
+
else:
|
|
392
|
+
feedback.append("✗ No standard fixtures used")
|
|
393
|
+
|
|
394
|
+
# Criterion 4: Proper assertions (0.15)
|
|
395
|
+
bare_asserts = len(re.findall(r'\bassert\s+\w', python_output))
|
|
396
|
+
proper_asserts = len(re.findall(r'assert.*==|assert.*in|assert.*is', python_output))
|
|
397
|
+
|
|
398
|
+
if proper_asserts >= bare_asserts * 0.8: # 80% proper assertions
|
|
399
|
+
score += 0.15
|
|
400
|
+
feedback.append(
|
|
401
|
+
f"✓ Proper assertions ({proper_asserts}/{bare_asserts}, +0.15)"
|
|
402
|
+
)
|
|
403
|
+
else:
|
|
404
|
+
partial = (proper_asserts / max(bare_asserts, 1)) * 0.15
|
|
405
|
+
score += partial
|
|
406
|
+
feedback.append(
|
|
407
|
+
f"✗ Some bare asserts ({proper_asserts}/{bare_asserts}, +{partial:.2f})"
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
# Criterion 5: Registry key helper usage (0.1)
|
|
411
|
+
if 'app.' in python_output:
|
|
412
|
+
# Should use get/set helpers, not raw registry operations
|
|
413
|
+
has_helpers = bool(re.search(r'\b(get|set)_registry\b', python_output))
|
|
414
|
+
if has_helpers:
|
|
415
|
+
score += 0.1
|
|
416
|
+
feedback.append("✓ Uses registry helpers (+0.1)")
|
|
417
|
+
else:
|
|
418
|
+
feedback.append("✗ Registry keys without helpers")
|
|
419
|
+
else:
|
|
420
|
+
# No registry keys = neutral (no penalty)
|
|
421
|
+
score += 0.1
|
|
422
|
+
feedback.append("✓ No registry operations needed (+0.1)")
|
|
423
|
+
|
|
424
|
+
return ScoreDimension(
|
|
425
|
+
name="script_executability",
|
|
426
|
+
score=min(score, 1.0),
|
|
427
|
+
feedback=feedback,
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
# ── Publish Confidence Scorer ─────────────────────────────────────────────────
|
|
432
|
+
|
|
433
|
+
class PublishScorer:
|
|
434
|
+
"""Composite score: Ready for human use without editing?"""
|
|
435
|
+
|
|
436
|
+
def score(
|
|
437
|
+
self,
|
|
438
|
+
retrieval: ScoreDimension,
|
|
439
|
+
domain: ScoreDimension,
|
|
440
|
+
structural: ScoreDimension,
|
|
441
|
+
executability: ScoreDimension,
|
|
442
|
+
) -> ScoreDimension:
|
|
443
|
+
"""
|
|
444
|
+
Weighted composite:
|
|
445
|
+
- Retrieval: 25%
|
|
446
|
+
- Domain: 25%
|
|
447
|
+
- Structural: 25%
|
|
448
|
+
- Executability: 25%
|
|
449
|
+
|
|
450
|
+
Thresholds:
|
|
451
|
+
- >= 0.85: Publish immediately
|
|
452
|
+
- 0.70-0.84: Publish with low-priority review
|
|
453
|
+
- 0.60-0.69: Human review required
|
|
454
|
+
- < 0.60: Block, fix before publish
|
|
455
|
+
"""
|
|
456
|
+
composite = (
|
|
457
|
+
retrieval.score * 0.25 +
|
|
458
|
+
domain.score * 0.25 +
|
|
459
|
+
structural.score * 0.25 +
|
|
460
|
+
executability.score * 0.25
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
feedback = []
|
|
464
|
+
|
|
465
|
+
if composite >= 0.85:
|
|
466
|
+
feedback.append("PUBLISH: High confidence, ready for immediate use")
|
|
467
|
+
elif composite >= 0.70:
|
|
468
|
+
feedback.append("PUBLISH: Good confidence, low-priority review recommended")
|
|
469
|
+
elif composite >= 0.60:
|
|
470
|
+
feedback.append("REVIEW REQUIRED: Moderate confidence, human validation needed")
|
|
471
|
+
else:
|
|
472
|
+
feedback.append("BLOCK: Low confidence, requires fixes before publishing")
|
|
473
|
+
|
|
474
|
+
# Flag specific issues
|
|
475
|
+
if retrieval.score < 0.6:
|
|
476
|
+
feedback.append("ISSUE: Poor retrieval quality")
|
|
477
|
+
if domain.score < 0.6:
|
|
478
|
+
feedback.append("ISSUE: Unverified or hallucinated entities")
|
|
479
|
+
if structural.score < 0.6:
|
|
480
|
+
feedback.append("ISSUE: Incomplete test case structure")
|
|
481
|
+
if executability.score < 0.6:
|
|
482
|
+
feedback.append("ISSUE: Script has errors or missing components")
|
|
483
|
+
|
|
484
|
+
return ScoreDimension(
|
|
485
|
+
name="publish_confidence",
|
|
486
|
+
score=composite,
|
|
487
|
+
feedback=feedback,
|
|
488
|
+
metadata={
|
|
489
|
+
"retrieval": retrieval.score,
|
|
490
|
+
"domain": domain.score,
|
|
491
|
+
"structural": structural.score,
|
|
492
|
+
"executability": executability.score,
|
|
493
|
+
},
|
|
494
|
+
)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Few-shot exemplars for fidelity-first generation
|
|
2
|
+
|
|
3
|
+
- **pytest_reference_snippet.py** — Reference pytest shape (`@allure.step`, `TCnnn_stepN`, `api_config`, UMS/WUMS, SSH, OCR).
|
|
4
|
+
- **gold_manual_concise_snippet.md** — Short IGEL manual TC style (few steps, terse expected results).
|
|
5
|
+
- **gold_manual_detailed_snippet.md** — Long TC style (many steps, full `TC Setup` paths).
|
|
6
|
+
|
|
7
|
+
These are **style anchors**, not KB content. Transform mode still uses the user-pasted TC as primary truth.
|
|
Binary file
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Example: concise official manual style (UMS device lifecycle)
|
|
2
|
+
|
|
3
|
+
| Step | Test Data | Expected Result |
|
|
4
|
+
|------|-----------|-----------------|
|
|
5
|
+
| Register endpoint | Register in UMS (Radar). Check WUMS import. | Endpoint registered; license applied if configured. |
|
|
6
|
+
| Check device info | Open device details: system + license. | Information displayed correctly. |
|
|
7
|
+
| Assign profiles | Assign app + standard profiles; save now / on reboot. | Profiles applied per option; apps from portal if applicable. |
|
|
8
|
+
| Reboot | Reboot via UMS. | Endpoint reboots. |
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Example: detailed official manual style (browser policies)
|
|
2
|
+
|
|
3
|
+
Steps preserve exact `TC Setup` navigation and verification URLs from IGEL QA.
|
|
4
|
+
|
|
5
|
+
1. Open **TC Setup > Chromium Browser > Global Settings > General** — enable *Automatic browser restart on exit*. Expected: setting applied after policy sync.
|
|
6
|
+
2. Open **TC Setup > Chromium Browser > Global Settings > Security & Encryption > JavaScript**. Navigate to `https://browserleaks.com/javascript` in session. Expected: behavior matches policy (enabled/disabled as configured).
|
|
7
|
+
3. Use **chrome://policy** in session to confirm policies applied. Expected: configured keys visible and match TC Setup values.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import time, allure
|
|
2
|
+
from core.api.UMS import UMS
|
|
3
|
+
from core.ssh.ssh import SSHClient
|
|
4
|
+
from core.ui.ui_automation_text import OcrUiInteractor
|
|
5
|
+
from config.read_config import ums_cred, device_cred
|
|
6
|
+
from core.ssh.my_logger import logger
|
|
7
|
+
from core.api.ums_wums_api import UMSWUMSApi
|
|
8
|
+
|
|
9
|
+
click = OcrUiInteractor()
|
|
10
|
+
|
|
11
|
+
def get_ssh():
|
|
12
|
+
return SSHClient(host=device_cred["host"], user=device_cred["user"],
|
|
13
|
+
pwd=device_cred["pwd"], port=device_cred["port"])
|
|
14
|
+
|
|
15
|
+
def _assign(ums, wums, device, profile_key, default_name, api_config):
|
|
16
|
+
profile = ums.get_profile_details(api_config.get(profile_key, default_name))
|
|
17
|
+
wums.assign_object(device["id"], profile["id"], "profile")
|
|
18
|
+
return profile
|
|
19
|
+
|
|
20
|
+
def _detach(ums, wums, device, profile_key, default_name, api_config):
|
|
21
|
+
profile = ums.get_profile_details(api_config.get(profile_key, default_name))
|
|
22
|
+
wums.detach_profile(device["id"], profile["id"])
|
|
23
|
+
|
|
24
|
+
@allure.step("TC001 S1: Assign profile and verify UI")
|
|
25
|
+
def TC001_step1(api_config, browser):
|
|
26
|
+
try:
|
|
27
|
+
ums = UMS(ums_cred["base_url"], ums_cred["username"], ums_cred["password"])
|
|
28
|
+
wums = UMSWUMSApi(ums_cred["weburl"], ums_cred["username"], ums_cred["password"])
|
|
29
|
+
dev = ums.get_vm_details(device_cred["hostname"])
|
|
30
|
+
_assign(ums, wums, dev, "profile_key", "Default-Profile", api_config)
|
|
31
|
+
return click.is_text_present_on_screen("ExpectedLabel", refresh_before_check=True)
|
|
32
|
+
except Exception as e:
|
|
33
|
+
logger.error(f"TC001_step1: {e}"); return False
|
|
34
|
+
|
|
35
|
+
@allure.feature("Feature Area")
|
|
36
|
+
@allure.severity(allure.severity_level.CRITICAL)
|
|
37
|
+
def test_TC001_step1(api_config, browser_instance): assert TC001_step1(api_config, browser_instance)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""Human feedback capture, curation, and application."""
|
|
2
|
+
|
|
3
|
+
from knowledge_base.feedback.handler import apply_feedback, apply_promotion, capture_feedback, curate_feedback
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"apply_feedback",
|
|
7
|
+
"apply_promotion",
|
|
8
|
+
"capture_feedback",
|
|
9
|
+
"curate_feedback",
|
|
10
|
+
]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""Feedback analytics — Phase 2 weekly failure pattern reports."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from datetime import datetime, timedelta
|
|
5
|
+
|
|
6
|
+
from knowledge_base.db.client import get_conn
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def generate_weekly_report(days: int = 7) -> dict:
|
|
10
|
+
"""Aggregate feedback trends for the last N days."""
|
|
11
|
+
since = datetime.utcnow() - timedelta(days=days)
|
|
12
|
+
|
|
13
|
+
with get_conn() as conn:
|
|
14
|
+
with conn.cursor() as cur:
|
|
15
|
+
cur.execute(
|
|
16
|
+
"""
|
|
17
|
+
SELECT feedback_type, COUNT(*) FROM feedback_events
|
|
18
|
+
WHERE created_at >= %s
|
|
19
|
+
GROUP BY feedback_type ORDER BY COUNT(*) DESC
|
|
20
|
+
""",
|
|
21
|
+
(since,),
|
|
22
|
+
)
|
|
23
|
+
by_type = {row[0]: row[1] for row in cur.fetchall()}
|
|
24
|
+
|
|
25
|
+
cur.execute(
|
|
26
|
+
"""
|
|
27
|
+
SELECT status, COUNT(*) FROM feedback_events
|
|
28
|
+
WHERE created_at >= %s
|
|
29
|
+
GROUP BY status ORDER BY COUNT(*) DESC
|
|
30
|
+
""",
|
|
31
|
+
(since,),
|
|
32
|
+
)
|
|
33
|
+
by_status = {row[0]: row[1] for row in cur.fetchall()}
|
|
34
|
+
|
|
35
|
+
cur.execute(
|
|
36
|
+
"""
|
|
37
|
+
SELECT feedback_type, COUNT(*) FROM feedback_events
|
|
38
|
+
WHERE created_at >= %s AND status = 'pending'
|
|
39
|
+
GROUP BY feedback_type ORDER BY COUNT(*) DESC LIMIT 5
|
|
40
|
+
""",
|
|
41
|
+
(since,),
|
|
42
|
+
)
|
|
43
|
+
top_pending = [{"type": r[0], "count": r[1]} for r in cur.fetchall()]
|
|
44
|
+
|
|
45
|
+
cur.execute(
|
|
46
|
+
"""
|
|
47
|
+
SELECT COUNT(*) FROM feedback_promotions
|
|
48
|
+
WHERE created_at >= %s AND status = 'applied'
|
|
49
|
+
""",
|
|
50
|
+
(since,),
|
|
51
|
+
)
|
|
52
|
+
applied_count = cur.fetchone()[0]
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
"period_days": days,
|
|
56
|
+
"generated_at": datetime.utcnow().isoformat(),
|
|
57
|
+
"by_feedback_type": by_type,
|
|
58
|
+
"by_status": by_status,
|
|
59
|
+
"top_pending_patterns": top_pending,
|
|
60
|
+
"promotions_applied": applied_count,
|
|
61
|
+
"summary": _build_summary(by_type, by_status, top_pending),
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _build_summary(by_type: dict, by_status: dict, top_pending: list) -> str:
|
|
66
|
+
total = sum(by_type.values())
|
|
67
|
+
pending = by_status.get("pending", 0)
|
|
68
|
+
lines = [f"Total feedback events (7d): {total}", f"Pending review: {pending}"]
|
|
69
|
+
if top_pending:
|
|
70
|
+
top = top_pending[0]
|
|
71
|
+
lines.append(f"Top failure pattern: {top['type']} ({top['count']} events)")
|
|
72
|
+
return " | ".join(lines)
|