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,435 @@
1
+ """Git Pattern Extractor
2
+
3
+ Automatically detects bug fixes from git commits and creates
4
+ draft pattern entries for review.
5
+
6
+ This module integrates with git hooks (post-commit) to capture
7
+ fix patterns as they happen.
8
+
9
+ Usage:
10
+ # As a post-commit hook
11
+ python -m attune_llm.git_pattern_extractor
12
+
13
+ # Manual extraction for recent commits
14
+ python -m attune_llm.git_pattern_extractor --commits 5
15
+
16
+ Author: Empathy Framework Team
17
+ Version: 2.1.3
18
+ License: Fair Source 0.9
19
+ """
20
+
21
+ import hashlib
22
+ import json
23
+ import logging
24
+ import re
25
+ import subprocess
26
+ from datetime import datetime
27
+ from pathlib import Path
28
+ from typing import Any
29
+
30
+ logger = logging.getLogger(__name__)
31
+
32
+
33
+ class GitPatternExtractor:
34
+ """Extracts bug fix patterns from git commits.
35
+
36
+ Analyzes commit messages and diffs to detect common
37
+ fix patterns, then creates draft pattern files.
38
+ """
39
+
40
+ def __init__(self, patterns_dir: str = "./patterns"):
41
+ self.patterns_dir = Path(patterns_dir)
42
+ self.debugging_dir = self.patterns_dir / "debugging"
43
+
44
+ # Commit message patterns that indicate fixes
45
+ self._fix_message_patterns = [
46
+ (r"\bfix(?:es|ed)?\b", 1.0), # "fix", "fixes", "fixed"
47
+ (r"\bbug\b", 0.8), # "bug"
48
+ (r"\bresolve[sd]?\b", 0.9), # "resolve", "resolved"
49
+ (r"\brepair[sed]?\b", 0.8), # "repair"
50
+ (r"\bpatch(?:es|ed)?\b", 0.7), # "patch"
51
+ (r"\bcorrect[sed]?\b", 0.7), # "correct"
52
+ (r"\bhotfix\b", 1.0), # "hotfix"
53
+ (r"#\d+", 0.6), # Issue references
54
+ (r"\bclose[sd]?\s+#\d+", 0.9), # "closes #123"
55
+ ]
56
+
57
+ # Code patterns that indicate specific fix types
58
+ self._code_fix_patterns = {
59
+ "null_reference": {
60
+ "patterns": [
61
+ r"\?\.", # Optional chaining added
62
+ r"\?\?\s*\[", # Nullish coalescing with array
63
+ r"\.get\s*\([^,]+,\s*", # Python .get() with default
64
+ r"if\s*\(\s*\w+\s*(!=|!==)\s*(null|undefined)", # Null check
65
+ r"or\s*\[\]", # Python or [] fallback
66
+ ],
67
+ "description": "Null/undefined reference fix",
68
+ },
69
+ "async_timing": {
70
+ "patterns": [
71
+ r"\bawait\s+\w+", # Added await
72
+ r"async\s+def\s+", # Made async
73
+ r"\.then\s*\([^)]*\)\s*\.\s*catch", # Added error handling
74
+ ],
75
+ "description": "Async/timing fix",
76
+ },
77
+ "error_handling": {
78
+ "patterns": [
79
+ r"\btry\s*[:\{]", # Try block
80
+ r"\bexcept\s+\w+", # Python except
81
+ r"\.catch\s*\(", # Promise catch
82
+ r"\bcatch\s*\(", # Try-catch
83
+ ],
84
+ "description": "Error handling improvement",
85
+ },
86
+ "type_mismatch": {
87
+ "patterns": [
88
+ r":\s*(str|int|float|bool)", # Python type hints
89
+ r"isinstance\s*\(", # Type check
90
+ r"typeof\s+\w+\s*===", # JS typeof
91
+ ],
92
+ "description": "Type mismatch fix",
93
+ },
94
+ "import_error": {
95
+ "patterns": [
96
+ r"from\s+\w+\s+import", # Python import
97
+ r"import\s+\{[^}]+\}\s+from", # ES6 import
98
+ r"require\s*\(['\"]", # CommonJS require
99
+ ],
100
+ "description": "Import/dependency fix",
101
+ },
102
+ }
103
+
104
+ def extract_from_recent_commits(self, num_commits: int = 1) -> list[dict[str, Any]]:
105
+ """Extract patterns from recent git commits.
106
+
107
+ Args:
108
+ num_commits: Number of recent commits to analyze
109
+
110
+ Returns:
111
+ List of detected pattern dicts
112
+
113
+ """
114
+ patterns = []
115
+
116
+ for i in range(num_commits):
117
+ commit_info = self._get_commit_info(f"HEAD~{i}")
118
+ if not commit_info:
119
+ continue
120
+
121
+ # Check if this looks like a fix commit
122
+ fix_score = self._score_fix_commit(commit_info["message"])
123
+ if fix_score < 0.5:
124
+ continue
125
+
126
+ # Analyze the diff for this commit
127
+ diff = self._get_commit_diff(f"HEAD~{i + 1}", f"HEAD~{i}")
128
+ detected = self._analyze_diff(diff, commit_info)
129
+
130
+ for pattern in detected:
131
+ pattern["fix_score"] = fix_score
132
+ pattern["commit_hash"] = commit_info["hash"]
133
+ pattern["commit_message"] = commit_info["message"]
134
+ patterns.append(pattern)
135
+
136
+ return patterns
137
+
138
+ def extract_from_staged(self) -> list[dict[str, Any]]:
139
+ """Extract patterns from currently staged changes.
140
+
141
+ Returns:
142
+ List of detected pattern dicts
143
+
144
+ """
145
+ diff = self._get_staged_diff()
146
+ if not diff:
147
+ return []
148
+
149
+ commit_info = {
150
+ "hash": "staged",
151
+ "message": "staged changes",
152
+ "author": self._get_git_config("user.name") or "developer",
153
+ "date": datetime.now().isoformat(),
154
+ }
155
+
156
+ return self._analyze_diff(diff, commit_info)
157
+
158
+ def save_pattern(self, pattern: dict[str, Any]) -> Path | None:
159
+ """Save a detected pattern as a draft for review.
160
+
161
+ Args:
162
+ pattern: Pattern dict from extraction
163
+
164
+ Returns:
165
+ Path to saved file, or None if failed
166
+
167
+ """
168
+ self.debugging_dir.mkdir(parents=True, exist_ok=True)
169
+
170
+ # Generate pattern file
171
+ pattern_data = {
172
+ "bug_id": pattern["pattern_id"],
173
+ "date": datetime.now().isoformat(),
174
+ "file_path": pattern.get("file", "unknown"),
175
+ "error_type": pattern.get("type", "unknown"),
176
+ "error_message": f"From commit: {pattern.get('commit_message', '')[:80]}",
177
+ "root_cause": "", # To be filled by user
178
+ "fix_applied": pattern.get("description", ""),
179
+ "fix_code": pattern.get("code_sample", ""),
180
+ "status": "investigating", # Draft status
181
+ "resolved_by": pattern.get("author", "@developer"),
182
+ "auto_detected": True,
183
+ "commit_hash": pattern.get("commit_hash", ""),
184
+ "fix_score": pattern.get("fix_score", 0.0),
185
+ }
186
+
187
+ output_file = self.debugging_dir / f"{pattern['pattern_id']}.json"
188
+
189
+ try:
190
+ with open(output_file, "w", encoding="utf-8") as f:
191
+ json.dump(pattern_data, f, indent=2, default=str)
192
+ return output_file
193
+ except OSError as e:
194
+ logger.error("Failed to save pattern: %s", e)
195
+ return None
196
+
197
+ def _get_commit_info(self, ref: str) -> dict[str, str] | None:
198
+ """Get info about a specific commit."""
199
+ try:
200
+ result = subprocess.run(
201
+ ["git", "log", "-1", "--format=%H%n%s%n%an%n%aI", ref],
202
+ check=False,
203
+ capture_output=True,
204
+ text=True,
205
+ timeout=5,
206
+ )
207
+ if result.returncode != 0:
208
+ return None
209
+
210
+ lines = result.stdout.strip().split("\n")
211
+ if len(lines) < 4:
212
+ return None
213
+
214
+ return {
215
+ "hash": lines[0][:8],
216
+ "message": lines[1],
217
+ "author": lines[2],
218
+ "date": lines[3],
219
+ }
220
+ except Exception: # noqa: BLE001
221
+ # INTENTIONAL: Git commands may fail for various reasons (not a repo, detached HEAD, etc.)
222
+ return None
223
+
224
+ def _get_commit_diff(self, ref1: str, ref2: str) -> str:
225
+ """Get diff between two commits."""
226
+ try:
227
+ result = subprocess.run(
228
+ ["git", "diff", ref1, ref2],
229
+ check=False,
230
+ capture_output=True,
231
+ text=True,
232
+ timeout=10,
233
+ )
234
+ return result.stdout if result.returncode == 0 else ""
235
+ except Exception: # noqa: BLE001
236
+ # INTENTIONAL: Git commands may fail for various reasons (not a repo, no commits, etc.)
237
+ return ""
238
+
239
+ def _get_staged_diff(self) -> str:
240
+ """Get diff of staged changes."""
241
+ try:
242
+ result = subprocess.run(
243
+ ["git", "diff", "--cached"],
244
+ check=False,
245
+ capture_output=True,
246
+ text=True,
247
+ timeout=10,
248
+ )
249
+ return result.stdout if result.returncode == 0 else ""
250
+ except Exception: # noqa: BLE001
251
+ # INTENTIONAL: Git commands may fail for various reasons (not a repo, nothing staged, etc.)
252
+ return ""
253
+
254
+ def _get_git_config(self, key: str) -> str | None:
255
+ """Get a git config value."""
256
+ try:
257
+ result = subprocess.run(
258
+ ["git", "config", key],
259
+ check=False,
260
+ capture_output=True,
261
+ text=True,
262
+ timeout=5,
263
+ )
264
+ return result.stdout.strip() if result.returncode == 0 else None
265
+ except Exception: # noqa: BLE001
266
+ # INTENTIONAL: Git config may fail (not a repo, key not set, etc.)
267
+ return None
268
+
269
+ def _score_fix_commit(self, message: str) -> float:
270
+ """Score how likely a commit message indicates a fix."""
271
+ message_lower = message.lower()
272
+ max_score = 0.0
273
+
274
+ for pattern, score in self._fix_message_patterns:
275
+ if re.search(pattern, message_lower, re.IGNORECASE):
276
+ max_score = max(max_score, score)
277
+
278
+ return max_score
279
+
280
+ def _analyze_diff(
281
+ self,
282
+ diff: str,
283
+ commit_info: dict[str, str],
284
+ ) -> list[dict[str, Any]]:
285
+ """Analyze a diff for fix patterns."""
286
+ patterns = []
287
+ current_file = ""
288
+ added_lines: list[str] = []
289
+
290
+ for line in diff.split("\n"):
291
+ if line.startswith("diff --git"):
292
+ # Process previous file
293
+ if current_file and added_lines:
294
+ file_patterns = self._detect_fix_patterns(
295
+ current_file,
296
+ added_lines,
297
+ commit_info,
298
+ )
299
+ patterns.extend(file_patterns)
300
+
301
+ # Start new file
302
+ match = re.search(r"b/(.+)$", line)
303
+ current_file = match.group(1) if match else ""
304
+ added_lines = []
305
+
306
+ elif line.startswith("+") and not line.startswith("+++"):
307
+ added_lines.append(line[1:])
308
+
309
+ # Process last file
310
+ if current_file and added_lines:
311
+ file_patterns = self._detect_fix_patterns(current_file, added_lines, commit_info)
312
+ patterns.extend(file_patterns)
313
+
314
+ return patterns
315
+
316
+ def _detect_fix_patterns(
317
+ self,
318
+ file_path: str,
319
+ added_lines: list[str],
320
+ commit_info: dict[str, str],
321
+ ) -> list[dict[str, Any]]:
322
+ """Detect fix patterns in added lines."""
323
+ detected = []
324
+ added_content = "\n".join(added_lines)
325
+
326
+ for fix_type, config in self._code_fix_patterns.items():
327
+ matches = []
328
+ for pattern in config["patterns"]:
329
+ found = re.findall(pattern, added_content)
330
+ if found:
331
+ matches.extend(found)
332
+
333
+ if matches:
334
+ pattern_id = self._generate_pattern_id(file_path, fix_type)
335
+ detected.append(
336
+ {
337
+ "pattern_id": pattern_id,
338
+ "type": fix_type,
339
+ "file": file_path,
340
+ "description": config["description"],
341
+ "code_sample": matches[0] if matches else "",
342
+ "matches_count": len(matches),
343
+ "author": commit_info.get("author", "unknown"),
344
+ "date": commit_info.get("date", datetime.now().isoformat()),
345
+ },
346
+ )
347
+
348
+ return detected
349
+
350
+ def _generate_pattern_id(self, file_path: str, pattern_type: str) -> str:
351
+ """Generate unique pattern ID."""
352
+ date_str = datetime.now().strftime("%Y%m%d")
353
+ content = f"{file_path}:{pattern_type}:{datetime.now().isoformat()}"
354
+ hash_suffix = hashlib.md5(content.encode(), usedforsecurity=False).hexdigest()[:8]
355
+ return f"bug_{date_str}_{hash_suffix}"
356
+
357
+
358
+ def main():
359
+ """CLI entry point for git pattern extraction."""
360
+ import argparse
361
+
362
+ parser = argparse.ArgumentParser(
363
+ description="Extract bug fix patterns from git commits",
364
+ formatter_class=argparse.RawDescriptionHelpFormatter,
365
+ epilog="""
366
+ Examples:
367
+ # Extract from last commit (post-commit hook)
368
+ python -m attune_llm.git_pattern_extractor
369
+
370
+ # Extract from last 5 commits
371
+ python -m attune_llm.git_pattern_extractor --commits 5
372
+
373
+ # Extract from staged changes
374
+ python -m attune_llm.git_pattern_extractor --staged
375
+
376
+ # Save detected patterns
377
+ python -m attune_llm.git_pattern_extractor --save
378
+ """,
379
+ )
380
+
381
+ parser.add_argument("--commits", type=int, default=1, help="Number of commits to analyze")
382
+ parser.add_argument("--staged", action="store_true", help="Analyze staged changes instead")
383
+ parser.add_argument("--save", action="store_true", help="Save detected patterns to files")
384
+ parser.add_argument("--patterns-dir", default="./patterns", help="Patterns directory")
385
+ parser.add_argument("--quiet", action="store_true", help="Suppress output (for hooks)")
386
+
387
+ args = parser.parse_args()
388
+
389
+ # Configure logging
390
+ log_level = logging.WARNING if args.quiet else logging.INFO
391
+ logging.basicConfig(level=log_level, format="%(levelname)s: %(message)s")
392
+
393
+ extractor = GitPatternExtractor(args.patterns_dir)
394
+
395
+ # Extract patterns
396
+ if args.staged:
397
+ patterns = extractor.extract_from_staged()
398
+ else:
399
+ patterns = extractor.extract_from_recent_commits(args.commits)
400
+
401
+ if not patterns:
402
+ if not args.quiet:
403
+ print("No fix patterns detected.")
404
+ return
405
+
406
+ # Display or save patterns
407
+ if not args.quiet:
408
+ print(f"\n{'=' * 50}")
409
+ print(f"Detected {len(patterns)} fix pattern(s)")
410
+ print(f"{'=' * 50}\n")
411
+
412
+ for pattern in patterns:
413
+ if not args.quiet:
414
+ print(f" Pattern: {pattern['pattern_id']}")
415
+ print(f" Type: {pattern['type']}")
416
+ print(f" File: {pattern['file']}")
417
+ print(f" Description: {pattern['description']}")
418
+ if "commit_message" in pattern:
419
+ print(f" Commit: {pattern['commit_message'][:60]}...")
420
+ print(f" Confidence: {pattern.get('fix_score', 0):.0%}")
421
+ print()
422
+
423
+ if args.save:
424
+ saved_path = extractor.save_pattern(pattern)
425
+ if saved_path and not args.quiet:
426
+ print(f" ✓ Saved to: {saved_path}")
427
+ print()
428
+
429
+ if args.save and not args.quiet:
430
+ print("\nPatterns saved with 'investigating' status.")
431
+ print("Use 'empathy patterns resolve <id>' to complete them.")
432
+
433
+
434
+ if __name__ == "__main__":
435
+ main()
@@ -0,0 +1,24 @@
1
+ """Hook System for Empathy Framework
2
+
3
+ Event-driven automation system for Empathy Framework.
4
+ Supports PreToolUse, PostToolUse, SessionStart, SessionEnd, PreCompact, and Stop events.
5
+
6
+ Architectural patterns inspired by everything-claude-code by Affaan Mustafa.
7
+ See: https://github.com/affaan-m/everything-claude-code (MIT License)
8
+ See: ACKNOWLEDGMENTS.md for full attribution.
9
+
10
+ Copyright 2025 Smart-AI-Memory
11
+ Licensed under Fair Source License 0.9
12
+ """
13
+
14
+ from attune_llm.hooks.config import HookConfig, HookDefinition, HookEvent
15
+ from attune_llm.hooks.executor import HookExecutor
16
+ from attune_llm.hooks.registry import HookRegistry
17
+
18
+ __all__ = [
19
+ "HookConfig",
20
+ "HookDefinition",
21
+ "HookEvent",
22
+ "HookExecutor",
23
+ "HookRegistry",
24
+ ]