attune-ai 2.0.0__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 (457) hide show
  1. attune/__init__.py +358 -0
  2. attune/adaptive/__init__.py +13 -0
  3. attune/adaptive/task_complexity.py +127 -0
  4. attune/agent_monitoring.py +414 -0
  5. attune/cache/__init__.py +117 -0
  6. attune/cache/base.py +166 -0
  7. attune/cache/dependency_manager.py +256 -0
  8. attune/cache/hash_only.py +251 -0
  9. attune/cache/hybrid.py +457 -0
  10. attune/cache/storage.py +285 -0
  11. attune/cache_monitor.py +356 -0
  12. attune/cache_stats.py +298 -0
  13. attune/cli/__init__.py +152 -0
  14. attune/cli/__main__.py +12 -0
  15. attune/cli/commands/__init__.py +1 -0
  16. attune/cli/commands/batch.py +264 -0
  17. attune/cli/commands/cache.py +248 -0
  18. attune/cli/commands/help.py +331 -0
  19. attune/cli/commands/info.py +140 -0
  20. attune/cli/commands/inspect.py +436 -0
  21. attune/cli/commands/inspection.py +57 -0
  22. attune/cli/commands/memory.py +48 -0
  23. attune/cli/commands/metrics.py +92 -0
  24. attune/cli/commands/orchestrate.py +184 -0
  25. attune/cli/commands/patterns.py +207 -0
  26. attune/cli/commands/profiling.py +202 -0
  27. attune/cli/commands/provider.py +98 -0
  28. attune/cli/commands/routing.py +285 -0
  29. attune/cli/commands/setup.py +96 -0
  30. attune/cli/commands/status.py +235 -0
  31. attune/cli/commands/sync.py +166 -0
  32. attune/cli/commands/tier.py +121 -0
  33. attune/cli/commands/utilities.py +114 -0
  34. attune/cli/commands/workflow.py +579 -0
  35. attune/cli/core.py +32 -0
  36. attune/cli/parsers/__init__.py +68 -0
  37. attune/cli/parsers/batch.py +118 -0
  38. attune/cli/parsers/cache.py +65 -0
  39. attune/cli/parsers/help.py +41 -0
  40. attune/cli/parsers/info.py +26 -0
  41. attune/cli/parsers/inspect.py +66 -0
  42. attune/cli/parsers/metrics.py +42 -0
  43. attune/cli/parsers/orchestrate.py +61 -0
  44. attune/cli/parsers/patterns.py +54 -0
  45. attune/cli/parsers/provider.py +40 -0
  46. attune/cli/parsers/routing.py +110 -0
  47. attune/cli/parsers/setup.py +42 -0
  48. attune/cli/parsers/status.py +47 -0
  49. attune/cli/parsers/sync.py +31 -0
  50. attune/cli/parsers/tier.py +33 -0
  51. attune/cli/parsers/workflow.py +77 -0
  52. attune/cli/utils/__init__.py +1 -0
  53. attune/cli/utils/data.py +242 -0
  54. attune/cli/utils/helpers.py +68 -0
  55. attune/cli_legacy.py +3957 -0
  56. attune/cli_minimal.py +1159 -0
  57. attune/cli_router.py +437 -0
  58. attune/cli_unified.py +814 -0
  59. attune/config/__init__.py +66 -0
  60. attune/config/xml_config.py +286 -0
  61. attune/config.py +545 -0
  62. attune/coordination.py +870 -0
  63. attune/core.py +1511 -0
  64. attune/core_modules/__init__.py +15 -0
  65. attune/cost_tracker.py +626 -0
  66. attune/dashboard/__init__.py +41 -0
  67. attune/dashboard/app.py +512 -0
  68. attune/dashboard/simple_server.py +435 -0
  69. attune/dashboard/standalone_server.py +547 -0
  70. attune/discovery.py +306 -0
  71. attune/emergence.py +306 -0
  72. attune/exceptions.py +123 -0
  73. attune/feedback_loops.py +373 -0
  74. attune/hot_reload/README.md +473 -0
  75. attune/hot_reload/__init__.py +62 -0
  76. attune/hot_reload/config.py +83 -0
  77. attune/hot_reload/integration.py +229 -0
  78. attune/hot_reload/reloader.py +298 -0
  79. attune/hot_reload/watcher.py +183 -0
  80. attune/hot_reload/websocket.py +177 -0
  81. attune/levels.py +577 -0
  82. attune/leverage_points.py +441 -0
  83. attune/logging_config.py +261 -0
  84. attune/mcp/__init__.py +10 -0
  85. attune/mcp/server.py +506 -0
  86. attune/memory/__init__.py +237 -0
  87. attune/memory/claude_memory.py +469 -0
  88. attune/memory/config.py +224 -0
  89. attune/memory/control_panel.py +1290 -0
  90. attune/memory/control_panel_support.py +145 -0
  91. attune/memory/cross_session.py +845 -0
  92. attune/memory/edges.py +179 -0
  93. attune/memory/encryption.py +159 -0
  94. attune/memory/file_session.py +770 -0
  95. attune/memory/graph.py +570 -0
  96. attune/memory/long_term.py +913 -0
  97. attune/memory/long_term_types.py +99 -0
  98. attune/memory/mixins/__init__.py +25 -0
  99. attune/memory/mixins/backend_init_mixin.py +249 -0
  100. attune/memory/mixins/capabilities_mixin.py +208 -0
  101. attune/memory/mixins/handoff_mixin.py +208 -0
  102. attune/memory/mixins/lifecycle_mixin.py +49 -0
  103. attune/memory/mixins/long_term_mixin.py +352 -0
  104. attune/memory/mixins/promotion_mixin.py +109 -0
  105. attune/memory/mixins/short_term_mixin.py +182 -0
  106. attune/memory/nodes.py +179 -0
  107. attune/memory/redis_bootstrap.py +540 -0
  108. attune/memory/security/__init__.py +31 -0
  109. attune/memory/security/audit_logger.py +932 -0
  110. attune/memory/security/pii_scrubber.py +640 -0
  111. attune/memory/security/secrets_detector.py +678 -0
  112. attune/memory/short_term.py +2192 -0
  113. attune/memory/simple_storage.py +302 -0
  114. attune/memory/storage/__init__.py +15 -0
  115. attune/memory/storage_backend.py +167 -0
  116. attune/memory/summary_index.py +583 -0
  117. attune/memory/types.py +446 -0
  118. attune/memory/unified.py +182 -0
  119. attune/meta_workflows/__init__.py +74 -0
  120. attune/meta_workflows/agent_creator.py +248 -0
  121. attune/meta_workflows/builtin_templates.py +567 -0
  122. attune/meta_workflows/cli_commands/__init__.py +56 -0
  123. attune/meta_workflows/cli_commands/agent_commands.py +321 -0
  124. attune/meta_workflows/cli_commands/analytics_commands.py +442 -0
  125. attune/meta_workflows/cli_commands/config_commands.py +232 -0
  126. attune/meta_workflows/cli_commands/memory_commands.py +182 -0
  127. attune/meta_workflows/cli_commands/template_commands.py +354 -0
  128. attune/meta_workflows/cli_commands/workflow_commands.py +382 -0
  129. attune/meta_workflows/cli_meta_workflows.py +59 -0
  130. attune/meta_workflows/form_engine.py +292 -0
  131. attune/meta_workflows/intent_detector.py +409 -0
  132. attune/meta_workflows/models.py +569 -0
  133. attune/meta_workflows/pattern_learner.py +738 -0
  134. attune/meta_workflows/plan_generator.py +384 -0
  135. attune/meta_workflows/session_context.py +397 -0
  136. attune/meta_workflows/template_registry.py +229 -0
  137. attune/meta_workflows/workflow.py +984 -0
  138. attune/metrics/__init__.py +12 -0
  139. attune/metrics/collector.py +31 -0
  140. attune/metrics/prompt_metrics.py +194 -0
  141. attune/models/__init__.py +172 -0
  142. attune/models/__main__.py +13 -0
  143. attune/models/adaptive_routing.py +437 -0
  144. attune/models/auth_cli.py +444 -0
  145. attune/models/auth_strategy.py +450 -0
  146. attune/models/cli.py +655 -0
  147. attune/models/empathy_executor.py +354 -0
  148. attune/models/executor.py +257 -0
  149. attune/models/fallback.py +762 -0
  150. attune/models/provider_config.py +282 -0
  151. attune/models/registry.py +472 -0
  152. attune/models/tasks.py +359 -0
  153. attune/models/telemetry/__init__.py +71 -0
  154. attune/models/telemetry/analytics.py +594 -0
  155. attune/models/telemetry/backend.py +196 -0
  156. attune/models/telemetry/data_models.py +431 -0
  157. attune/models/telemetry/storage.py +489 -0
  158. attune/models/token_estimator.py +420 -0
  159. attune/models/validation.py +280 -0
  160. attune/monitoring/__init__.py +52 -0
  161. attune/monitoring/alerts.py +946 -0
  162. attune/monitoring/alerts_cli.py +448 -0
  163. attune/monitoring/multi_backend.py +271 -0
  164. attune/monitoring/otel_backend.py +362 -0
  165. attune/optimization/__init__.py +19 -0
  166. attune/optimization/context_optimizer.py +272 -0
  167. attune/orchestration/__init__.py +67 -0
  168. attune/orchestration/agent_templates.py +707 -0
  169. attune/orchestration/config_store.py +499 -0
  170. attune/orchestration/execution_strategies.py +2111 -0
  171. attune/orchestration/meta_orchestrator.py +1168 -0
  172. attune/orchestration/pattern_learner.py +696 -0
  173. attune/orchestration/real_tools.py +931 -0
  174. attune/pattern_cache.py +187 -0
  175. attune/pattern_library.py +542 -0
  176. attune/patterns/debugging/all_patterns.json +81 -0
  177. attune/patterns/debugging/workflow_20260107_1770825e.json +77 -0
  178. attune/patterns/refactoring_memory.json +89 -0
  179. attune/persistence.py +564 -0
  180. attune/platform_utils.py +265 -0
  181. attune/plugins/__init__.py +28 -0
  182. attune/plugins/base.py +361 -0
  183. attune/plugins/registry.py +268 -0
  184. attune/project_index/__init__.py +32 -0
  185. attune/project_index/cli.py +335 -0
  186. attune/project_index/index.py +667 -0
  187. attune/project_index/models.py +504 -0
  188. attune/project_index/reports.py +474 -0
  189. attune/project_index/scanner.py +777 -0
  190. attune/project_index/scanner_parallel.py +291 -0
  191. attune/prompts/__init__.py +61 -0
  192. attune/prompts/config.py +77 -0
  193. attune/prompts/context.py +177 -0
  194. attune/prompts/parser.py +285 -0
  195. attune/prompts/registry.py +313 -0
  196. attune/prompts/templates.py +208 -0
  197. attune/redis_config.py +302 -0
  198. attune/redis_memory.py +799 -0
  199. attune/resilience/__init__.py +56 -0
  200. attune/resilience/circuit_breaker.py +256 -0
  201. attune/resilience/fallback.py +179 -0
  202. attune/resilience/health.py +300 -0
  203. attune/resilience/retry.py +209 -0
  204. attune/resilience/timeout.py +135 -0
  205. attune/routing/__init__.py +43 -0
  206. attune/routing/chain_executor.py +433 -0
  207. attune/routing/classifier.py +217 -0
  208. attune/routing/smart_router.py +234 -0
  209. attune/routing/workflow_registry.py +343 -0
  210. attune/scaffolding/README.md +589 -0
  211. attune/scaffolding/__init__.py +35 -0
  212. attune/scaffolding/__main__.py +14 -0
  213. attune/scaffolding/cli.py +240 -0
  214. attune/scaffolding/templates/base_wizard.py.jinja2 +121 -0
  215. attune/scaffolding/templates/coach_wizard.py.jinja2 +321 -0
  216. attune/scaffolding/templates/domain_wizard.py.jinja2 +408 -0
  217. attune/scaffolding/templates/linear_flow_wizard.py.jinja2 +203 -0
  218. attune/socratic/__init__.py +256 -0
  219. attune/socratic/ab_testing.py +958 -0
  220. attune/socratic/blueprint.py +533 -0
  221. attune/socratic/cli.py +703 -0
  222. attune/socratic/collaboration.py +1114 -0
  223. attune/socratic/domain_templates.py +924 -0
  224. attune/socratic/embeddings.py +738 -0
  225. attune/socratic/engine.py +794 -0
  226. attune/socratic/explainer.py +682 -0
  227. attune/socratic/feedback.py +772 -0
  228. attune/socratic/forms.py +629 -0
  229. attune/socratic/generator.py +732 -0
  230. attune/socratic/llm_analyzer.py +637 -0
  231. attune/socratic/mcp_server.py +702 -0
  232. attune/socratic/session.py +312 -0
  233. attune/socratic/storage.py +667 -0
  234. attune/socratic/success.py +730 -0
  235. attune/socratic/visual_editor.py +860 -0
  236. attune/socratic/web_ui.py +958 -0
  237. attune/telemetry/__init__.py +39 -0
  238. attune/telemetry/agent_coordination.py +475 -0
  239. attune/telemetry/agent_tracking.py +367 -0
  240. attune/telemetry/approval_gates.py +545 -0
  241. attune/telemetry/cli.py +1231 -0
  242. attune/telemetry/commands/__init__.py +14 -0
  243. attune/telemetry/commands/dashboard_commands.py +696 -0
  244. attune/telemetry/event_streaming.py +409 -0
  245. attune/telemetry/feedback_loop.py +567 -0
  246. attune/telemetry/usage_tracker.py +591 -0
  247. attune/templates.py +754 -0
  248. attune/test_generator/__init__.py +38 -0
  249. attune/test_generator/__main__.py +14 -0
  250. attune/test_generator/cli.py +234 -0
  251. attune/test_generator/generator.py +355 -0
  252. attune/test_generator/risk_analyzer.py +216 -0
  253. attune/test_generator/templates/unit_test.py.jinja2 +272 -0
  254. attune/tier_recommender.py +384 -0
  255. attune/tools.py +183 -0
  256. attune/trust/__init__.py +28 -0
  257. attune/trust/circuit_breaker.py +579 -0
  258. attune/trust_building.py +527 -0
  259. attune/validation/__init__.py +19 -0
  260. attune/validation/xml_validator.py +281 -0
  261. attune/vscode_bridge.py +173 -0
  262. attune/workflow_commands.py +780 -0
  263. attune/workflow_patterns/__init__.py +33 -0
  264. attune/workflow_patterns/behavior.py +249 -0
  265. attune/workflow_patterns/core.py +76 -0
  266. attune/workflow_patterns/output.py +99 -0
  267. attune/workflow_patterns/registry.py +255 -0
  268. attune/workflow_patterns/structural.py +288 -0
  269. attune/workflows/__init__.py +539 -0
  270. attune/workflows/autonomous_test_gen.py +1268 -0
  271. attune/workflows/base.py +2667 -0
  272. attune/workflows/batch_processing.py +342 -0
  273. attune/workflows/bug_predict.py +1084 -0
  274. attune/workflows/builder.py +273 -0
  275. attune/workflows/caching.py +253 -0
  276. attune/workflows/code_review.py +1048 -0
  277. attune/workflows/code_review_adapters.py +312 -0
  278. attune/workflows/code_review_pipeline.py +722 -0
  279. attune/workflows/config.py +645 -0
  280. attune/workflows/dependency_check.py +644 -0
  281. attune/workflows/document_gen/__init__.py +25 -0
  282. attune/workflows/document_gen/config.py +30 -0
  283. attune/workflows/document_gen/report_formatter.py +162 -0
  284. attune/workflows/document_gen/workflow.py +1426 -0
  285. attune/workflows/document_manager.py +216 -0
  286. attune/workflows/document_manager_README.md +134 -0
  287. attune/workflows/documentation_orchestrator.py +1205 -0
  288. attune/workflows/history.py +510 -0
  289. attune/workflows/keyboard_shortcuts/__init__.py +39 -0
  290. attune/workflows/keyboard_shortcuts/generators.py +391 -0
  291. attune/workflows/keyboard_shortcuts/parsers.py +416 -0
  292. attune/workflows/keyboard_shortcuts/prompts.py +295 -0
  293. attune/workflows/keyboard_shortcuts/schema.py +193 -0
  294. attune/workflows/keyboard_shortcuts/workflow.py +509 -0
  295. attune/workflows/llm_base.py +363 -0
  296. attune/workflows/manage_docs.py +87 -0
  297. attune/workflows/manage_docs_README.md +134 -0
  298. attune/workflows/manage_documentation.py +821 -0
  299. attune/workflows/new_sample_workflow1.py +149 -0
  300. attune/workflows/new_sample_workflow1_README.md +150 -0
  301. attune/workflows/orchestrated_health_check.py +849 -0
  302. attune/workflows/orchestrated_release_prep.py +600 -0
  303. attune/workflows/output.py +413 -0
  304. attune/workflows/perf_audit.py +863 -0
  305. attune/workflows/pr_review.py +762 -0
  306. attune/workflows/progress.py +785 -0
  307. attune/workflows/progress_server.py +322 -0
  308. attune/workflows/progressive/README 2.md +454 -0
  309. attune/workflows/progressive/README.md +454 -0
  310. attune/workflows/progressive/__init__.py +82 -0
  311. attune/workflows/progressive/cli.py +219 -0
  312. attune/workflows/progressive/core.py +488 -0
  313. attune/workflows/progressive/orchestrator.py +723 -0
  314. attune/workflows/progressive/reports.py +520 -0
  315. attune/workflows/progressive/telemetry.py +274 -0
  316. attune/workflows/progressive/test_gen.py +495 -0
  317. attune/workflows/progressive/workflow.py +589 -0
  318. attune/workflows/refactor_plan.py +694 -0
  319. attune/workflows/release_prep.py +895 -0
  320. attune/workflows/release_prep_crew.py +969 -0
  321. attune/workflows/research_synthesis.py +404 -0
  322. attune/workflows/routing.py +168 -0
  323. attune/workflows/secure_release.py +593 -0
  324. attune/workflows/security_adapters.py +297 -0
  325. attune/workflows/security_audit.py +1329 -0
  326. attune/workflows/security_audit_phase3.py +355 -0
  327. attune/workflows/seo_optimization.py +633 -0
  328. attune/workflows/step_config.py +234 -0
  329. attune/workflows/telemetry_mixin.py +269 -0
  330. attune/workflows/test5.py +125 -0
  331. attune/workflows/test5_README.md +158 -0
  332. attune/workflows/test_coverage_boost_crew.py +849 -0
  333. attune/workflows/test_gen/__init__.py +52 -0
  334. attune/workflows/test_gen/ast_analyzer.py +249 -0
  335. attune/workflows/test_gen/config.py +88 -0
  336. attune/workflows/test_gen/data_models.py +38 -0
  337. attune/workflows/test_gen/report_formatter.py +289 -0
  338. attune/workflows/test_gen/test_templates.py +381 -0
  339. attune/workflows/test_gen/workflow.py +655 -0
  340. attune/workflows/test_gen.py +54 -0
  341. attune/workflows/test_gen_behavioral.py +477 -0
  342. attune/workflows/test_gen_parallel.py +341 -0
  343. attune/workflows/test_lifecycle.py +526 -0
  344. attune/workflows/test_maintenance.py +627 -0
  345. attune/workflows/test_maintenance_cli.py +590 -0
  346. attune/workflows/test_maintenance_crew.py +840 -0
  347. attune/workflows/test_runner.py +622 -0
  348. attune/workflows/tier_tracking.py +531 -0
  349. attune/workflows/xml_enhanced_crew.py +285 -0
  350. attune_ai-2.0.0.dist-info/METADATA +1026 -0
  351. attune_ai-2.0.0.dist-info/RECORD +457 -0
  352. attune_ai-2.0.0.dist-info/WHEEL +5 -0
  353. attune_ai-2.0.0.dist-info/entry_points.txt +26 -0
  354. attune_ai-2.0.0.dist-info/licenses/LICENSE +201 -0
  355. attune_ai-2.0.0.dist-info/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md +101 -0
  356. attune_ai-2.0.0.dist-info/top_level.txt +5 -0
  357. attune_healthcare/__init__.py +13 -0
  358. attune_healthcare/monitors/__init__.py +9 -0
  359. attune_healthcare/monitors/clinical_protocol_monitor.py +315 -0
  360. attune_healthcare/monitors/monitoring/__init__.py +44 -0
  361. attune_healthcare/monitors/monitoring/protocol_checker.py +300 -0
  362. attune_healthcare/monitors/monitoring/protocol_loader.py +214 -0
  363. attune_healthcare/monitors/monitoring/sensor_parsers.py +306 -0
  364. attune_healthcare/monitors/monitoring/trajectory_analyzer.py +389 -0
  365. attune_llm/README.md +553 -0
  366. attune_llm/__init__.py +28 -0
  367. attune_llm/agent_factory/__init__.py +53 -0
  368. attune_llm/agent_factory/adapters/__init__.py +85 -0
  369. attune_llm/agent_factory/adapters/autogen_adapter.py +312 -0
  370. attune_llm/agent_factory/adapters/crewai_adapter.py +483 -0
  371. attune_llm/agent_factory/adapters/haystack_adapter.py +298 -0
  372. attune_llm/agent_factory/adapters/langchain_adapter.py +362 -0
  373. attune_llm/agent_factory/adapters/langgraph_adapter.py +333 -0
  374. attune_llm/agent_factory/adapters/native.py +228 -0
  375. attune_llm/agent_factory/adapters/wizard_adapter.py +423 -0
  376. attune_llm/agent_factory/base.py +305 -0
  377. attune_llm/agent_factory/crews/__init__.py +67 -0
  378. attune_llm/agent_factory/crews/code_review.py +1113 -0
  379. attune_llm/agent_factory/crews/health_check.py +1262 -0
  380. attune_llm/agent_factory/crews/refactoring.py +1128 -0
  381. attune_llm/agent_factory/crews/security_audit.py +1018 -0
  382. attune_llm/agent_factory/decorators.py +287 -0
  383. attune_llm/agent_factory/factory.py +558 -0
  384. attune_llm/agent_factory/framework.py +193 -0
  385. attune_llm/agent_factory/memory_integration.py +328 -0
  386. attune_llm/agent_factory/resilient.py +320 -0
  387. attune_llm/agents_md/__init__.py +22 -0
  388. attune_llm/agents_md/loader.py +218 -0
  389. attune_llm/agents_md/parser.py +271 -0
  390. attune_llm/agents_md/registry.py +307 -0
  391. attune_llm/claude_memory.py +466 -0
  392. attune_llm/cli/__init__.py +8 -0
  393. attune_llm/cli/sync_claude.py +487 -0
  394. attune_llm/code_health.py +1313 -0
  395. attune_llm/commands/__init__.py +51 -0
  396. attune_llm/commands/context.py +375 -0
  397. attune_llm/commands/loader.py +301 -0
  398. attune_llm/commands/models.py +231 -0
  399. attune_llm/commands/parser.py +371 -0
  400. attune_llm/commands/registry.py +429 -0
  401. attune_llm/config/__init__.py +29 -0
  402. attune_llm/config/unified.py +291 -0
  403. attune_llm/context/__init__.py +22 -0
  404. attune_llm/context/compaction.py +455 -0
  405. attune_llm/context/manager.py +434 -0
  406. attune_llm/contextual_patterns.py +361 -0
  407. attune_llm/core.py +907 -0
  408. attune_llm/git_pattern_extractor.py +435 -0
  409. attune_llm/hooks/__init__.py +24 -0
  410. attune_llm/hooks/config.py +306 -0
  411. attune_llm/hooks/executor.py +289 -0
  412. attune_llm/hooks/registry.py +302 -0
  413. attune_llm/hooks/scripts/__init__.py +39 -0
  414. attune_llm/hooks/scripts/evaluate_session.py +201 -0
  415. attune_llm/hooks/scripts/first_time_init.py +285 -0
  416. attune_llm/hooks/scripts/pre_compact.py +207 -0
  417. attune_llm/hooks/scripts/session_end.py +183 -0
  418. attune_llm/hooks/scripts/session_start.py +163 -0
  419. attune_llm/hooks/scripts/suggest_compact.py +225 -0
  420. attune_llm/learning/__init__.py +30 -0
  421. attune_llm/learning/evaluator.py +438 -0
  422. attune_llm/learning/extractor.py +514 -0
  423. attune_llm/learning/storage.py +560 -0
  424. attune_llm/levels.py +227 -0
  425. attune_llm/pattern_confidence.py +414 -0
  426. attune_llm/pattern_resolver.py +272 -0
  427. attune_llm/pattern_summary.py +350 -0
  428. attune_llm/providers.py +967 -0
  429. attune_llm/routing/__init__.py +32 -0
  430. attune_llm/routing/model_router.py +362 -0
  431. attune_llm/security/IMPLEMENTATION_SUMMARY.md +413 -0
  432. attune_llm/security/PHASE2_COMPLETE.md +384 -0
  433. attune_llm/security/PHASE2_SECRETS_DETECTOR_COMPLETE.md +271 -0
  434. attune_llm/security/QUICK_REFERENCE.md +316 -0
  435. attune_llm/security/README.md +262 -0
  436. attune_llm/security/__init__.py +62 -0
  437. attune_llm/security/audit_logger.py +929 -0
  438. attune_llm/security/audit_logger_example.py +152 -0
  439. attune_llm/security/pii_scrubber.py +640 -0
  440. attune_llm/security/secrets_detector.py +678 -0
  441. attune_llm/security/secrets_detector_example.py +304 -0
  442. attune_llm/security/secure_memdocs.py +1192 -0
  443. attune_llm/security/secure_memdocs_example.py +278 -0
  444. attune_llm/session_status.py +745 -0
  445. attune_llm/state.py +246 -0
  446. attune_llm/utils/__init__.py +5 -0
  447. attune_llm/utils/tokens.py +349 -0
  448. attune_software/SOFTWARE_PLUGIN_README.md +57 -0
  449. attune_software/__init__.py +13 -0
  450. attune_software/cli/__init__.py +120 -0
  451. attune_software/cli/inspect.py +362 -0
  452. attune_software/cli.py +574 -0
  453. attune_software/plugin.py +188 -0
  454. workflow_scaffolding/__init__.py +11 -0
  455. workflow_scaffolding/__main__.py +12 -0
  456. workflow_scaffolding/cli.py +206 -0
  457. workflow_scaffolding/generator.py +265 -0
@@ -0,0 +1,216 @@
1
+ """Risk analyzer for test generation.
2
+
3
+ Analyzes workflow patterns to identify critical paths and determine
4
+ appropriate test coverage levels.
5
+
6
+ Copyright 2025 Smart AI Memory, LLC
7
+ Licensed under Fair Source 0.9
8
+ """
9
+
10
+ import logging
11
+ from dataclasses import dataclass, field
12
+
13
+ from patterns import get_pattern_registry
14
+ from patterns.behavior import PredictionPattern, RiskAssessmentPattern
15
+ from patterns.structural import PhasedProcessingPattern
16
+ from patterns.validation import ApprovalPattern, StepValidationPattern
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ @dataclass
22
+ class RiskAnalysis:
23
+ """Risk analysis results for a workflow."""
24
+
25
+ workflow_id: str
26
+ pattern_ids: list[str]
27
+ critical_paths: list[str] = field(default_factory=list)
28
+ high_risk_inputs: list[str] = field(default_factory=list)
29
+ validation_points: list[str] = field(default_factory=list)
30
+ recommended_coverage: int = 80 # Percentage
31
+ test_priorities: dict[str, int] = field(default_factory=dict) # test_name -> priority (1-5)
32
+
33
+ def get_critical_test_cases(self) -> list[str]:
34
+ """Get list of critical test case names.
35
+
36
+ Returns:
37
+ List of critical test cases to implement
38
+
39
+ """
40
+ test_cases = []
41
+
42
+ # Critical paths become test cases
43
+ for path in self.critical_paths:
44
+ test_case = f"test_{path.lower().replace(' ', '_').replace('-', '_')}"
45
+ test_cases.append(test_case)
46
+
47
+ # High-risk inputs become test cases
48
+ for input_risk in self.high_risk_inputs:
49
+ test_case = f"test_{input_risk.lower().replace(' ', '_')}_validation"
50
+ test_cases.append(test_case)
51
+
52
+ return test_cases
53
+
54
+ def to_dict(self) -> dict:
55
+ """Convert to dictionary."""
56
+ return {
57
+ "workflow_id": self.workflow_id,
58
+ "pattern_ids": self.pattern_ids,
59
+ "critical_paths": self.critical_paths,
60
+ "high_risk_inputs": self.high_risk_inputs,
61
+ "validation_points": self.validation_points,
62
+ "recommended_coverage": self.recommended_coverage,
63
+ "test_priorities": self.test_priorities,
64
+ }
65
+
66
+
67
+ class RiskAnalyzer:
68
+ """Analyzes workflow patterns to determine testing requirements.
69
+
70
+ Uses pattern analysis to identify:
71
+ - Critical execution paths
72
+ - High-risk input scenarios
73
+ - Required validation points
74
+ - Recommended test coverage level
75
+ """
76
+
77
+ def __init__(self):
78
+ """Initialize risk analyzer."""
79
+ self.registry = get_pattern_registry()
80
+
81
+ def analyze(self, workflow_id: str, pattern_ids: list[str]) -> RiskAnalysis:
82
+ """Analyze workflow patterns for risk.
83
+
84
+ Args:
85
+ workflow_id: Workflow identifier
86
+ pattern_ids: List of pattern IDs used by workflow
87
+
88
+ Returns:
89
+ RiskAnalysis with recommendations
90
+
91
+ """
92
+ logger.info(f"Analyzing risk for workflow: {workflow_id}")
93
+
94
+ analysis = RiskAnalysis(
95
+ workflow_id=workflow_id,
96
+ pattern_ids=pattern_ids,
97
+ )
98
+
99
+ # Analyze each pattern
100
+ for pattern_id in pattern_ids:
101
+ pattern = self.registry.get(pattern_id)
102
+ if not pattern:
103
+ logger.warning(f"Pattern not found: {pattern_id}")
104
+ continue
105
+
106
+ self._analyze_pattern(pattern, analysis)
107
+
108
+ # Calculate recommended coverage based on risk
109
+ self._calculate_coverage(analysis)
110
+
111
+ # Prioritize tests
112
+ self._prioritize_tests(analysis)
113
+
114
+ logger.info(
115
+ f"Risk analysis complete: {len(analysis.critical_paths)} critical paths, "
116
+ f"{analysis.recommended_coverage}% coverage recommended"
117
+ )
118
+
119
+ return analysis
120
+
121
+ def _analyze_pattern(self, pattern, analysis: RiskAnalysis) -> None:
122
+ """Analyze a specific pattern for risks.
123
+
124
+ Args:
125
+ pattern: Pattern to analyze
126
+ analysis: RiskAnalysis to update
127
+
128
+ """
129
+ # Approval patterns are CRITICAL - must test preview → approval flow
130
+ if isinstance(pattern, ApprovalPattern):
131
+ analysis.critical_paths.append("approval_workflow")
132
+ analysis.high_risk_inputs.append("save_without_preview")
133
+ analysis.high_risk_inputs.append("save_without_approval")
134
+ analysis.validation_points.append("preview_generated")
135
+ analysis.validation_points.append("user_approved")
136
+
137
+ # Step validation patterns - test step sequencing
138
+ elif isinstance(pattern, StepValidationPattern):
139
+ analysis.critical_paths.append("step_sequence_validation")
140
+ analysis.high_risk_inputs.append("skip_step")
141
+ analysis.high_risk_inputs.append("wrong_step_number")
142
+ analysis.validation_points.append("current_step")
143
+
144
+ # Phased processing - each phase is a critical path
145
+ elif isinstance(pattern, PhasedProcessingPattern):
146
+ for phase in pattern.phases:
147
+ analysis.critical_paths.append(f"phase_{phase.name}")
148
+ if phase.required:
149
+ analysis.validation_points.append(f"{phase.name}_completed")
150
+
151
+ # Risk assessment patterns - test risk detection
152
+ elif isinstance(pattern, RiskAssessmentPattern):
153
+ analysis.critical_paths.append("risk_assessment")
154
+ analysis.validation_points.append("alert_level")
155
+ for level in pattern.risk_levels:
156
+ analysis.high_risk_inputs.append(f"{level.name}_threshold")
157
+
158
+ # Prediction patterns - test predictions
159
+ elif isinstance(pattern, PredictionPattern):
160
+ analysis.critical_paths.append("prediction_generation")
161
+ for pred_type in pattern.prediction_types:
162
+ analysis.validation_points.append(pred_type)
163
+
164
+ def _calculate_coverage(self, analysis: RiskAnalysis) -> None:
165
+ """Calculate recommended test coverage.
166
+
167
+ Args:
168
+ analysis: RiskAnalysis to update
169
+
170
+ """
171
+ # Base coverage
172
+ base_coverage = 70
173
+
174
+ # Add 5% for each critical path
175
+ critical_bonus = min(20, len(analysis.critical_paths) * 5)
176
+
177
+ # Add 3% for each validation point
178
+ validation_bonus = min(10, len(analysis.validation_points) * 3)
179
+
180
+ # Cap at 95%
181
+ analysis.recommended_coverage = min(
182
+ 95,
183
+ base_coverage + critical_bonus + validation_bonus,
184
+ )
185
+
186
+ def _prioritize_tests(self, analysis: RiskAnalysis) -> None:
187
+ """Assign priorities to test cases.
188
+
189
+ Args:
190
+ analysis: RiskAnalysis to update
191
+
192
+ """
193
+ # Priority levels: 1 (critical) to 5 (nice-to-have)
194
+
195
+ # Critical paths = Priority 1
196
+ for path in analysis.critical_paths:
197
+ test_name = f"test_{path}"
198
+ analysis.test_priorities[test_name] = 1
199
+
200
+ # High-risk inputs = Priority 2
201
+ for input_risk in analysis.high_risk_inputs:
202
+ test_name = f"test_{input_risk}_validation"
203
+ analysis.test_priorities[test_name] = 2
204
+
205
+ # Validation points = Priority 3
206
+ for validation in analysis.validation_points:
207
+ test_name = f"test_{validation}"
208
+ if test_name not in analysis.test_priorities:
209
+ analysis.test_priorities[test_name] = 3
210
+
211
+ # Success path = Priority 4
212
+ analysis.test_priorities["test_success_path"] = 4
213
+ analysis.test_priorities["test_happy_path"] = 4
214
+
215
+ # Edge cases = Priority 5
216
+ analysis.test_priorities["test_edge_cases"] = 5
@@ -0,0 +1,272 @@
1
+ """Unit tests for {{ wizard_id }} wizard.
2
+
3
+ Auto-generated by Empathy Framework Test Generator
4
+ Risk Analysis: {{ risk_analysis.critical_paths|length }} critical paths identified
5
+ Target Coverage: {{ risk_analysis.recommended_coverage }}%
6
+ Generated: {{ timestamp }}
7
+ """
8
+
9
+ import pytest
10
+ {% if has_async %}
11
+ import asyncio
12
+ {% endif %}
13
+ from unittest.mock import MagicMock, patch, AsyncMock
14
+
15
+ from {{ wizard_module }} import {{ wizard_class }}
16
+
17
+
18
+ class Test{{ wizard_class }}:
19
+ """Test {{ wizard_id }} wizard."""
20
+
21
+ @pytest.fixture
22
+ def wizard(self):
23
+ """Create wizard instance."""
24
+ return {{ wizard_class }}()
25
+
26
+ {% if 'approval' in pattern_ids %}
27
+ # =========================================================================
28
+ # CRITICAL: User Approval Tests (Priority 1)
29
+ # =========================================================================
30
+
31
+ {% if has_async %}async {% endif %}def test_cannot_save_without_preview(self, wizard):
32
+ """CRITICAL: Saving without preview should fail.
33
+
34
+ Risk: Users bypassing review step could save unreviewed content
35
+ Priority: 1 (Critical)
36
+ Pattern: approval
37
+ """
38
+ {% if has_async %}
39
+ with pytest.raises(Exception) as exc:
40
+ await wizard.save(wizard_id="test", approval={"user_approved": True})
41
+ {% else %}
42
+ with pytest.raises(Exception) as exc:
43
+ wizard.save(wizard_id="test", approval={"user_approved": True})
44
+ {% endif %}
45
+
46
+ # Should fail with preview requirement message
47
+ assert "preview" in str(exc.value).lower()
48
+
49
+ {% if has_async %}async {% endif %}def test_cannot_save_without_approval(self, wizard):
50
+ """CRITICAL: Saving without user approval should fail.
51
+
52
+ Risk: Content finalized without explicit user consent
53
+ Priority: 1 (Critical)
54
+ Pattern: approval
55
+ """
56
+ {% if has_async %}
57
+ # Generate preview first
58
+ await wizard.preview(wizard_id="test")
59
+
60
+ # Try to save without approval
61
+ with pytest.raises(Exception) as exc:
62
+ await wizard.save(wizard_id="test", approval={"user_approved": False})
63
+ {% else %}
64
+ wizard.preview(wizard_id="test")
65
+
66
+ with pytest.raises(Exception) as exc:
67
+ wizard.save(wizard_id="test", approval={"user_approved": False})
68
+ {% endif %}
69
+
70
+ # Should fail with approval requirement
71
+ assert "approval" in str(exc.value).lower()
72
+
73
+ {% if has_async %}async {% endif %}def test_preview_does_not_finalize(self, wizard):
74
+ """CRITICAL: Preview should NOT mark wizard as complete.
75
+
76
+ Risk: Users locked out from editing after preview
77
+ Priority: 1 (Critical)
78
+ Pattern: approval
79
+ """
80
+ {% if has_async %}
81
+ session = await wizard.start()
82
+ wizard_id = session["wizard_id"]
83
+
84
+ # Generate preview
85
+ preview = await wizard.preview(wizard_id)
86
+
87
+ # Check wizard NOT marked complete
88
+ session = await wizard.get_session(wizard_id)
89
+ {% else %}
90
+ session = wizard.start()
91
+ wizard_id = session["wizard_id"]
92
+
93
+ preview = wizard.preview(wizard_id)
94
+
95
+ session = wizard.get_session(wizard_id)
96
+ {% endif %}
97
+
98
+ assert session.get("completed", False) is False
99
+ assert "preview_report" in session # Preview exists
100
+ assert "final_report" not in session # But not finalized
101
+ {% endif %}
102
+
103
+ {% if 'step_validation' in pattern_ids %}
104
+ # =========================================================================
105
+ # CRITICAL: Step Validation Tests (Priority 1)
106
+ # =========================================================================
107
+
108
+ {% if has_async %}async {% endif %}def test_cannot_skip_steps(self, wizard):
109
+ """CRITICAL: Steps must be completed in order.
110
+
111
+ Risk: Users skipping required data collection steps
112
+ Priority: 1 (Critical)
113
+ Pattern: step_validation
114
+ """
115
+ {% if has_async %}
116
+ session = await wizard.start()
117
+ wizard_id = session["wizard_id"]
118
+
119
+ # Try to skip to step 3
120
+ with pytest.raises(Exception) as exc:
121
+ await wizard.submit_step(wizard_id, {"step": 3, "data": {}})
122
+ {% else %}
123
+ session = wizard.start()
124
+ wizard_id = session["wizard_id"]
125
+
126
+ with pytest.raises(Exception) as exc:
127
+ wizard.submit_step(wizard_id, {"step": 3, "data": {}})
128
+ {% endif %}
129
+
130
+ assert "expected step 1" in str(exc.value).lower() or "step" in str(exc.value).lower()
131
+
132
+ {% if has_async %}async {% endif %}def test_step_sequence_enforced(self, wizard):
133
+ """CRITICAL: Wrong step number should be rejected.
134
+
135
+ Risk: Step sequence corruption
136
+ Priority: 1 (Critical)
137
+ Pattern: step_validation
138
+ """
139
+ {% if has_async %}
140
+ session = await wizard.start()
141
+ wizard_id = session["wizard_id"]
142
+
143
+ # Submit wrong step number
144
+ with pytest.raises(Exception) as exc:
145
+ await wizard.submit_step(wizard_id, {"step": 99, "data": {}})
146
+ {% else %}
147
+ session = wizard.start()
148
+ wizard_id = session["wizard_id"]
149
+
150
+ with pytest.raises(Exception) as exc:
151
+ wizard.submit_step(wizard_id, {"step": 99, "data": {}})
152
+ {% endif %}
153
+
154
+ assert exc.value is not None
155
+ {% endif %}
156
+
157
+ {% if 'risk_assessment' in pattern_ids %}
158
+ # =========================================================================
159
+ # Risk Assessment Tests (Priority 2)
160
+ # =========================================================================
161
+
162
+ def test_risk_assessment_identifies_critical_issues(self, wizard):
163
+ """Risk assessment should flag critical issues.
164
+
165
+ Priority: 2 (High)
166
+ Pattern: risk_assessment
167
+ """
168
+ issues = [
169
+ {"severity": "critical", "message": "Test issue"}
170
+ ]
171
+
172
+ risk_result = wizard.assess_risk(issues)
173
+
174
+ assert risk_result["alert_level"] == "CRITICAL"
175
+ assert risk_result["by_risk_level"]["critical"] == 1
176
+ {% endif %}
177
+
178
+ {% if 'phased_processing' in pattern_ids %}
179
+ # =========================================================================
180
+ # Phased Processing Tests (Priority 1)
181
+ # =========================================================================
182
+
183
+ {% for phase in phases %}
184
+ {% if has_async %}async {% endif %}def test_phase_{{ phase.name }}(self, wizard):
185
+ """Test {{ phase.name }} phase execution.
186
+
187
+ Priority: 1 (Critical path)
188
+ Pattern: phased_processing
189
+ """
190
+ context = {"test": "data"}
191
+
192
+ {% if has_async %}
193
+ result = await wizard._{{ phase.name }}(context)
194
+ {% else %}
195
+ result = wizard._{{ phase.name }}(context)
196
+ {% endif %}
197
+
198
+ assert result is not None
199
+ assert isinstance(result, dict)
200
+ {% endfor %}
201
+ {% endif %}
202
+
203
+ # =========================================================================
204
+ # Success Path Tests (Priority 4)
205
+ # =========================================================================
206
+
207
+ {% if has_async %}async {% endif %}def test_happy_path_success(self, wizard):
208
+ """Test complete wizard flow succeeds.
209
+
210
+ Priority: 4 (Success path)
211
+ """
212
+ {% if 'linear_flow' in pattern_ids %}
213
+ # Start wizard
214
+ {% if has_async %}
215
+ session = await wizard.start()
216
+ {% else %}
217
+ session = wizard.start()
218
+ {% endif %}
219
+ wizard_id = session["wizard_id"]
220
+
221
+ assert wizard_id is not None
222
+ assert session["current_step"] == 1
223
+
224
+ # Complete all steps
225
+ for step in range(1, {{ total_steps or 5 }}):
226
+ {% if has_async %}
227
+ result = await wizard.submit_step(
228
+ wizard_id,
229
+ {"step": step, "data": {"test": f"data_{step}"}}
230
+ )
231
+ {% else %}
232
+ result = wizard.submit_step(
233
+ wizard_id,
234
+ {"step": step, "data": {"test": f"data_{step}"}}
235
+ )
236
+ {% endif %}
237
+ assert result is not None
238
+
239
+ # Generate preview
240
+ {% if has_async %}
241
+ preview = await wizard.preview(wizard_id)
242
+ {% else %}
243
+ preview = wizard.preview(wizard_id)
244
+ {% endif %}
245
+ assert preview is not None
246
+
247
+ # Save with approval
248
+ {% if has_async %}
249
+ final = await wizard.save(wizard_id, {"user_approved": True})
250
+ {% else %}
251
+ final = wizard.save(wizard_id, {"user_approved": True})
252
+ {% endif %}
253
+ assert final["completed"] is True
254
+ {% else %}
255
+ # Test basic wizard functionality
256
+ result = wizard.process({"test": "data"})
257
+ assert result is not None
258
+ {% endif %}
259
+
260
+ # =========================================================================
261
+ # Validation Tests (Priority 3)
262
+ # =========================================================================
263
+
264
+ {% for validation in risk_analysis.validation_points[:5] %}
265
+ def test_{{ validation }}_validated(self, wizard):
266
+ """Test {{ validation }} is properly validated.
267
+
268
+ Priority: 3 (Validation point)
269
+ """
270
+ # TODO: Implement validation test for {{ validation }}
271
+ pass
272
+ {% endfor %}