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,196 @@
1
+ """Telemetry backend interface.
2
+
3
+ Abstract base class for telemetry storage backends.
4
+
5
+ Copyright 2025 Smart-AI-Memory
6
+ Licensed under Fair Source License 0.9
7
+ """
8
+
9
+ from datetime import datetime
10
+ from typing import Protocol
11
+
12
+ from .data_models import (
13
+ AgentAssignmentRecord,
14
+ CoverageRecord,
15
+ FileTestRecord,
16
+ LLMCallRecord,
17
+ TaskRoutingRecord,
18
+ TestExecutionRecord,
19
+ WorkflowRunRecord,
20
+ )
21
+
22
+
23
+ def _parse_timestamp(timestamp_str: str) -> datetime:
24
+ """Parse ISO format timestamp, handling 'Z' suffix for Python 3.10 compatibility.
25
+
26
+ Args:
27
+ timestamp_str: ISO format timestamp string, possibly with 'Z' suffix
28
+
29
+ Returns:
30
+ Parsed datetime object (timezone-naive UTC)
31
+ """
32
+ # Python 3.10's fromisoformat() doesn't handle 'Z' suffix
33
+ if timestamp_str.endswith("Z"):
34
+ timestamp_str = timestamp_str[:-1]
35
+
36
+ dt = datetime.fromisoformat(timestamp_str)
37
+
38
+ # Convert to naive UTC if timezone-aware
39
+ if dt.tzinfo is not None:
40
+ dt = dt.replace(tzinfo=None)
41
+
42
+ return dt
43
+
44
+
45
+
46
+ class TelemetryBackend(Protocol):
47
+ """Protocol for telemetry storage backends.
48
+
49
+ Implementations can store telemetry data in different backends:
50
+ - JSONL files (default, via TelemetryStore)
51
+ - Database (PostgreSQL, SQLite, etc.)
52
+ - Cloud services (DataDog, New Relic, etc.)
53
+ - Custom backends
54
+
55
+ Supports both core telemetry (LLM calls, workflows) and Tier 1
56
+ automation monitoring (task routing, tests, coverage, assignments).
57
+
58
+ Example implementing a custom backend:
59
+ >>> class DatabaseBackend:
60
+ ... def log_call(self, record: LLMCallRecord) -> None:
61
+ ... # Insert into database
62
+ ... pass
63
+ ...
64
+ ... def log_workflow(self, record: WorkflowRunRecord) -> None:
65
+ ... # Insert into database
66
+ ... pass
67
+ ...
68
+ ... def get_calls(self, since=None, workflow_name=None, limit=1000):
69
+ ... # Query database
70
+ ... return []
71
+ ...
72
+ ... def get_workflows(self, since=None, workflow_name=None, limit=100):
73
+ ... # Query database
74
+ ... return []
75
+ """
76
+
77
+ def log_call(self, record: LLMCallRecord) -> None:
78
+ """Log an LLM call record."""
79
+ ...
80
+
81
+ def log_workflow(self, record: WorkflowRunRecord) -> None:
82
+ """Log a workflow run record."""
83
+ ...
84
+
85
+ def get_calls(
86
+ self,
87
+ since: datetime | None = None,
88
+ workflow_name: str | None = None,
89
+ limit: int = 1000,
90
+ ) -> list[LLMCallRecord]:
91
+ """Get LLM call records with optional filters."""
92
+ ...
93
+
94
+ def get_workflows(
95
+ self,
96
+ since: datetime | None = None,
97
+ workflow_name: str | None = None,
98
+ limit: int = 100,
99
+ ) -> list[WorkflowRunRecord]:
100
+ """Get workflow run records with optional filters."""
101
+ ...
102
+
103
+ # Tier 1 automation monitoring methods
104
+ def log_task_routing(self, record: TaskRoutingRecord) -> None:
105
+ """Log a task routing decision."""
106
+ ...
107
+
108
+ def log_test_execution(self, record: TestExecutionRecord) -> None:
109
+ """Log a test execution."""
110
+ ...
111
+
112
+ def log_coverage(self, record: CoverageRecord) -> None:
113
+ """Log coverage metrics."""
114
+ ...
115
+
116
+ def log_agent_assignment(self, record: AgentAssignmentRecord) -> None:
117
+ """Log an agent assignment."""
118
+ ...
119
+
120
+ def get_task_routings(
121
+ self,
122
+ since: datetime | None = None,
123
+ status: str | None = None,
124
+ limit: int = 1000,
125
+ ) -> list[TaskRoutingRecord]:
126
+ """Get task routing records with optional filters."""
127
+ ...
128
+
129
+ def get_test_executions(
130
+ self,
131
+ since: datetime | None = None,
132
+ success_only: bool = False,
133
+ limit: int = 100,
134
+ ) -> list[TestExecutionRecord]:
135
+ """Get test execution records with optional filters."""
136
+ ...
137
+
138
+ def get_coverage_history(
139
+ self,
140
+ since: datetime | None = None,
141
+ limit: int = 100,
142
+ ) -> list[CoverageRecord]:
143
+ """Get coverage history records."""
144
+ ...
145
+
146
+ def get_agent_assignments(
147
+ self,
148
+ since: datetime | None = None,
149
+ automated_only: bool = True,
150
+ limit: int = 1000,
151
+ ) -> list[AgentAssignmentRecord]:
152
+ """Get agent assignment records with optional filters."""
153
+ ...
154
+
155
+ # Per-file test tracking methods
156
+ def log_file_test(self, record: "FileTestRecord") -> None:
157
+ """Log a per-file test execution record."""
158
+ ...
159
+
160
+ def get_file_tests(
161
+ self,
162
+ file_path: str | None = None,
163
+ since: datetime | None = None,
164
+ result_filter: str | None = None,
165
+ limit: int = 1000,
166
+ ) -> list["FileTestRecord"]:
167
+ """Get per-file test records with optional filters."""
168
+ ...
169
+
170
+ def get_latest_file_test(self, file_path: str) -> "FileTestRecord | None":
171
+ """Get the most recent test record for a specific file."""
172
+ ...
173
+
174
+
175
+ def _parse_timestamp(timestamp_str: str) -> datetime:
176
+ """Parse ISO format timestamp, handling 'Z' suffix for Python 3.10 compatibility.
177
+
178
+ Args:
179
+ timestamp_str: ISO format timestamp string, possibly with 'Z' suffix
180
+
181
+ Returns:
182
+ Parsed datetime object (timezone-naive UTC)
183
+ """
184
+ # Python 3.10's fromisoformat() doesn't handle 'Z' suffix
185
+ if timestamp_str.endswith("Z"):
186
+ timestamp_str = timestamp_str[:-1]
187
+
188
+ dt = datetime.fromisoformat(timestamp_str)
189
+
190
+ # Convert to naive UTC if timezone-aware
191
+ if dt.tzinfo is not None:
192
+ dt = dt.replace(tzinfo=None)
193
+
194
+ return dt
195
+
196
+
@@ -0,0 +1,431 @@
1
+ """Telemetry data models.
2
+
3
+ Data classes for tracking LLM calls, workflows, tests, and agent assignments.
4
+
5
+ Copyright 2025 Smart-AI-Memory
6
+ Licensed under Fair Source License 0.9
7
+ """
8
+
9
+ from dataclasses import asdict, dataclass, field
10
+ from typing import Any
11
+
12
+
13
+ @dataclass
14
+ class LLMCallRecord:
15
+ """Record of a single LLM API call.
16
+
17
+ Captures all relevant metrics for cost tracking, performance analysis,
18
+ and debugging.
19
+ """
20
+
21
+ # Identification
22
+ call_id: str
23
+ timestamp: str # ISO format
24
+
25
+ # Context
26
+ workflow_name: str | None = None
27
+ step_name: str | None = None
28
+ user_id: str | None = None
29
+ session_id: str | None = None
30
+
31
+ # Task routing
32
+ task_type: str = "unknown"
33
+ provider: str = "anthropic"
34
+ tier: str = "capable"
35
+ model_id: str = ""
36
+
37
+ # Token usage
38
+ input_tokens: int = 0
39
+ output_tokens: int = 0
40
+
41
+ # Cost (in USD)
42
+ estimated_cost: float = 0.0
43
+ actual_cost: float | None = None
44
+
45
+ # Performance
46
+ latency_ms: int = 0
47
+
48
+ # Fallback and resilience tracking
49
+ fallback_used: bool = False
50
+ fallback_chain: list[str] = field(default_factory=list)
51
+ original_provider: str | None = None
52
+ original_model: str | None = None
53
+ retry_count: int = 0 # Number of retries before success
54
+ circuit_breaker_state: str | None = None # "closed", "open", "half-open"
55
+
56
+ # Error tracking
57
+ success: bool = True
58
+ error_type: str | None = None
59
+ error_message: str | None = None
60
+
61
+ # Additional metadata
62
+ metadata: dict[str, Any] = field(default_factory=dict)
63
+
64
+ def to_dict(self) -> dict[str, Any]:
65
+ """Convert to dictionary for JSON serialization."""
66
+ return asdict(self)
67
+
68
+ @classmethod
69
+ def from_dict(cls, data: dict[str, Any]) -> "LLMCallRecord":
70
+ """Create from dictionary."""
71
+ return cls(**data)
72
+
73
+
74
+ @dataclass
75
+ class WorkflowStageRecord:
76
+ """Record of a single workflow stage execution."""
77
+
78
+ stage_name: str
79
+ tier: str
80
+ model_id: str
81
+ input_tokens: int = 0
82
+ output_tokens: int = 0
83
+ cost: float = 0.0
84
+ latency_ms: int = 0
85
+ success: bool = True
86
+ skipped: bool = False
87
+ skip_reason: str | None = None
88
+ error: str | None = None
89
+
90
+
91
+ @dataclass
92
+ class WorkflowRunRecord:
93
+ """Record of a complete workflow execution.
94
+
95
+ Aggregates stage-level metrics and provides workflow-level analytics.
96
+ """
97
+
98
+ # Identification
99
+ run_id: str
100
+ workflow_name: str
101
+ started_at: str # ISO format
102
+ completed_at: str | None = None
103
+
104
+ # Context
105
+ user_id: str | None = None
106
+ session_id: str | None = None
107
+
108
+ # Stages
109
+ stages: list[WorkflowStageRecord] = field(default_factory=list)
110
+
111
+ # Aggregated metrics
112
+ total_input_tokens: int = 0
113
+ total_output_tokens: int = 0
114
+ total_cost: float = 0.0
115
+ baseline_cost: float = 0.0 # If all stages used premium
116
+ savings: float = 0.0
117
+ savings_percent: float = 0.0
118
+
119
+ # Performance
120
+ total_duration_ms: int = 0
121
+
122
+ # Status
123
+ success: bool = True
124
+ error: str | None = None
125
+
126
+ # Provider usage
127
+ providers_used: list[str] = field(default_factory=list)
128
+ tiers_used: list[str] = field(default_factory=list)
129
+
130
+ def to_dict(self) -> dict[str, Any]:
131
+ """Convert to dictionary for JSON serialization."""
132
+ data = asdict(self)
133
+ data["stages"] = [asdict(s) for s in self.stages]
134
+ return data
135
+
136
+ @classmethod
137
+ def from_dict(cls, data: dict[str, Any]) -> "WorkflowRunRecord":
138
+ """Create from dictionary."""
139
+ stages = [WorkflowStageRecord(**s) for s in data.pop("stages", [])]
140
+ return cls(stages=stages, **data)
141
+
142
+
143
+ @dataclass
144
+ class TaskRoutingRecord:
145
+ """Record of task routing decision for Tier 1 automation.
146
+
147
+ Tracks which agent/workflow handles each task, routing strategy,
148
+ and execution outcome for automation monitoring.
149
+ """
150
+
151
+ # Identification (required)
152
+ routing_id: str
153
+ timestamp: str # ISO format
154
+
155
+ # Task context (required)
156
+ task_description: str
157
+ task_type: str # "code_review", "test_gen", "bug_fix", "refactor", etc.
158
+ task_complexity: str # "simple", "moderate", "complex"
159
+
160
+ # Routing decision (required)
161
+ assigned_agent: str # "test_gen_workflow", "code_review_workflow", etc.
162
+ assigned_tier: str # "cheap", "capable", "premium"
163
+ routing_strategy: str # "rule_based", "ml_predicted", "manual_override"
164
+
165
+ # Optional fields with defaults
166
+ task_dependencies: list[str] = field(default_factory=list) # Task IDs this depends on
167
+ confidence_score: float = 1.0 # 0.0-1.0 for ML predictions
168
+
169
+ # Execution tracking
170
+ status: str = "pending" # "pending", "running", "completed", "failed"
171
+ started_at: str | None = None
172
+ completed_at: str | None = None
173
+
174
+ # Outcome
175
+ success: bool = False
176
+ quality_score: float | None = None # 0.0-1.0 if applicable
177
+ retry_count: int = 0
178
+ error_type: str | None = None
179
+ error_message: str | None = None
180
+
181
+ # Cost tracking
182
+ estimated_cost: float = 0.0
183
+ actual_cost: float | None = None
184
+
185
+ # Metadata
186
+ user_id: str | None = None
187
+ session_id: str | None = None
188
+ metadata: dict[str, Any] = field(default_factory=dict)
189
+
190
+ def to_dict(self) -> dict[str, Any]:
191
+ """Convert to dictionary for JSON serialization."""
192
+ return asdict(self)
193
+
194
+ @classmethod
195
+ def from_dict(cls, data: dict[str, Any]) -> "TaskRoutingRecord":
196
+ """Create from dictionary."""
197
+ return cls(**data)
198
+
199
+
200
+ @dataclass
201
+ class TestExecutionRecord:
202
+ """Record of test execution for Tier 1 QA automation.
203
+
204
+ Tracks test execution results, coverage metrics, and failure details
205
+ for quality assurance monitoring.
206
+ """
207
+
208
+ # Identification (required)
209
+ execution_id: str
210
+ timestamp: str # ISO format
211
+
212
+ # Test context (required)
213
+ test_suite: str # "unit", "integration", "e2e", "all"
214
+
215
+ # Optional fields with defaults
216
+ test_files: list[str] = field(default_factory=list) # Specific test files executed
217
+ triggered_by: str = "manual" # "workflow", "manual", "ci", "pre_commit"
218
+
219
+ # Execution details
220
+ command: str = ""
221
+ working_directory: str = ""
222
+ duration_seconds: float = 0.0
223
+
224
+ # Results
225
+ total_tests: int = 0
226
+ passed: int = 0
227
+ failed: int = 0
228
+ skipped: int = 0
229
+ errors: int = 0
230
+
231
+ # Coverage (if available)
232
+ coverage_percentage: float | None = None
233
+ coverage_report_path: str | None = None
234
+
235
+ # Failures
236
+ failed_tests: list[dict[str, Any]] = field(
237
+ default_factory=list
238
+ ) # [{name, file, error, traceback}]
239
+
240
+ # Status
241
+ success: bool = False # True if all tests passed
242
+ exit_code: int = 0
243
+
244
+ # Metadata
245
+ workflow_id: str | None = None # Link to workflow that triggered this
246
+ metadata: dict[str, Any] = field(default_factory=dict)
247
+
248
+ def to_dict(self) -> dict[str, Any]:
249
+ """Convert to dictionary for JSON serialization."""
250
+ return asdict(self)
251
+
252
+ @classmethod
253
+ def from_dict(cls, data: dict[str, Any]) -> "TestExecutionRecord":
254
+ """Create from dictionary."""
255
+ return cls(**data)
256
+
257
+
258
+ @dataclass
259
+ class CoverageRecord:
260
+ """Record of test coverage metrics for Tier 1 QA monitoring.
261
+
262
+ Tracks coverage percentage, trends, and critical gaps for
263
+ continuous quality improvement.
264
+ """
265
+
266
+ # Identification (required)
267
+ record_id: str
268
+ timestamp: str # ISO format
269
+
270
+ # Coverage metrics (required)
271
+ overall_percentage: float
272
+ lines_total: int
273
+ lines_covered: int
274
+
275
+ # Optional fields with defaults
276
+ branches_total: int = 0
277
+ branches_covered: int = 0
278
+
279
+ # File-level breakdown
280
+ files_total: int = 0
281
+ files_well_covered: int = 0 # >= 80%
282
+ files_critical: int = 0 # < 50%
283
+ untested_files: list[str] = field(default_factory=list)
284
+
285
+ # Critical gaps
286
+ critical_gaps: list[dict[str, Any]] = field(
287
+ default_factory=list
288
+ ) # [{file, coverage, priority}]
289
+
290
+ # Trend data
291
+ previous_percentage: float | None = None
292
+ trend: str | None = None # "improving", "declining", "stable"
293
+
294
+ # Source
295
+ coverage_format: str = "xml" # "xml", "json", "lcov"
296
+ coverage_file: str = ""
297
+
298
+ # Metadata
299
+ workflow_id: str | None = None
300
+ metadata: dict[str, Any] = field(default_factory=dict)
301
+
302
+ def to_dict(self) -> dict[str, Any]:
303
+ """Convert to dictionary for JSON serialization."""
304
+ return asdict(self)
305
+
306
+ @classmethod
307
+ def from_dict(cls, data: dict[str, Any]) -> "CoverageRecord":
308
+ """Create from dictionary."""
309
+ return cls(**data)
310
+
311
+
312
+ @dataclass
313
+ class AgentAssignmentRecord:
314
+ """Record of agent assignment for simple tasks (Tier 1).
315
+
316
+ Tracks task assignments to agents/workflows with clear specs
317
+ and no complex dependencies for automation monitoring.
318
+ """
319
+
320
+ # Identification (required)
321
+ assignment_id: str
322
+ timestamp: str # ISO format
323
+
324
+ # Task details (required)
325
+ task_id: str
326
+ task_title: str
327
+ task_description: str
328
+
329
+ # Assignment (required)
330
+ assigned_agent: str # Agent/workflow name
331
+
332
+ # Optional fields with defaults
333
+ task_spec_clarity: float = 0.0 # 0.0-1.0, higher = clearer spec
334
+ assignment_reason: str = "" # Why this agent was chosen
335
+ estimated_duration_hours: float = 0.0
336
+
337
+ # Criteria checks
338
+ has_clear_spec: bool = False
339
+ has_dependencies: bool = False
340
+ requires_human_review: bool = False
341
+ automated_eligible: bool = False # True for Tier 1
342
+
343
+ # Execution tracking
344
+ status: str = "assigned" # "assigned", "in_progress", "completed", "blocked"
345
+ started_at: str | None = None
346
+ completed_at: str | None = None
347
+ actual_duration_hours: float | None = None
348
+
349
+ # Outcome
350
+ success: bool = False
351
+ quality_check_passed: bool = False
352
+ human_review_required: bool = False
353
+
354
+ # Metadata
355
+ workflow_id: str | None = None
356
+ metadata: dict[str, Any] = field(default_factory=dict)
357
+
358
+ def to_dict(self) -> dict[str, Any]:
359
+ """Convert to dictionary for JSON serialization."""
360
+ return asdict(self)
361
+
362
+ @classmethod
363
+ def from_dict(cls, data: dict[str, Any]) -> "AgentAssignmentRecord":
364
+ """Create from dictionary."""
365
+ return cls(**data)
366
+
367
+
368
+ @dataclass
369
+ class FileTestRecord:
370
+ """Record of test execution for a specific source file.
371
+
372
+ Tracks when tests for an individual file were last run, results,
373
+ and coverage - enabling per-file test status tracking.
374
+
375
+ This complements TestExecutionRecord (suite-level) by providing
376
+ granular file-level test tracking for better test maintenance.
377
+ """
378
+
379
+ # Identification (required)
380
+ file_path: str # Source file path (relative to project root)
381
+ timestamp: str # ISO format - when tests were run
382
+
383
+ # Test results (required)
384
+ last_test_result: str # "passed", "failed", "error", "skipped", "no_tests"
385
+ test_count: int # Number of tests for this file
386
+
387
+ # Detailed results with defaults
388
+ passed: int = 0
389
+ failed: int = 0
390
+ skipped: int = 0
391
+ errors: int = 0
392
+
393
+ # Timing
394
+ duration_seconds: float = 0.0
395
+
396
+ # Coverage for this file (if available)
397
+ coverage_percent: float | None = None
398
+ lines_total: int = 0
399
+ lines_covered: int = 0
400
+
401
+ # Test file info
402
+ test_file_path: str | None = None # Associated test file
403
+
404
+ # Failure details (if any)
405
+ failed_tests: list[dict[str, Any]] = field(default_factory=list)
406
+
407
+ # Staleness tracking
408
+ source_modified_at: str | None = None # When source file was last modified
409
+ tests_modified_at: str | None = None # When test file was last modified
410
+ is_stale: bool = False # Tests haven't been run since source changed
411
+
412
+ # Link to execution
413
+ execution_id: str | None = None # Link to TestExecutionRecord
414
+ workflow_id: str | None = None
415
+
416
+ # Metadata
417
+ metadata: dict[str, Any] = field(default_factory=dict)
418
+
419
+ def to_dict(self) -> dict[str, Any]:
420
+ """Convert to dictionary for JSON serialization."""
421
+ return asdict(self)
422
+
423
+ @classmethod
424
+ def from_dict(cls, data: dict[str, Any]) -> "FileTestRecord":
425
+ """Create from dictionary."""
426
+ return cls(**data)
427
+
428
+ @property
429
+ def success(self) -> bool:
430
+ """Check if all tests passed."""
431
+ return self.last_test_result == "passed" and self.failed == 0 and self.errors == 0