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
attune/discovery.py ADDED
@@ -0,0 +1,306 @@
1
+ """Progressive Feature Discovery for Empathy Framework
2
+
3
+ Surface tips and suggestions at the right time based on usage patterns.
4
+ Helps users discover power-user features without overwhelming them upfront.
5
+
6
+ Copyright 2025 Smart-AI-Memory
7
+ Licensed under Fair Source License 0.9
8
+ """
9
+
10
+ import json
11
+ from datetime import datetime
12
+ from pathlib import Path
13
+
14
+ from attune.config import _validate_file_path
15
+
16
+ # Discovery tips with conditions
17
+ DISCOVERY_TIPS = {
18
+ # After first commands
19
+ "after_first_inspect": {
20
+ "tip": "Try 'empathy ship' before commits for automated pre-flight checks",
21
+ "trigger": "inspect",
22
+ "min_uses": 1,
23
+ "priority": 2,
24
+ "shown": False,
25
+ },
26
+ "after_first_health": {
27
+ "tip": "Use 'empathy fix-all' to auto-fix lint and format issues",
28
+ "trigger": "health",
29
+ "min_uses": 1,
30
+ "priority": 2,
31
+ "shown": False,
32
+ },
33
+ # After accumulating usage
34
+ "after_10_inspects": {
35
+ "tip": "You've got patterns! Run 'empathy sync-claude' to share them with Claude Code",
36
+ "trigger": "inspect",
37
+ "min_uses": 10,
38
+ "priority": 1,
39
+ "shown": False,
40
+ },
41
+ "after_5_ships": {
42
+ "tip": "Start your day with 'empathy morning' for a productivity briefing",
43
+ "trigger": "ship",
44
+ "min_uses": 5,
45
+ "priority": 1,
46
+ "shown": False,
47
+ },
48
+ # Context-based tips
49
+ "high_tech_debt": {
50
+ "tip": "Tech debt is trending up. Try 'empathy status' for priority focus areas",
51
+ "condition": lambda stats: stats.get("tech_debt_trend") == "increasing",
52
+ "priority": 1,
53
+ "shown": False,
54
+ },
55
+ "no_patterns": {
56
+ "tip": "Run 'empathy learn' to extract patterns from your git history",
57
+ "condition": lambda stats: stats.get("patterns_learned", 0) == 0
58
+ and stats.get("total_commands", 0) > 5,
59
+ "priority": 1,
60
+ "shown": False,
61
+ },
62
+ "cost_savings": {
63
+ "tip": "Check your API savings with 'empathy costs' - model routing can save 80%!",
64
+ "condition": lambda stats: stats.get("api_requests", 0) > 10,
65
+ "priority": 2,
66
+ "shown": False,
67
+ },
68
+ # Weekly reminders
69
+ "weekly_sync": {
70
+ "tip": "Weekly reminder: Run 'empathy sync-claude' to keep Claude Code patterns current",
71
+ "condition": lambda stats: _days_since_sync(stats) >= 7,
72
+ "priority": 2,
73
+ "shown": False,
74
+ },
75
+ }
76
+
77
+
78
+ def _days_since_sync(stats: dict) -> int:
79
+ """Calculate days since last Claude sync."""
80
+ last_sync = stats.get("last_claude_sync")
81
+ if not last_sync:
82
+ return 999
83
+ try:
84
+ sync_date = datetime.fromisoformat(last_sync)
85
+ return (datetime.now() - sync_date).days
86
+ except (ValueError, TypeError):
87
+ return 999
88
+
89
+
90
+ class DiscoveryEngine:
91
+ """Tracks usage and surfaces contextual tips.
92
+
93
+ Usage:
94
+ engine = DiscoveryEngine()
95
+ engine.record_command("inspect")
96
+ tips = engine.get_pending_tips()
97
+ engine.mark_shown("after_first_inspect")
98
+ """
99
+
100
+ def __init__(self, storage_dir: str = ".empathy"):
101
+ """Initialize discovery engine."""
102
+ self.storage_dir = Path(storage_dir)
103
+ self.storage_dir.mkdir(parents=True, exist_ok=True)
104
+ self.stats_file = self.storage_dir / "discovery_stats.json"
105
+ self._load()
106
+
107
+ def _load(self) -> None:
108
+ """Load discovery state from storage."""
109
+ if self.stats_file.exists():
110
+ try:
111
+ with open(self.stats_file) as f:
112
+ self.state = json.load(f)
113
+ except (OSError, json.JSONDecodeError):
114
+ self.state = self._default_state()
115
+ else:
116
+ self.state = self._default_state()
117
+
118
+ def _default_state(self) -> dict:
119
+ """Return default state structure."""
120
+ return {
121
+ "command_counts": {},
122
+ "tips_shown": [],
123
+ "total_commands": 0,
124
+ "patterns_learned": 0,
125
+ "api_requests": 0,
126
+ "tech_debt_trend": "unknown",
127
+ "last_claude_sync": None,
128
+ "first_run": datetime.now().isoformat(),
129
+ "last_updated": datetime.now().isoformat(),
130
+ }
131
+
132
+ def _save(self) -> None:
133
+ """Save state to storage."""
134
+ self.state["last_updated"] = datetime.now().isoformat()
135
+ validated_path = _validate_file_path(str(self.stats_file))
136
+ with open(validated_path, "w") as f:
137
+ json.dump(self.state, f, indent=2)
138
+
139
+ def record_command(self, command: str) -> list:
140
+ """Record a command execution and return any triggered tips.
141
+
142
+ Args:
143
+ command: The command that was executed
144
+
145
+ Returns:
146
+ List of tip messages to show
147
+
148
+ """
149
+ # Update counts
150
+ counts = self.state.get("command_counts", {})
151
+ counts[command] = counts.get(command, 0) + 1
152
+ self.state["command_counts"] = counts
153
+ self.state["total_commands"] = self.state.get("total_commands", 0) + 1
154
+
155
+ self._save()
156
+
157
+ # Check for triggered tips
158
+ return self.get_pending_tips(trigger=command)
159
+
160
+ def record_patterns_learned(self, count: int) -> None:
161
+ """Record patterns learned."""
162
+ self.state["patterns_learned"] = self.state.get("patterns_learned", 0) + count
163
+ self._save()
164
+
165
+ def record_api_request(self) -> None:
166
+ """Record an API request."""
167
+ self.state["api_requests"] = self.state.get("api_requests", 0) + 1
168
+ self._save()
169
+
170
+ def record_claude_sync(self) -> None:
171
+ """Record a Claude sync."""
172
+ self.state["last_claude_sync"] = datetime.now().isoformat()
173
+ self._save()
174
+
175
+ def set_tech_debt_trend(self, trend: str) -> None:
176
+ """Set tech debt trend (increasing/decreasing/stable)."""
177
+ self.state["tech_debt_trend"] = trend
178
+ self._save()
179
+
180
+ def get_pending_tips(self, trigger: str | None = None, max_tips: int = 2) -> list:
181
+ """Get pending tips based on current state.
182
+
183
+ Args:
184
+ trigger: Command that triggered this check (optional)
185
+ max_tips: Maximum number of tips to return
186
+
187
+ Returns:
188
+ List of tip messages
189
+
190
+ """
191
+ tips_to_show = []
192
+ shown_tips = set(self.state.get("tips_shown", []))
193
+
194
+ for tip_id, tip_config in DISCOVERY_TIPS.items():
195
+ # Skip if already shown
196
+ if tip_id in shown_tips:
197
+ continue
198
+
199
+ should_show = False
200
+
201
+ # Check trigger-based tips
202
+ if "trigger" in tip_config:
203
+ if trigger == tip_config["trigger"]:
204
+ count = self.state.get("command_counts", {}).get(trigger, 0)
205
+ if count >= tip_config.get("min_uses", 1):
206
+ should_show = True
207
+
208
+ # Check condition-based tips
209
+ elif "condition" in tip_config:
210
+ try:
211
+ condition = tip_config["condition"]
212
+ if callable(condition) and condition(self.state):
213
+ should_show = True
214
+ except Exception:
215
+ pass
216
+
217
+ if should_show:
218
+ tips_to_show.append(
219
+ {
220
+ "id": tip_id,
221
+ "tip": tip_config["tip"],
222
+ "priority": tip_config.get("priority", 3),
223
+ },
224
+ )
225
+
226
+ # Sort by priority and limit - ensure we get an int for sorting
227
+ def get_priority(x: dict) -> int:
228
+ p = x.get("priority", 3)
229
+ return int(p) if isinstance(p, int | float | str) else 3
230
+
231
+ tips_to_show.sort(key=get_priority)
232
+ return tips_to_show[:max_tips]
233
+
234
+ def mark_shown(self, tip_id: str) -> None:
235
+ """Mark a tip as shown so it won't be repeated."""
236
+ shown = self.state.get("tips_shown", [])
237
+ if tip_id not in shown:
238
+ shown.append(tip_id)
239
+ self.state["tips_shown"] = shown
240
+ self._save()
241
+
242
+ def get_stats(self) -> dict:
243
+ """Get current discovery statistics."""
244
+ return {
245
+ "total_commands": self.state.get("total_commands", 0),
246
+ "command_counts": self.state.get("command_counts", {}),
247
+ "patterns_learned": self.state.get("patterns_learned", 0),
248
+ "tips_shown": len(self.state.get("tips_shown", [])),
249
+ "tips_remaining": len(DISCOVERY_TIPS) - len(self.state.get("tips_shown", [])),
250
+ "days_active": self._days_active(),
251
+ }
252
+
253
+ def _days_active(self) -> int:
254
+ """Calculate days since first run."""
255
+ first_run = self.state.get("first_run")
256
+ if not first_run:
257
+ return 0
258
+ try:
259
+ first = datetime.fromisoformat(first_run)
260
+ return (datetime.now() - first).days
261
+ except (ValueError, TypeError):
262
+ return 0
263
+
264
+
265
+ # Singleton instance
266
+ _engine: DiscoveryEngine | None = None
267
+
268
+
269
+ def get_engine(storage_dir: str = ".empathy") -> DiscoveryEngine:
270
+ """Get or create the global discovery engine."""
271
+ global _engine
272
+ if _engine is None:
273
+ _engine = DiscoveryEngine(storage_dir)
274
+ return _engine
275
+
276
+
277
+ def show_tip_if_available(command: str, quiet: bool = False) -> None:
278
+ """Check for tips after a command and display them.
279
+
280
+ Args:
281
+ command: The command that was just executed
282
+ quiet: If True, don't print anything
283
+
284
+ """
285
+ engine = get_engine()
286
+ tips = engine.record_command(command)
287
+
288
+ if tips and not quiet:
289
+ print()
290
+ for tip_data in tips:
291
+ print(f" TIP: {tip_data['tip']}")
292
+ engine.mark_shown(tip_data["id"])
293
+ print()
294
+
295
+
296
+ def format_tips_for_cli(tips: list) -> str:
297
+ """Format tips for CLI output."""
298
+ if not tips:
299
+ return ""
300
+
301
+ lines = ["\n TIPS", " " + "-" * 38]
302
+ for tip_data in tips:
303
+ lines.append(f" {tip_data['tip']}")
304
+ lines.append("")
305
+
306
+ return "\n".join(lines)
attune/emergence.py ADDED
@@ -0,0 +1,306 @@
1
+ """Emergence Detection for AI-Human Collaboration
2
+
3
+ Detects emergent properties in AI-human collaboration - system-level behaviors
4
+ that arise from component interactions but aren't properties of components.
5
+
6
+ Based on systems thinking principles from Donella Meadows and Peter Senge.
7
+
8
+ Copyright 2025 Smart AI Memory, LLC
9
+ Licensed under Fair Source 0.9
10
+ """
11
+
12
+ from dataclasses import dataclass, field
13
+ from datetime import datetime
14
+ from typing import Any
15
+
16
+
17
+ @dataclass
18
+ class EmergentProperty:
19
+ """An emergent property discovered in the system
20
+
21
+ Emergent properties are behaviors or patterns that arise from the
22
+ interactions of system components but cannot be predicted from
23
+ the components alone.
24
+ """
25
+
26
+ property_type: str # "norm", "pattern", "behavior", "capability"
27
+ description: str
28
+ first_observed: datetime = field(default_factory=datetime.now)
29
+ confidence: float = 0.0 # 0.0-1.0
30
+ evidence: list[dict[str, Any]] = field(default_factory=list)
31
+ components_involved: list[str] = field(default_factory=list)
32
+
33
+
34
+ class EmergenceDetector:
35
+ """Detects emergent properties in AI-human collaboration
36
+
37
+ Emergent properties are system-level behaviors that arise from
38
+ component interactions but aren't properties of the components themselves.
39
+
40
+ Examples:
41
+ - Team norms that developed organically (not prescribed)
42
+ - Collaboration patterns that emerged from repeated interactions
43
+ - Shared understanding that goes beyond individual knowledge
44
+ - Trust dynamics that affect system behavior
45
+
46
+ Based on systems thinking:
47
+ - Whole is greater than sum of parts
48
+ - Properties emerge at system level
49
+ - Cannot reduce to component analysis
50
+
51
+ Example:
52
+ >>> detector = EmergenceDetector()
53
+ >>> baseline = {"trust": 0.3, "interactions": 10}
54
+ >>> current = {"trust": 0.8, "interactions": 50, "shared_patterns": 5}
55
+ >>> score = detector.measure_emergence(baseline, current)
56
+ >>> print(f"Emergence score: {score:.2f}")
57
+
58
+ """
59
+
60
+ def __init__(self):
61
+ """Initialize EmergenceDetector with tracking structures"""
62
+ self.detected_properties: list[EmergentProperty] = []
63
+ self.baseline_metrics: dict[str, Any] = {}
64
+
65
+ def detect_emergent_norms(
66
+ self,
67
+ team_interactions: list[dict[str, Any]],
68
+ ) -> list[EmergentProperty]:
69
+ """Detect team norms that emerged organically
70
+
71
+ Analyzes interaction history to identify behavioral patterns that:
72
+ 1. Were not explicitly programmed or prescribed
73
+ 2. Emerged from repeated interactions
74
+ 3. Are now consistently followed by team members
75
+
76
+ Args:
77
+ team_interactions: List of interaction records with metadata
78
+
79
+ Returns:
80
+ List of detected emergent norms
81
+
82
+ Example:
83
+ >>> interactions = [
84
+ ... {"type": "help_request", "response_time": 5},
85
+ ... {"type": "help_request", "response_time": 3},
86
+ ... {"type": "help_request", "response_time": 4}
87
+ ... ]
88
+ >>> norms = detector.detect_emergent_norms(interactions)
89
+
90
+ """
91
+ norms: list[EmergentProperty] = []
92
+
93
+ if not team_interactions:
94
+ return norms
95
+
96
+ # Detect response time norms
97
+ response_times = [
98
+ i.get("response_time", 0) for i in team_interactions if "response_time" in i
99
+ ]
100
+
101
+ if len(response_times) >= 3:
102
+ avg_response = sum(response_times) / len(response_times)
103
+ consistency = self._calculate_consistency(response_times)
104
+
105
+ if consistency > 0.7: # High consistency indicates norm
106
+ norm = EmergentProperty(
107
+ property_type="norm",
108
+ description=f"Response time norm emerged: ~{avg_response:.1f} minutes",
109
+ confidence=consistency,
110
+ evidence=[{"response_times": response_times}],
111
+ components_involved=["ai_agent", "human_user"],
112
+ )
113
+ norms.append(norm)
114
+
115
+ # Detect communication style norms
116
+ communication_patterns = self._analyze_communication_patterns(team_interactions)
117
+ if communication_patterns:
118
+ for pattern_name, pattern_data in communication_patterns.items():
119
+ if pattern_data["frequency"] > 0.6: # Appears in >60% of interactions
120
+ norm = EmergentProperty(
121
+ property_type="norm",
122
+ description=f"Communication pattern emerged: {pattern_name}",
123
+ confidence=pattern_data["frequency"],
124
+ evidence=[pattern_data],
125
+ components_involved=["communication_style"],
126
+ )
127
+ norms.append(norm)
128
+
129
+ self.detected_properties.extend(norms)
130
+ return norms
131
+
132
+ def measure_emergence(self, baseline: dict[str, Any], current: dict[str, Any]) -> float:
133
+ """Quantify emergence by comparing baseline to current state
134
+
135
+ Measures how much new system-level properties have emerged that
136
+ weren't present in the baseline state.
137
+
138
+ Args:
139
+ baseline: Initial system state metrics
140
+ current: Current system state metrics
141
+
142
+ Returns:
143
+ Emergence score (0.0-1.0), where:
144
+ - 0.0: No emergence (system unchanged)
145
+ - 0.5: Moderate emergence (some new properties)
146
+ - 1.0: High emergence (significant new system capabilities)
147
+
148
+ Example:
149
+ >>> baseline = {"trust": 0.3, "interactions": 10}
150
+ >>> current = {"trust": 0.8, "interactions": 50, "patterns": 5}
151
+ >>> score = detector.measure_emergence(baseline, current)
152
+
153
+ """
154
+ emergence_score = 0.0
155
+ max_score = 0.0
156
+
157
+ # Measure growth in key metrics
158
+ if "trust" in baseline and "trust" in current:
159
+ trust_growth = (current["trust"] - baseline["trust"]) / max(baseline["trust"], 0.1)
160
+ emergence_score += min(trust_growth, 1.0) * 0.3
161
+ max_score += 0.3
162
+
163
+ # Measure new capabilities
164
+ baseline_keys = set(baseline.keys())
165
+ current_keys = set(current.keys())
166
+ new_capabilities = current_keys - baseline_keys
167
+
168
+ if new_capabilities:
169
+ capability_score = len(new_capabilities) / max(len(baseline_keys), 1)
170
+ emergence_score += min(capability_score, 1.0) * 0.3
171
+ max_score += 0.3
172
+
173
+ # Measure interaction complexity growth
174
+ if "interactions" in baseline and "interactions" in current:
175
+ if baseline["interactions"] > 0:
176
+ interaction_ratio = current["interactions"] / baseline["interactions"]
177
+ complexity_score = min((interaction_ratio - 1.0) / 4.0, 1.0) # Normalize
178
+ emergence_score += complexity_score * 0.2
179
+ max_score += 0.2
180
+
181
+ # Measure pattern development
182
+ if "shared_patterns" in current:
183
+ pattern_score = min(current["shared_patterns"] / 10.0, 1.0)
184
+ emergence_score += pattern_score * 0.2
185
+ max_score += 0.2
186
+
187
+ # Normalize to 0-1 range
188
+ if max_score > 0:
189
+ return min(emergence_score / max_score, 1.0)
190
+ return 0.0
191
+
192
+ def detect_emergent_capabilities(
193
+ self,
194
+ historical_states: list[dict[str, Any]],
195
+ ) -> list[EmergentProperty]:
196
+ """Detect new capabilities that emerged over time
197
+
198
+ Analyzes historical system states to identify capabilities that:
199
+ 1. Weren't present initially
200
+ 2. Emerged through system evolution
201
+ 3. Enable new behaviors
202
+
203
+ Args:
204
+ historical_states: List of system states over time
205
+
206
+ Returns:
207
+ List of emergent capabilities detected
208
+
209
+ """
210
+ if len(historical_states) < 2:
211
+ return []
212
+
213
+ capabilities: list[EmergentProperty] = []
214
+ initial_state = historical_states[0]
215
+
216
+ # Track capability development
217
+ for state in historical_states[1:]:
218
+ new_keys = set(state.keys()) - set(initial_state.keys())
219
+
220
+ for key in new_keys:
221
+ capability = EmergentProperty(
222
+ property_type="capability",
223
+ description=f"New capability emerged: {key}",
224
+ confidence=0.8,
225
+ evidence=[{"state": state, "timestamp": state.get("timestamp")}],
226
+ components_involved=["system"],
227
+ )
228
+ capabilities.append(capability)
229
+
230
+ self.detected_properties.extend(capabilities)
231
+ return capabilities
232
+
233
+ def _calculate_consistency(self, values: list[float]) -> float:
234
+ """Calculate consistency of a set of values (0.0-1.0)
235
+
236
+ Uses coefficient of variation: lower variation = higher consistency
237
+ """
238
+ if not values or len(values) < 2:
239
+ return 0.0
240
+
241
+ mean = sum(values) / len(values)
242
+ if mean == 0:
243
+ return 0.0
244
+
245
+ variance = sum((x - mean) ** 2 for x in values) / len(values)
246
+ std_dev = variance**0.5
247
+ cv = std_dev / mean # Coefficient of variation
248
+
249
+ # Convert to consistency score (inverse of variation)
250
+ consistency: float = max(0.0, 1.0 - min(cv, 1.0))
251
+ return consistency
252
+
253
+ def _analyze_communication_patterns(
254
+ self,
255
+ interactions: list[dict[str, Any]],
256
+ ) -> dict[str, dict[str, Any]]:
257
+ """Analyze communication patterns in interactions
258
+
259
+ Returns dict of pattern_name -> {frequency, examples}
260
+ """
261
+ patterns: dict[str, dict[str, Any]] = {}
262
+ total_interactions = len(interactions)
263
+
264
+ if total_interactions == 0:
265
+ return patterns
266
+
267
+ # Detect clarifying questions pattern
268
+ clarifying_count = sum(1 for i in interactions if i.get("type") == "clarifying_question")
269
+ if clarifying_count > 0:
270
+ patterns["clarifying_questions"] = {
271
+ "frequency": clarifying_count / total_interactions,
272
+ "count": clarifying_count,
273
+ "examples": [i for i in interactions if i.get("type") == "clarifying_question"][:3],
274
+ }
275
+
276
+ # Detect proactive suggestions pattern
277
+ proactive_count = sum(1 for i in interactions if i.get("type") == "proactive_suggestion")
278
+ if proactive_count > 0:
279
+ patterns["proactive_suggestions"] = {
280
+ "frequency": proactive_count / total_interactions,
281
+ "count": proactive_count,
282
+ "examples": [i for i in interactions if i.get("type") == "proactive_suggestion"][
283
+ :3
284
+ ],
285
+ }
286
+
287
+ return patterns
288
+
289
+ def get_detected_properties(self, property_type: str | None = None) -> list[EmergentProperty]:
290
+ """Get all detected emergent properties, optionally filtered by type
291
+
292
+ Args:
293
+ property_type: Optional filter ("norm", "pattern", "behavior", "capability")
294
+
295
+ Returns:
296
+ List of emergent properties
297
+
298
+ """
299
+ if property_type:
300
+ return [p for p in self.detected_properties if p.property_type == property_type]
301
+ return self.detected_properties
302
+
303
+ def reset(self):
304
+ """Reset detector state"""
305
+ self.detected_properties = []
306
+ self.baseline_metrics = {}