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,514 @@
1
+ """Pattern Extractor for Continuous Learning
2
+
3
+ Extracts learnable patterns from collaboration sessions.
4
+ Identifies and structures patterns for storage and future application.
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, LLC
11
+ Licensed under Fair Source 0.9
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import hashlib
17
+ import logging
18
+ import re
19
+ from dataclasses import dataclass, field
20
+ from datetime import datetime
21
+ from enum import Enum
22
+ from typing import TYPE_CHECKING, Any
23
+
24
+ if TYPE_CHECKING:
25
+ from attune_llm.state import CollaborationState
26
+
27
+ logger = logging.getLogger(__name__)
28
+
29
+
30
+ class PatternCategory(Enum):
31
+ """Categories of extractable patterns."""
32
+
33
+ ERROR_RESOLUTION = "error_resolution" # How errors were resolved
34
+ USER_CORRECTION = "user_correction" # "Actually, I meant..." patterns
35
+ WORKAROUND = "workaround" # Framework quirk solutions
36
+ PREFERENCE = "preference" # Response format preferences
37
+ PROJECT_SPECIFIC = "project_specific" # Project conventions
38
+ DEBUGGING_TECHNIQUE = "debugging_technique" # Debugging approaches
39
+ CODE_PATTERN = "code_pattern" # Code-related patterns
40
+
41
+
42
+ @dataclass
43
+ class ExtractedPattern:
44
+ """A pattern extracted from a session."""
45
+
46
+ category: PatternCategory
47
+ trigger: str # What triggers this pattern
48
+ context: str # Context in which it applies
49
+ resolution: str # What was done / learned
50
+ confidence: float # Extraction confidence (0.0-1.0)
51
+ source_session: str # Session ID
52
+ extracted_at: datetime = field(default_factory=datetime.now)
53
+ tags: list[str] = field(default_factory=list)
54
+ metadata: dict[str, Any] = field(default_factory=dict)
55
+
56
+ @property
57
+ def pattern_id(self) -> str:
58
+ """Generate unique pattern ID."""
59
+ content = f"{self.category.value}:{self.trigger}:{self.resolution}"
60
+ return hashlib.sha256(content.encode()).hexdigest()[:12]
61
+
62
+ def to_dict(self) -> dict[str, Any]:
63
+ """Convert to dictionary."""
64
+ return {
65
+ "pattern_id": self.pattern_id,
66
+ "category": self.category.value,
67
+ "trigger": self.trigger,
68
+ "context": self.context,
69
+ "resolution": self.resolution,
70
+ "confidence": self.confidence,
71
+ "source_session": self.source_session,
72
+ "extracted_at": self.extracted_at.isoformat(),
73
+ "tags": self.tags,
74
+ "metadata": self.metadata,
75
+ }
76
+
77
+ @classmethod
78
+ def from_dict(cls, data: dict[str, Any]) -> ExtractedPattern:
79
+ """Create from dictionary."""
80
+ return cls(
81
+ category=PatternCategory(data["category"]),
82
+ trigger=data["trigger"],
83
+ context=data["context"],
84
+ resolution=data["resolution"],
85
+ confidence=data.get("confidence", 0.5),
86
+ source_session=data.get("source_session", ""),
87
+ extracted_at=datetime.fromisoformat(data["extracted_at"])
88
+ if "extracted_at" in data
89
+ else datetime.now(),
90
+ tags=data.get("tags", []),
91
+ metadata=data.get("metadata", {}),
92
+ )
93
+
94
+ def format_readable(self) -> str:
95
+ """Format as human-readable text."""
96
+ lines = [
97
+ f"**{self.category.value.replace('_', ' ').title()}**",
98
+ f"- **Trigger**: {self.trigger}",
99
+ f"- **Context**: {self.context}",
100
+ f"- **Resolution**: {self.resolution}",
101
+ f"- **Confidence**: {self.confidence:.0%}",
102
+ ]
103
+ if self.tags:
104
+ lines.append(f"- **Tags**: {', '.join(self.tags)}")
105
+ return "\n".join(lines)
106
+
107
+
108
+ class PatternExtractor:
109
+ """Extracts patterns from collaboration sessions.
110
+
111
+ Analyzes session interactions to identify and structure
112
+ patterns that can be learned and applied in future sessions.
113
+ """
114
+
115
+ # Correction indicators for user_correction patterns
116
+ CORRECTION_STARTERS = [
117
+ "actually",
118
+ "no,",
119
+ "i meant",
120
+ "let me clarify",
121
+ "to be clear",
122
+ "what i really want",
123
+ "correction:",
124
+ ]
125
+
126
+ def __init__(
127
+ self,
128
+ min_confidence: float = 0.3,
129
+ max_patterns_per_session: int = 10,
130
+ ):
131
+ """Initialize the extractor.
132
+
133
+ Args:
134
+ min_confidence: Minimum confidence to include pattern
135
+ max_patterns_per_session: Maximum patterns to extract per session
136
+ """
137
+ self._min_confidence = min_confidence
138
+ self._max_patterns = max_patterns_per_session
139
+
140
+ def extract_patterns(
141
+ self,
142
+ state: CollaborationState,
143
+ session_id: str = "",
144
+ ) -> list[ExtractedPattern]:
145
+ """Extract all patterns from a session.
146
+
147
+ Args:
148
+ state: Collaboration state to analyze
149
+ session_id: Optional session identifier
150
+
151
+ Returns:
152
+ List of extracted patterns
153
+ """
154
+ patterns = []
155
+
156
+ # Extract user corrections
157
+ patterns.extend(self._extract_corrections(state, session_id))
158
+
159
+ # Extract error resolutions
160
+ patterns.extend(self._extract_error_resolutions(state, session_id))
161
+
162
+ # Extract workarounds
163
+ patterns.extend(self._extract_workarounds(state, session_id))
164
+
165
+ # Extract preferences
166
+ patterns.extend(self._extract_preferences(state, session_id))
167
+
168
+ # Extract project-specific patterns
169
+ patterns.extend(self._extract_project_patterns(state, session_id))
170
+
171
+ # Filter by confidence and limit
172
+ patterns = [p for p in patterns if p.confidence >= self._min_confidence]
173
+ patterns = sorted(patterns, key=lambda p: p.confidence, reverse=True)
174
+ patterns = patterns[: self._max_patterns]
175
+
176
+ logger.info(f"Extracted {len(patterns)} patterns from session")
177
+ return patterns
178
+
179
+ def _extract_corrections(
180
+ self,
181
+ state: CollaborationState,
182
+ session_id: str,
183
+ ) -> list[ExtractedPattern]:
184
+ """Extract user correction patterns."""
185
+ patterns = []
186
+ interactions = state.interactions
187
+
188
+ for i, interaction in enumerate(interactions):
189
+ if interaction.role != "user":
190
+ continue
191
+
192
+ content_lower = interaction.content.lower()
193
+
194
+ # Check for correction indicators
195
+ is_correction = any(
196
+ content_lower.startswith(starter) or f" {starter}" in content_lower
197
+ for starter in self.CORRECTION_STARTERS
198
+ )
199
+
200
+ if not is_correction:
201
+ continue
202
+
203
+ # Get the previous assistant message (what was corrected)
204
+ prev_assistant = None
205
+ for j in range(i - 1, -1, -1):
206
+ if interactions[j].role == "assistant":
207
+ prev_assistant = interactions[j]
208
+ break
209
+
210
+ # Get the resolution (next assistant message)
211
+ resolution = None
212
+ for j in range(i + 1, len(interactions)):
213
+ if interactions[j].role == "assistant":
214
+ resolution = interactions[j]
215
+ break
216
+
217
+ if prev_assistant and resolution:
218
+ pattern = ExtractedPattern(
219
+ category=PatternCategory.USER_CORRECTION,
220
+ trigger=self._summarize(prev_assistant.content, 100),
221
+ context=interaction.content,
222
+ resolution=self._summarize(resolution.content, 150),
223
+ confidence=0.7,
224
+ source_session=session_id,
225
+ tags=["correction", "clarification"],
226
+ )
227
+ patterns.append(pattern)
228
+
229
+ return patterns
230
+
231
+ def _extract_error_resolutions(
232
+ self,
233
+ state: CollaborationState,
234
+ session_id: str,
235
+ ) -> list[ExtractedPattern]:
236
+ """Extract error resolution patterns."""
237
+ patterns = []
238
+ interactions = state.interactions
239
+
240
+ error_patterns = [
241
+ r"error[:\s]",
242
+ r"exception[:\s]",
243
+ r"failed[:\s]",
244
+ r"traceback",
245
+ r"cannot\s",
246
+ r"unable to",
247
+ ]
248
+ error_re = re.compile("|".join(error_patterns), re.IGNORECASE)
249
+
250
+ success_patterns = [
251
+ r"that works",
252
+ r"works now",
253
+ r"fixed",
254
+ r"solved",
255
+ r"thank",
256
+ r"perfect",
257
+ ]
258
+ success_re = re.compile("|".join(success_patterns), re.IGNORECASE)
259
+
260
+ # Find error mentions and track resolutions
261
+ for i, interaction in enumerate(interactions):
262
+ if interaction.role != "user":
263
+ continue
264
+
265
+ if not error_re.search(interaction.content):
266
+ continue
267
+
268
+ # Look for successful resolution later
269
+ error_context = interaction.content
270
+ resolution_text = None
271
+ assistant_fix = None
272
+
273
+ for j in range(i + 1, len(interactions)):
274
+ other = interactions[j]
275
+
276
+ if other.role == "assistant":
277
+ # Capture the assistant's response to the error
278
+ if not assistant_fix:
279
+ assistant_fix = other.content
280
+
281
+ elif other.role == "user" and success_re.search(other.content):
282
+ # Found success confirmation
283
+ resolution_text = assistant_fix
284
+ break
285
+
286
+ if resolution_text:
287
+ pattern = ExtractedPattern(
288
+ category=PatternCategory.ERROR_RESOLUTION,
289
+ trigger=self._extract_error_summary(error_context),
290
+ context=self._summarize(error_context, 100),
291
+ resolution=self._summarize(resolution_text, 200),
292
+ confidence=0.8,
293
+ source_session=session_id,
294
+ tags=["error", "debugging", "fix"],
295
+ )
296
+ patterns.append(pattern)
297
+
298
+ return patterns
299
+
300
+ def _extract_workarounds(
301
+ self,
302
+ state: CollaborationState,
303
+ session_id: str,
304
+ ) -> list[ExtractedPattern]:
305
+ """Extract workaround patterns."""
306
+ patterns = []
307
+
308
+ workaround_indicators = [
309
+ r"workaround",
310
+ r"instead",
311
+ r"alternative",
312
+ r"hack",
313
+ r"trick",
314
+ r"work around",
315
+ ]
316
+ workaround_re = re.compile("|".join(workaround_indicators), re.IGNORECASE)
317
+
318
+ for interaction in state.interactions:
319
+ if interaction.role != "assistant":
320
+ continue
321
+
322
+ if not workaround_re.search(interaction.content):
323
+ continue
324
+
325
+ # Extract the workaround description
326
+ content = interaction.content
327
+
328
+ pattern = ExtractedPattern(
329
+ category=PatternCategory.WORKAROUND,
330
+ trigger="Framework/library limitation",
331
+ context=self._extract_context_around_keyword(content, workaround_indicators),
332
+ resolution=self._summarize(content, 200),
333
+ confidence=0.6,
334
+ source_session=session_id,
335
+ tags=["workaround", "hack"],
336
+ )
337
+ patterns.append(pattern)
338
+
339
+ return patterns
340
+
341
+ def _extract_preferences(
342
+ self,
343
+ state: CollaborationState,
344
+ session_id: str,
345
+ ) -> list[ExtractedPattern]:
346
+ """Extract user preference patterns."""
347
+ patterns = []
348
+
349
+ preference_indicators = [
350
+ (r"i prefer\s+(\w+(?:\s+\w+){0,5})", "preference"),
351
+ (r"i like\s+(\w+(?:\s+\w+){0,5})", "like"),
352
+ (r"i don't like\s+(\w+(?:\s+\w+){0,5})", "dislike"),
353
+ (r"please always\s+(\w+(?:\s+\w+){0,5})", "always"),
354
+ (r"please don't\s+(\w+(?:\s+\w+){0,5})", "never"),
355
+ (r"i always\s+(\w+(?:\s+\w+){0,5})", "habit"),
356
+ ]
357
+
358
+ for interaction in state.interactions:
359
+ if interaction.role != "user":
360
+ continue
361
+
362
+ content_lower = interaction.content.lower()
363
+
364
+ for pattern_str, pref_type in preference_indicators:
365
+ matches = re.findall(pattern_str, content_lower)
366
+ for match in matches:
367
+ pattern = ExtractedPattern(
368
+ category=PatternCategory.PREFERENCE,
369
+ trigger=pref_type,
370
+ context=f"User expressed: {match}",
371
+ resolution=self._summarize(interaction.content, 100),
372
+ confidence=0.5,
373
+ source_session=session_id,
374
+ tags=["preference", pref_type],
375
+ )
376
+ patterns.append(pattern)
377
+
378
+ return patterns
379
+
380
+ def _extract_project_patterns(
381
+ self,
382
+ state: CollaborationState,
383
+ session_id: str,
384
+ ) -> list[ExtractedPattern]:
385
+ """Extract project-specific patterns."""
386
+ patterns = []
387
+
388
+ # Look for conventions, file structures, naming patterns
389
+ convention_indicators = [
390
+ r"in this project",
391
+ r"we always",
392
+ r"our convention",
393
+ r"the pattern here",
394
+ r"this codebase",
395
+ ]
396
+ convention_re = re.compile("|".join(convention_indicators), re.IGNORECASE)
397
+
398
+ for interaction in state.interactions:
399
+ if not convention_re.search(interaction.content):
400
+ continue
401
+
402
+ pattern = ExtractedPattern(
403
+ category=PatternCategory.PROJECT_SPECIFIC,
404
+ trigger="Project convention",
405
+ context=self._extract_context_around_keyword(
406
+ interaction.content, convention_indicators
407
+ ),
408
+ resolution=self._summarize(interaction.content, 150),
409
+ confidence=0.6,
410
+ source_session=session_id,
411
+ tags=["project", "convention"],
412
+ )
413
+ patterns.append(pattern)
414
+
415
+ return patterns
416
+
417
+ def _summarize(self, text: str, max_length: int) -> str:
418
+ """Summarize text to max length."""
419
+ text = text.strip()
420
+ if len(text) <= max_length:
421
+ return text
422
+
423
+ # Try to cut at sentence boundary
424
+ truncated = text[:max_length]
425
+ last_period = truncated.rfind(".")
426
+ last_newline = truncated.rfind("\n")
427
+
428
+ cut_point = max(last_period, last_newline)
429
+ if cut_point > max_length // 2:
430
+ return truncated[: cut_point + 1].strip()
431
+
432
+ return truncated.strip() + "..."
433
+
434
+ def _extract_error_summary(self, error_text: str) -> str:
435
+ """Extract a summary of the error."""
436
+ # Look for common error patterns
437
+ error_patterns = [
438
+ r"(Error|Exception):\s*([^\n]+)",
439
+ r"(cannot|unable to)\s+([^\n.]+)",
440
+ r"(failed to)\s+([^\n.]+)",
441
+ ]
442
+
443
+ for pattern in error_patterns:
444
+ match = re.search(pattern, error_text, re.IGNORECASE)
445
+ if match:
446
+ return match.group(0)[:100]
447
+
448
+ # Fall back to first line
449
+ first_line = error_text.split("\n")[0]
450
+ return self._summarize(first_line, 100)
451
+
452
+ def _extract_context_around_keyword(
453
+ self,
454
+ text: str,
455
+ keywords: list[str],
456
+ ) -> str:
457
+ """Extract context around matching keywords."""
458
+ text_lower = text.lower()
459
+
460
+ for keyword in keywords:
461
+ # Clean keyword for search
462
+ search_term = keyword.replace(r"\s+", " ").replace("\\", "")
463
+ match = re.search(search_term, text_lower, re.IGNORECASE)
464
+
465
+ if match:
466
+ # Get surrounding context
467
+ start = max(0, match.start() - 50)
468
+ end = min(len(text), match.end() + 100)
469
+
470
+ context = text[start:end]
471
+ if start > 0:
472
+ context = "..." + context
473
+ if end < len(text):
474
+ context = context + "..."
475
+
476
+ return context
477
+
478
+ return self._summarize(text, 150)
479
+
480
+ def categorize_pattern(
481
+ self,
482
+ trigger: str,
483
+ content: str,
484
+ ) -> PatternCategory:
485
+ """Categorize a pattern based on content.
486
+
487
+ Args:
488
+ trigger: The trigger text
489
+ content: The pattern content
490
+
491
+ Returns:
492
+ Appropriate PatternCategory
493
+ """
494
+ content_lower = content.lower()
495
+ trigger_lower = trigger.lower()
496
+
497
+ if any(word in content_lower for word in ["error", "exception", "failed", "fix", "bug"]):
498
+ return PatternCategory.ERROR_RESOLUTION
499
+
500
+ if any(word in trigger_lower for word in ["actually", "correction", "meant", "clarify"]):
501
+ return PatternCategory.USER_CORRECTION
502
+
503
+ if any(word in content_lower for word in ["workaround", "instead", "alternative", "hack"]):
504
+ return PatternCategory.WORKAROUND
505
+
506
+ if any(word in content_lower for word in ["prefer", "like", "always", "never", "style"]):
507
+ return PatternCategory.PREFERENCE
508
+
509
+ if any(
510
+ word in content_lower for word in ["project", "codebase", "convention", "this repo"]
511
+ ):
512
+ return PatternCategory.PROJECT_SPECIFIC
513
+
514
+ return PatternCategory.CODE_PATTERN