nat-engine 1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (299) hide show
  1. mannf/__init__.py +33 -0
  2. mannf/__main__.py +10 -0
  3. mannf/_version.py +8 -0
  4. mannf/agents/__init__.py +7 -0
  5. mannf/agents/analyzer_agent.py +9 -0
  6. mannf/agents/base.py +9 -0
  7. mannf/agents/bdi_agent.py +9 -0
  8. mannf/agents/belief_state.py +9 -0
  9. mannf/agents/coordinator_agent.py +9 -0
  10. mannf/agents/executor_agent.py +9 -0
  11. mannf/agents/monitor_agent.py +9 -0
  12. mannf/agents/oracle_agent.py +9 -0
  13. mannf/agents/planner_agent.py +9 -0
  14. mannf/agents/test_agent.py +9 -0
  15. mannf/anomaly/__init__.py +7 -0
  16. mannf/anomaly/enhanced_detector.py +9 -0
  17. mannf/cli.py +9 -0
  18. mannf/core/__init__.py +26 -0
  19. mannf/core/agents/__init__.py +52 -0
  20. mannf/core/agents/accessibility_scanner_agent.py +245 -0
  21. mannf/core/agents/analyzer_agent.py +224 -0
  22. mannf/core/agents/autonomous_loop_agent.py +1086 -0
  23. mannf/core/agents/autonomous_loop_models.py +62 -0
  24. mannf/core/agents/autonomous_run_differ.py +427 -0
  25. mannf/core/agents/base.py +128 -0
  26. mannf/core/agents/bdi_agent.py +330 -0
  27. mannf/core/agents/belief_state.py +202 -0
  28. mannf/core/agents/browser_coordinator_agent.py +224 -0
  29. mannf/core/agents/browser_executor_agent.py +410 -0
  30. mannf/core/agents/coordinator_agent.py +262 -0
  31. mannf/core/agents/executor_agent.py +222 -0
  32. mannf/core/agents/monitor_agent.py +188 -0
  33. mannf/core/agents/oracle_agent.py +150 -0
  34. mannf/core/agents/performance_testing_agent.py +279 -0
  35. mannf/core/agents/planner_agent.py +128 -0
  36. mannf/core/agents/test_agent.py +249 -0
  37. mannf/core/agents/visual_regression_agent.py +311 -0
  38. mannf/core/agents/web_crawler_agent.py +510 -0
  39. mannf/core/agents/worker_pool.py +366 -0
  40. mannf/core/anomaly/__init__.py +14 -0
  41. mannf/core/anomaly/enhanced_detector.py +541 -0
  42. mannf/core/browser/__init__.py +63 -0
  43. mannf/core/browser/accessibility_scanner.py +424 -0
  44. mannf/core/browser/discovery_model.py +178 -0
  45. mannf/core/browser/dom_snapshot.py +349 -0
  46. mannf/core/browser/ingestor_bridge.py +371 -0
  47. mannf/core/browser/performance_metrics.py +217 -0
  48. mannf/core/browser/reflection_analyzer.py +442 -0
  49. mannf/core/browser/scenario_generator.py +1100 -0
  50. mannf/core/browser/security_scenario_generator.py +695 -0
  51. mannf/core/browser/visual_comparer.py +159 -0
  52. mannf/core/diagnostics/__init__.py +28 -0
  53. mannf/core/diagnostics/failure_clusterer.py +211 -0
  54. mannf/core/diagnostics/flake_detector.py +233 -0
  55. mannf/core/diagnostics/root_cause_analyzer.py +273 -0
  56. mannf/core/distributed/__init__.py +16 -0
  57. mannf/core/distributed/endpoint.py +139 -0
  58. mannf/core/distributed/system_under_test.py +207 -0
  59. mannf/core/functional_orchestrator.py +428 -0
  60. mannf/core/messaging/__init__.py +11 -0
  61. mannf/core/messaging/bus.py +113 -0
  62. mannf/core/messaging/messages.py +89 -0
  63. mannf/core/nat_orchestrator.py +342 -0
  64. mannf/core/neural/__init__.py +183 -0
  65. mannf/core/orchestrator.py +272 -0
  66. mannf/core/prioritization/__init__.py +17 -0
  67. mannf/core/prioritization/adaptive_controller.py +509 -0
  68. mannf/core/prioritization/belief_prioritizer.py +231 -0
  69. mannf/core/prioritization/risk_scorer.py +430 -0
  70. mannf/core/reporting/__init__.py +12 -0
  71. mannf/core/reporting/unified_report.py +664 -0
  72. mannf/core/testing/__init__.py +17 -0
  73. mannf/core/testing/adaptive_controller.py +149 -0
  74. mannf/core/testing/models.py +179 -0
  75. mannf/core/validation/__init__.py +10 -0
  76. mannf/core/validation/self_validation_runner.py +180 -0
  77. mannf/dashboard/__init__.py +7 -0
  78. mannf/dashboard/app.py +9 -0
  79. mannf/dashboard/models.py +9 -0
  80. mannf/dashboard/static/index.html +2538 -0
  81. mannf/dashboard/telemetry.py +9 -0
  82. mannf/distributed/__init__.py +7 -0
  83. mannf/distributed/endpoint.py +9 -0
  84. mannf/distributed/system_under_test.py +9 -0
  85. mannf/healing/__init__.py +7 -0
  86. mannf/healing/graphql_schema_diff.py +9 -0
  87. mannf/healing/healer.py +9 -0
  88. mannf/healing/models.py +9 -0
  89. mannf/healing/schema_diff.py +9 -0
  90. mannf/integrations/__init__.py +7 -0
  91. mannf/integrations/auth.py +9 -0
  92. mannf/integrations/graphql_parser.py +9 -0
  93. mannf/integrations/graphql_sut.py +9 -0
  94. mannf/integrations/http_sut.py +9 -0
  95. mannf/integrations/openapi_parser.py +9 -0
  96. mannf/integrations/postman_parser.py +9 -0
  97. mannf/llm/__init__.py +7 -0
  98. mannf/llm/anthropic_provider.py +9 -0
  99. mannf/llm/base.py +9 -0
  100. mannf/llm/config.py +9 -0
  101. mannf/llm/factory.py +9 -0
  102. mannf/llm/openai_provider.py +9 -0
  103. mannf/llm/prompts.py +9 -0
  104. mannf/messaging/__init__.py +7 -0
  105. mannf/messaging/bus.py +9 -0
  106. mannf/messaging/messages.py +9 -0
  107. mannf/nat_orchestrator.py +9 -0
  108. mannf/neural/__init__.py +7 -0
  109. mannf/orchestrator.py +9 -0
  110. mannf/prioritization/__init__.py +7 -0
  111. mannf/prioritization/adaptive_controller.py +9 -0
  112. mannf/prioritization/belief_prioritizer.py +9 -0
  113. mannf/prioritization/risk_scorer.py +9 -0
  114. mannf/product/__init__.py +29 -0
  115. mannf/product/admin/__init__.py +3 -0
  116. mannf/product/admin/routes.py +514 -0
  117. mannf/product/auth/__init__.py +5 -0
  118. mannf/product/auth/saml.py +212 -0
  119. mannf/product/billing/__init__.py +5 -0
  120. mannf/product/billing/audit.py +160 -0
  121. mannf/product/billing/feature_gates.py +180 -0
  122. mannf/product/billing/metering.py +179 -0
  123. mannf/product/billing/notifications.py +181 -0
  124. mannf/product/billing/plans.py +133 -0
  125. mannf/product/billing/rate_limits.py +35 -0
  126. mannf/product/billing/stripe_billing.py +906 -0
  127. mannf/product/billing/tenant_auth.py +233 -0
  128. mannf/product/billing/tenant_manager.py +873 -0
  129. mannf/product/cli.py +3900 -0
  130. mannf/product/cli_admin.py +408 -0
  131. mannf/product/dashboard/__init__.py +61 -0
  132. mannf/product/dashboard/app.py +3567 -0
  133. mannf/product/dashboard/models.py +460 -0
  134. mannf/product/dashboard/static/index.html +6347 -0
  135. mannf/product/dashboard/static/manifest.json +25 -0
  136. mannf/product/dashboard/static/pwa-icon-192.png +0 -0
  137. mannf/product/dashboard/static/pwa-icon-512.png +0 -0
  138. mannf/product/dashboard/static/sw.js +64 -0
  139. mannf/product/dashboard/telemetry.py +547 -0
  140. mannf/product/database.py +145 -0
  141. mannf/product/demo.py +844 -0
  142. mannf/product/doctor.py +509 -0
  143. mannf/product/exporters/__init__.py +65 -0
  144. mannf/product/exporters/azuredevops_exporter.py +257 -0
  145. mannf/product/exporters/base.py +307 -0
  146. mannf/product/exporters/bugzilla_exporter.py +200 -0
  147. mannf/product/exporters/dedup.py +275 -0
  148. mannf/product/exporters/finding_adapter.py +216 -0
  149. mannf/product/exporters/github_exporter.py +197 -0
  150. mannf/product/exporters/gitlab_exporter.py +215 -0
  151. mannf/product/exporters/jira_exporter.py +180 -0
  152. mannf/product/exporters/linear_exporter.py +195 -0
  153. mannf/product/exporters/loader.py +233 -0
  154. mannf/product/exporters/pagerduty_exporter.py +363 -0
  155. mannf/product/exporters/sentry_exporter.py +322 -0
  156. mannf/product/exporters/servicenow_exporter.py +240 -0
  157. mannf/product/exporters/shortcut_exporter.py +231 -0
  158. mannf/product/exporters/webhook_exporter.py +383 -0
  159. mannf/product/formatters/__init__.py +18 -0
  160. mannf/product/formatters/allure_formatter.py +161 -0
  161. mannf/product/formatters/ctrf_formatter.py +149 -0
  162. mannf/product/healing/__init__.py +30 -0
  163. mannf/product/healing/graphql_schema_diff.py +152 -0
  164. mannf/product/healing/healer.py +141 -0
  165. mannf/product/healing/models.py +175 -0
  166. mannf/product/healing/schema_diff.py +251 -0
  167. mannf/product/ingestors/__init__.py +77 -0
  168. mannf/product/ingestors/base.py +256 -0
  169. mannf/product/ingestors/bgstm_ingestor.py +764 -0
  170. mannf/product/ingestors/curl_ingestor.py +1019 -0
  171. mannf/product/ingestors/cypress_ingestor.py +487 -0
  172. mannf/product/ingestors/gherkin_ingestor.py +967 -0
  173. mannf/product/ingestors/graphql_ingestor.py +845 -0
  174. mannf/product/ingestors/grpc_ingestor.py +591 -0
  175. mannf/product/ingestors/har_ingestor.py +976 -0
  176. mannf/product/ingestors/loader.py +284 -0
  177. mannf/product/ingestors/models.py +146 -0
  178. mannf/product/ingestors/openapi_ingestor.py +606 -0
  179. mannf/product/ingestors/playwright_ingestor.py +449 -0
  180. mannf/product/ingestors/postman_ingestor.py +631 -0
  181. mannf/product/ingestors/traffic_ingestor.py +679 -0
  182. mannf/product/ingestors/websocket_ingestor.py +526 -0
  183. mannf/product/integrations/__init__.py +21 -0
  184. mannf/product/integrations/auth.py +190 -0
  185. mannf/product/integrations/graphql_parser.py +436 -0
  186. mannf/product/integrations/graphql_sut.py +247 -0
  187. mannf/product/integrations/grpc_sut.py +469 -0
  188. mannf/product/integrations/http_sut.py +237 -0
  189. mannf/product/integrations/kafka_adapter.py +342 -0
  190. mannf/product/integrations/openapi_parser.py +513 -0
  191. mannf/product/integrations/postman_parser.py +467 -0
  192. mannf/product/integrations/webhook_receiver.py +344 -0
  193. mannf/product/integrations/websocket_sut.py +434 -0
  194. mannf/product/llm/__init__.py +25 -0
  195. mannf/product/llm/anthropic_provider.py +94 -0
  196. mannf/product/llm/base.py +267 -0
  197. mannf/product/llm/config.py +48 -0
  198. mannf/product/llm/factory.py +42 -0
  199. mannf/product/llm/openai_provider.py +93 -0
  200. mannf/product/llm/prompts.py +403 -0
  201. mannf/product/llm/root_cause_service.py +311 -0
  202. mannf/product/llm/test_plan_models.py +78 -0
  203. mannf/product/metrics.py +149 -0
  204. mannf/product/middleware/__init__.py +3 -0
  205. mannf/product/middleware/audit_middleware.py +112 -0
  206. mannf/product/middleware/tenant_isolation.py +114 -0
  207. mannf/product/models.py +347 -0
  208. mannf/product/notifications/__init__.py +24 -0
  209. mannf/product/notifications/dispatcher.py +411 -0
  210. mannf/product/onboarding.py +190 -0
  211. mannf/product/orchestration/__init__.py +39 -0
  212. mannf/product/orchestration/ingest_scan_orchestrator.py +339 -0
  213. mannf/product/orchestration/pipeline.py +401 -0
  214. mannf/product/orchestrator.py +987 -0
  215. mannf/product/orchestrator_models.py +269 -0
  216. mannf/product/regression/__init__.py +36 -0
  217. mannf/product/regression/differ.py +172 -0
  218. mannf/product/regression/masking.py +100 -0
  219. mannf/product/regression/models.py +232 -0
  220. mannf/product/regression/recorder.py +124 -0
  221. mannf/product/regression/replayer.py +168 -0
  222. mannf/product/reports/__init__.py +10 -0
  223. mannf/product/reports/pdf.py +132 -0
  224. mannf/product/scheduling/__init__.py +57 -0
  225. mannf/product/scheduling/cron_utils.py +251 -0
  226. mannf/product/scheduling/engine.py +473 -0
  227. mannf/product/scheduling/models.py +86 -0
  228. mannf/product/scheduling/queue.py +894 -0
  229. mannf/product/scheduling/store.py +235 -0
  230. mannf/product/security/__init__.py +21 -0
  231. mannf/product/security/belief_guided.py +143 -0
  232. mannf/product/security/checks/__init__.py +55 -0
  233. mannf/product/security/checks/base.py +69 -0
  234. mannf/product/security/checks/bfla.py +77 -0
  235. mannf/product/security/checks/bola.py +77 -0
  236. mannf/product/security/checks/bopla.py +80 -0
  237. mannf/product/security/checks/broken_auth.py +86 -0
  238. mannf/product/security/checks/graphql_security.py +299 -0
  239. mannf/product/security/checks/inventory.py +70 -0
  240. mannf/product/security/checks/misconfig.py +158 -0
  241. mannf/product/security/checks/resource_consumption.py +70 -0
  242. mannf/product/security/checks/sensitive_flows.py +80 -0
  243. mannf/product/security/checks/ssrf.py +101 -0
  244. mannf/product/security/checks/unsafe_consumption.py +120 -0
  245. mannf/product/security/models.py +92 -0
  246. mannf/product/security/plugin_loader.py +182 -0
  247. mannf/product/security/reporter.py +92 -0
  248. mannf/product/security/scanner.py +183 -0
  249. mannf/product/server.py +6220 -0
  250. mannf/product/setup_wizard.py +873 -0
  251. mannf/product/status.py +404 -0
  252. mannf/product/storage/__init__.py +10 -0
  253. mannf/product/storage/artifact_store.py +343 -0
  254. mannf/product/telemetry.py +300 -0
  255. mannf/product/uninstall.py +169 -0
  256. mannf/product/upgrade.py +139 -0
  257. mannf/product/weights/__init__.py +13 -0
  258. mannf/product/weights/blob_store.py +299 -0
  259. mannf/product/weights/factory.py +42 -0
  260. mannf/product/weights/registry.py +159 -0
  261. mannf/product/weights/store.py +210 -0
  262. mannf/regression/__init__.py +7 -0
  263. mannf/regression/differ.py +9 -0
  264. mannf/regression/masking.py +9 -0
  265. mannf/regression/models.py +9 -0
  266. mannf/regression/recorder.py +9 -0
  267. mannf/regression/replayer.py +9 -0
  268. mannf/security/__init__.py +7 -0
  269. mannf/security/belief_guided.py +9 -0
  270. mannf/security/checks/__init__.py +7 -0
  271. mannf/security/checks/base.py +9 -0
  272. mannf/security/checks/bfla.py +9 -0
  273. mannf/security/checks/bola.py +9 -0
  274. mannf/security/checks/bopla.py +9 -0
  275. mannf/security/checks/broken_auth.py +9 -0
  276. mannf/security/checks/graphql_security.py +9 -0
  277. mannf/security/checks/inventory.py +9 -0
  278. mannf/security/checks/misconfig.py +9 -0
  279. mannf/security/checks/resource_consumption.py +9 -0
  280. mannf/security/checks/sensitive_flows.py +9 -0
  281. mannf/security/checks/ssrf.py +9 -0
  282. mannf/security/checks/unsafe_consumption.py +9 -0
  283. mannf/security/models.py +9 -0
  284. mannf/security/reporter.py +9 -0
  285. mannf/security/scanner.py +9 -0
  286. mannf/server.py +9 -0
  287. mannf/testing/__init__.py +7 -0
  288. mannf/testing/adaptive_controller.py +9 -0
  289. mannf/testing/models.py +9 -0
  290. mannf/weights/__init__.py +7 -0
  291. mannf/weights/registry.py +9 -0
  292. mannf/weights/store.py +9 -0
  293. nat_engine-1.dist-info/METADATA +555 -0
  294. nat_engine-1.dist-info/RECORD +299 -0
  295. nat_engine-1.dist-info/WHEEL +5 -0
  296. nat_engine-1.dist-info/entry_points.txt +4 -0
  297. nat_engine-1.dist-info/licenses/LICENSE +651 -0
  298. nat_engine-1.dist-info/licenses/NOTICE +178 -0
  299. nat_engine-1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,460 @@
1
+ # Copyright (C) 2026 Brad Guider
2
+ # This file is part of NAT (Neural Agent Testing Framework).
3
+ # Licensed under the AGPL-3.0. See LICENSE for details.
4
+ # Commercial licensing available — see COMMERCIAL_LICENSE.md.
5
+
6
+ """Pydantic models for the NAT web dashboard data layer."""
7
+
8
+ from __future__ import annotations
9
+
10
+ from typing import Any, Dict, List, Optional
11
+
12
+ from pydantic import BaseModel, Field
13
+
14
+
15
+ class DashboardSummary(BaseModel):
16
+ """Overall system statistics shown in the overview bar."""
17
+
18
+ total_scans: int = 0
19
+ endpoints_discovered: int = 0
20
+ anomalies_found: int = 0
21
+ avg_risk_score: float = 0.0
22
+ total_tests_run: int = 0
23
+ pass_rate: float = 0.0
24
+ active_anomalies: int = 0
25
+ last_scan_at: Optional[str] = None
26
+ health_score: float = 1.0
27
+
28
+
29
+ class EndpointRiskCard(BaseModel):
30
+ """Per-endpoint card data for the risk heatmap."""
31
+
32
+ endpoint: str
33
+ risk_score: float
34
+ fault_rate: float
35
+ belief_signal: float
36
+ latency_signal: float
37
+ diversity_signal: float
38
+ trend: str
39
+ run_count: int
40
+ fault_count: int
41
+ anomaly_count: int = 0
42
+ last_test_result: Optional[str] = None
43
+
44
+
45
+ class BeliefStateSnapshot(BaseModel):
46
+ """Agent belief state data formatted for visualization."""
47
+
48
+ agent_id: str
49
+ agent_role: str
50
+ beliefs: Dict[str, Any] = Field(default_factory=dict)
51
+ active: bool = True
52
+ current_task: Optional[str] = None
53
+ endpoints_assigned: List[str] = Field(default_factory=list)
54
+ confidence: float = 0.5
55
+ # Telemetry-enriched fields (populated by the real-time broadcast path)
56
+ confidence_per_service: Dict[str, float] = Field(default_factory=dict)
57
+ intentions: List[Dict[str, Any]] = Field(default_factory=list)
58
+ desires: Dict[str, float] = Field(default_factory=dict)
59
+ entropy: float = 0.0
60
+ timestamp: Optional[str] = None
61
+
62
+
63
+ class AnomalyTimelineEntry(BaseModel):
64
+ """An anomaly event for the timeline display."""
65
+
66
+ endpoint: str
67
+ anomaly_type: str
68
+ severity: str
69
+ score: float
70
+ description: str
71
+ detected_at: str
72
+ scan_id: Optional[str] = None
73
+ details: Dict[str, Any] = Field(default_factory=dict)
74
+
75
+
76
+ # ---------------------------------------------------------------------------
77
+ # Functional Testing Results models
78
+ # ---------------------------------------------------------------------------
79
+
80
+
81
+ class VisualDiffEntry(BaseModel):
82
+ """A single visual regression comparison result."""
83
+
84
+ task_id: str
85
+ baseline_url: Optional[str] = None
86
+ current_url: Optional[str] = None
87
+ diff_url: Optional[str] = None
88
+ diff_percent: float = 0.0
89
+ passed: bool = True
90
+
91
+
92
+ class A11yViolationSummary(BaseModel):
93
+ """Aggregated accessibility violation counts by severity."""
94
+
95
+ critical: int = 0
96
+ serious: int = 0
97
+ moderate: int = 0
98
+ minor: int = 0
99
+ total: int = 0
100
+ sample_violations: List[Dict[str, Any]] = Field(default_factory=list)
101
+
102
+
103
+ class PerfMetrics(BaseModel):
104
+ """Performance scorecard (Core Web Vitals + TTFB)."""
105
+
106
+ lcp_ms: Optional[float] = None # Largest Contentful Paint
107
+ fid_ms: Optional[float] = None # First Input Delay
108
+ cls: Optional[float] = None # Cumulative Layout Shift
109
+ ttfb_ms: Optional[float] = None # Time to First Byte
110
+
111
+
112
+ class FunctionalTestItem(BaseModel):
113
+ """Per-task outcome row in the functional testing results."""
114
+
115
+ task_id: str
116
+ task_name: str
117
+ passed: bool
118
+ duration_ms: Optional[float] = None
119
+ error: Optional[str] = None
120
+ artifact_url: Optional[str] = None
121
+
122
+
123
+ class FunctionalTestResult(BaseModel):
124
+ """Aggregated functional testing results for the dashboard."""
125
+
126
+ run_id: Optional[str] = None
127
+ started_at: Optional[str] = None
128
+ completed_at: Optional[str] = None
129
+ total: int = 0
130
+ passed: int = 0
131
+ failed: int = 0
132
+ pass_rate: float = 0.0
133
+ items: List[FunctionalTestItem] = Field(default_factory=list)
134
+ visual_diffs: List[VisualDiffEntry] = Field(default_factory=list)
135
+ a11y: Optional[A11yViolationSummary] = None
136
+ perf: Optional[PerfMetrics] = None
137
+
138
+
139
+ # ---------------------------------------------------------------------------
140
+ # Usage & Billing models
141
+ # ---------------------------------------------------------------------------
142
+
143
+
144
+ class InvoiceEntry(BaseModel):
145
+ """A single invoice row for the billing tab."""
146
+
147
+ invoice_id: str
148
+ date: str
149
+ amount_cents: int
150
+ currency: str = "usd"
151
+ status: str # "paid", "open", "void", etc.
152
+ pdf_url: Optional[str] = None
153
+
154
+
155
+ class UsageSummary(BaseModel):
156
+ """Usage gauge data for the billing tab."""
157
+
158
+ plan_name: str = "Free"
159
+ plan_tier: str = "free"
160
+ functional_used: int = 0
161
+ functional_quota: int = 0
162
+ security_used: int = 0
163
+ security_quota: int = 0
164
+ functional_percent: float = 0.0
165
+ security_percent: float = 0.0
166
+ approaching_limit: bool = False
167
+ quota_reset_date: Optional[str] = None
168
+ stripe_portal_url: Optional[str] = None
169
+ invoices: List[InvoiceEntry] = Field(default_factory=list)
170
+
171
+
172
+ # ---------------------------------------------------------------------------
173
+ # Onboarding / Getting Started models
174
+ # ---------------------------------------------------------------------------
175
+
176
+
177
+ class OnboardingStep(BaseModel):
178
+ """A single step in the onboarding checklist."""
179
+
180
+ step: int
181
+ title: str
182
+ description: str
183
+ completed: bool = False
184
+ action_label: Optional[str] = None
185
+ action_url: Optional[str] = None
186
+ code_snippet: Optional[str] = None
187
+
188
+
189
+ class OnboardingStatus(BaseModel):
190
+ """Onboarding checklist completion state."""
191
+
192
+ steps: List[OnboardingStep] = Field(default_factory=list)
193
+ completed_count: int = 0
194
+ total_count: int = 0
195
+ api_key_masked: Optional[str] = None
196
+
197
+
198
+ # ---------------------------------------------------------------------------
199
+ # Scenario Suggestion / Discovery models (Phase 3)
200
+ # ---------------------------------------------------------------------------
201
+
202
+
203
+ class DiscoveryRequest(BaseModel):
204
+ """Request body for POST /api/v1/discover."""
205
+
206
+ url: str
207
+ max_pages: int = 50
208
+ max_depth: int = 5
209
+ include_negative: bool = True
210
+ include_boundary: bool = True
211
+ # Optional LLM configuration for AI-enhanced scenario generation
212
+ llm_provider: Optional[str] = None # e.g. "openai" or "anthropic"
213
+ llm_api_key: Optional[str] = None
214
+ llm_model: Optional[str] = None
215
+
216
+
217
+ class AutonomousRequest(BaseModel):
218
+ """Request body for POST /api/v1/autonomous/start."""
219
+
220
+ url: str
221
+ strategy: str = "all" # "all", "high_risk", "new_changed", "belief_targeted"
222
+ max_iterations: int = 5
223
+ max_duration_s: float = 600.0
224
+ max_pages: int = 50
225
+ max_depth: int = 5
226
+ headless: bool = True
227
+ risk_threshold: float = 0.6
228
+ llm_provider: Optional[str] = None
229
+ llm_api_key: Optional[str] = None
230
+ llm_model: Optional[str] = None
231
+ # Deploy / commit attribution (Phase 6.3)
232
+ build_id: Optional[str] = None
233
+ commit_sha: Optional[str] = None
234
+ deploy_tag: Optional[str] = None
235
+
236
+
237
+ class DiscoveryScenario(BaseModel):
238
+ """A single suggested functional test scenario."""
239
+
240
+ scenario_id: str
241
+ url: str
242
+ steps: List[Dict[str, Any]] = Field(default_factory=list)
243
+ metadata: Dict[str, Any] = Field(default_factory=dict)
244
+ selected: bool = True
245
+ confidence: float = 0.5
246
+ risk_score: float = 0.5
247
+
248
+
249
+ class DiscoveryResult(BaseModel):
250
+ """In-memory record for a single discovery crawl + scenario generation run."""
251
+
252
+ discovery_id: str
253
+ status: str # "running", "complete", "failed"
254
+ base_url: str
255
+ scenarios: List[DiscoveryScenario] = Field(default_factory=list)
256
+ stats: Dict[str, int] = Field(default_factory=dict)
257
+ created_at: str
258
+ error: Optional[str] = None
259
+
260
+
261
+ # ---------------------------------------------------------------------------
262
+ # Bug Filing / Triage models (Phase 6.4)
263
+ # ---------------------------------------------------------------------------
264
+
265
+
266
+ class BugFilingConfig(BaseModel):
267
+ """Configuration for the auto-bug-filing pipeline.
268
+
269
+ Controls *which* failures get filed, *where* they go, and whether they
270
+ need manual approval before a ticket is created.
271
+ """
272
+
273
+ enabled: bool = False
274
+ """Master switch — no tickets are created when ``False``."""
275
+
276
+ target_system: str = "github"
277
+ """Ticket destination: ``"github"``, ``"jira"``, or ``"webhook"``."""
278
+
279
+ exporter_config: Dict[str, Any] = Field(default_factory=dict)
280
+ """System-specific config passed directly to the chosen exporter plugin."""
281
+
282
+ severity_threshold: str = "high"
283
+ """Minimum failure severity to file (``"critical"``, ``"high"``, ``"medium"``, ``"low"``)."""
284
+
285
+ auto_file: bool = True
286
+ """When ``True``, tickets are created automatically.
287
+ When ``False``, failures land in the pending-approval queue."""
288
+
289
+ deduplicate: bool = True
290
+ """When ``True``, the pipeline checks for an existing open ticket with the
291
+ same fingerprint before creating a new one."""
292
+
293
+
294
+ class FiledBugEntry(BaseModel):
295
+ """A successfully auto-filed bug ticket."""
296
+
297
+ bug_id: str
298
+ """Internal UUID for this filing record."""
299
+
300
+ run_id: str
301
+ """Autonomous run that produced the failure."""
302
+
303
+ fingerprint: str
304
+ """Deterministic sha256 fingerprint of the failure."""
305
+
306
+ failure: Dict[str, Any] = Field(default_factory=dict)
307
+ """The original failure dict from ``AutonomousRunReport.unique_failures``."""
308
+
309
+ target_system: str
310
+ """Exporter used: ``"github"``, ``"jira"``, etc."""
311
+
312
+ external_id: Optional[str] = None
313
+ """Ticket ID in the external system (e.g. ``"NAT-42"`` or ``"99"``)."""
314
+
315
+ external_url: Optional[str] = None
316
+ """Direct link to the ticket in the external system."""
317
+
318
+ severity: str = "low"
319
+ filed_at: str = ""
320
+ was_duplicate: bool = False
321
+ """``True`` when this was a known duplicate — a comment was added instead of a new ticket."""
322
+
323
+
324
+ class PendingBugEntry(BaseModel):
325
+ """A failure awaiting manual approval before a ticket is created."""
326
+
327
+ bug_id: str
328
+ """Internal UUID for this pending record."""
329
+
330
+ run_id: str
331
+ """Autonomous run that produced the failure."""
332
+
333
+ fingerprint: str
334
+ """Deterministic sha256 fingerprint of the failure."""
335
+
336
+ failure: Dict[str, Any] = Field(default_factory=dict)
337
+ """The original failure dict."""
338
+
339
+ severity: str = "low"
340
+ queued_at: str = ""
341
+ status: str = "pending"
342
+ """Lifecycle state: ``"pending"``, ``"approved"``, ``"dismissed"``."""
343
+
344
+
345
+ # ---------------------------------------------------------------------------
346
+ # ML/LLM Diagnostics models (Phase 6.5)
347
+ # ---------------------------------------------------------------------------
348
+
349
+
350
+ class BeliefTrend(BaseModel):
351
+ """Time-series entry for a single page's fault_likelihood over time."""
352
+
353
+ run_id: str
354
+ iteration: int
355
+ page_key: str
356
+ fault_likelihood: float
357
+ timestamp: str
358
+
359
+
360
+ class FlakinessSummary(BaseModel):
361
+ """Flakiness statistics for a single page+scenario pair."""
362
+
363
+ page_key: str
364
+ scenario_id: str
365
+ is_flaky: bool
366
+ flake_rate: float
367
+ total_runs: int
368
+ pass_count: int
369
+ fail_count: int
370
+ alternations: int
371
+
372
+
373
+ class FailureCluster(BaseModel):
374
+ """A cluster of failures sharing a similar error signature."""
375
+
376
+ cluster_id: str
377
+ label: str
378
+ representative_error: str
379
+ pages: List[str] = Field(default_factory=list)
380
+ size: int
381
+ failures: List[Dict[str, Any]] = Field(default_factory=list)
382
+
383
+
384
+ class RootCauseSuggestion(BaseModel):
385
+ """LLM-generated root cause suggestion for a failure."""
386
+
387
+ task_id: str = ""
388
+ url: str = ""
389
+ page: str = ""
390
+ likely_cause: str
391
+ suggested_fix: str
392
+ confidence: float
393
+ files_to_check: List[str] = Field(default_factory=list)
394
+
395
+
396
+ class PredictiveRiskScore(BaseModel):
397
+ """Predicted failure probability for a page in the next run."""
398
+
399
+ page_key: str
400
+ predicted_failure_probability: float
401
+ belief_momentum: float
402
+ recent_failure_density: float
403
+ confidence: float
404
+
405
+
406
+ # ---------------------------------------------------------------------------
407
+ # Phase 7.4 — Confidence Calibration & Self-Validation models
408
+ # ---------------------------------------------------------------------------
409
+
410
+
411
+ class DismissedFinding(BaseModel):
412
+ """A finding dismissed by the user as a false positive."""
413
+
414
+ finding_id: str
415
+ """Unique identifier of the dismissed finding (from ``unique_failures`` or ``browser_security_findings``)."""
416
+
417
+ endpoint: str = ""
418
+ """Endpoint path/key the finding was associated with."""
419
+
420
+ dismissed_by: str = "user"
421
+ """Who dismissed the finding (user identifier or ``"user"`` if anonymous)."""
422
+
423
+ dismissed_at: str = ""
424
+ """ISO-8601 timestamp of the dismissal."""
425
+
426
+ run_id: str = ""
427
+ """Autonomous run that produced the finding."""
428
+
429
+ reason: str = ""
430
+ """Optional free-text reason supplied by the user."""
431
+
432
+
433
+ class CalibrationBucket(BaseModel):
434
+ """A single bucket in the predicted-vs-actual reliability curve.
435
+
436
+ The bucket covers predictions in ``[bucket_low, bucket_high)``.
437
+ """
438
+
439
+ bucket_low: float
440
+ bucket_high: float
441
+ predicted_count: int
442
+ """Number of predictions falling in this bucket."""
443
+ actual_failure_rate: Optional[float] = None
444
+ """Observed fraction of failures among the predictions in this bucket.
445
+ ``None`` when no actual outcomes are available (sparse data)."""
446
+ mean_predicted: Optional[float] = None
447
+ """Mean predicted failure probability within this bucket."""
448
+
449
+
450
+ class CalibrationReport(BaseModel):
451
+ """Predicted-vs-actual reliability curve for the calibration dashboard view."""
452
+
453
+ buckets: List[CalibrationBucket] = Field(default_factory=list)
454
+ total_predictions: int = 0
455
+ total_with_outcomes: int = 0
456
+ brier_score: Optional[float] = None
457
+ """Mean squared error between predicted probabilities and actual outcomes.
458
+ Lower is better (0 = perfect). ``None`` when no actual outcomes are available."""
459
+ generated_at: str = ""
460
+