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,487 @@
1
+ """CLAUDE.md Auto-Sync Command for Empathy Framework
2
+
3
+ Syncs learned patterns from Empathy's pattern storage to Claude Code's
4
+ .claude/rules/empathy/ directory for native integration.
5
+
6
+ Usage:
7
+ empathy sync-claude # One-time sync
8
+ empathy sync-claude --watch # Watch for changes
9
+ empathy sync-claude --dry-run # Show what would be synced
10
+
11
+ Output structure:
12
+ .claude/rules/empathy/
13
+ ├── bug-patterns.md # From patterns/debugging/
14
+ ├── security-decisions.md # From patterns/security/
15
+ ├── tech-debt-hotspots.md # From patterns/tech_debt/
16
+ └── coding-patterns.md # General patterns
17
+
18
+ Copyright 2025 Smart AI Memory, LLC
19
+ Licensed under Fair Source 0.9
20
+ """
21
+
22
+ import argparse
23
+ import json
24
+ import sys
25
+ import time
26
+ from datetime import datetime
27
+ from pathlib import Path
28
+ from typing import Any
29
+
30
+ # Output directory structure
31
+ CLAUDE_RULES_DIR = ".claude/rules/empathy"
32
+
33
+ # Pattern source directories
34
+ PATTERN_SOURCES = {
35
+ "debugging": "bug-patterns.md",
36
+ "security": "security-decisions.md",
37
+ "tech_debt": "tech-debt-hotspots.md",
38
+ "inspection": "coding-patterns.md",
39
+ }
40
+
41
+
42
+ def load_patterns_from_directory(pattern_dir: Path, pattern_type: str) -> list[dict]:
43
+ """Load all pattern JSON files from a directory.
44
+
45
+ Args:
46
+ pattern_dir: Path to pattern directory
47
+ pattern_type: Type of patterns (debugging, security, etc.)
48
+
49
+ Returns:
50
+ List of pattern dictionaries
51
+
52
+ """
53
+ patterns: list[dict[str, Any]] = []
54
+
55
+ if not pattern_dir.exists():
56
+ return patterns
57
+
58
+ for json_file in pattern_dir.glob("*.json"):
59
+ try:
60
+ with open(json_file) as f:
61
+ pattern = json.load(f)
62
+ pattern["_source_file"] = str(json_file)
63
+ pattern["_pattern_type"] = pattern_type
64
+ patterns.append(pattern)
65
+ except (json.JSONDecodeError, OSError) as e:
66
+ print(f"Warning: Could not load {json_file}: {e}", file=sys.stderr)
67
+
68
+ return patterns
69
+
70
+
71
+ def format_bug_patterns_markdown(patterns: list[dict]) -> str:
72
+ """Format debugging patterns as Claude-compatible markdown.
73
+
74
+ Args:
75
+ patterns: List of bug pattern dictionaries
76
+
77
+ Returns:
78
+ Formatted markdown string
79
+
80
+ """
81
+ lines = [
82
+ "---",
83
+ "paths: **/*.py, **/*.js, **/*.ts",
84
+ "---",
85
+ "",
86
+ "# Bug Patterns (Auto-generated by Empathy)",
87
+ f"Last sync: {datetime.now().strftime('%Y-%m-%d %H:%M')}",
88
+ "",
89
+ "These patterns help identify and fix common bugs based on your team's history.",
90
+ "",
91
+ ]
92
+
93
+ # Group by error type
94
+ by_type: dict[str, list[dict]] = {}
95
+ for p in patterns:
96
+ error_type = p.get("error_type", "unknown")
97
+ if error_type not in by_type:
98
+ by_type[error_type] = []
99
+ by_type[error_type].append(p)
100
+
101
+ for error_type, type_patterns in by_type.items():
102
+ type_title = error_type.replace("_", " ").title()
103
+ lines.append(f"## {type_title} Bugs")
104
+ lines.append("")
105
+
106
+ for p in type_patterns[:5]: # Max 5 per type
107
+ error_message = p.get("error_message", "Unknown error")
108
+ root_cause = p.get("root_cause", "")
109
+ fix_applied = p.get("fix_applied", "")
110
+ pattern_id = p.get("pattern_id", "")
111
+
112
+ lines.append(f"### When you see: `{error_message[:100]}`")
113
+ if root_cause:
114
+ lines.append(f"**Root cause:** {root_cause}")
115
+ if fix_applied:
116
+ lines.append(f"**Fix:** {fix_applied}")
117
+ if pattern_id:
118
+ lines.append(f"**Pattern ID:** {pattern_id}")
119
+ lines.append("")
120
+
121
+ return "\n".join(lines)
122
+
123
+
124
+ def format_security_decisions_markdown(patterns: list[dict]) -> str:
125
+ """Format security decisions as Claude-compatible markdown."""
126
+ lines = [
127
+ "---",
128
+ "paths: **/*.py, **/*.js, **/*.ts",
129
+ "---",
130
+ "",
131
+ "# Security Decisions (Auto-generated by Empathy)",
132
+ f"Last sync: {datetime.now().strftime('%Y-%m-%d %H:%M')}",
133
+ "",
134
+ "Team security decisions and accepted risks. Reference these before flagging issues.",
135
+ "",
136
+ ]
137
+
138
+ # Group by decision type
139
+ by_status: dict[str, list[dict]] = {"ACCEPTED": [], "FALSE_POSITIVE": [], "DEFERRED": []}
140
+
141
+ for p in patterns:
142
+ status = p.get("status", "ACCEPTED")
143
+ if status in by_status:
144
+ by_status[status].append(p)
145
+
146
+ if by_status["FALSE_POSITIVE"]:
147
+ lines.append("## False Positives (Do Not Flag)")
148
+ lines.append("")
149
+ for p in by_status["FALSE_POSITIVE"][:10]:
150
+ issue_type = p.get("issue_type", "unknown")
151
+ rationale = p.get("rationale", "")
152
+ decided_by = p.get("decided_by", "")
153
+ lines.append(f"- **{issue_type}**: {rationale}")
154
+ if decided_by:
155
+ lines.append(f" - Decided by: {decided_by}")
156
+ lines.append("")
157
+
158
+ if by_status["ACCEPTED"]:
159
+ lines.append("## Accepted Risks")
160
+ lines.append("")
161
+ for p in by_status["ACCEPTED"][:10]:
162
+ issue_type = p.get("issue_type", "unknown")
163
+ rationale = p.get("rationale", "")
164
+ lines.append(f"- **{issue_type}**: {rationale}")
165
+ lines.append("")
166
+
167
+ if by_status["DEFERRED"]:
168
+ lines.append("## Deferred (To Address Later)")
169
+ lines.append("")
170
+ for p in by_status["DEFERRED"][:10]:
171
+ issue_type = p.get("issue_type", "unknown")
172
+ rationale = p.get("rationale", "")
173
+ lines.append(f"- **{issue_type}**: {rationale}")
174
+ lines.append("")
175
+
176
+ return "\n".join(lines)
177
+
178
+
179
+ def format_tech_debt_markdown(patterns: list[dict]) -> str:
180
+ """Format tech debt hotspots as Claude-compatible markdown."""
181
+ lines = [
182
+ "---",
183
+ "paths: **/*",
184
+ "---",
185
+ "",
186
+ "# Tech Debt Hotspots (Auto-generated by Empathy)",
187
+ f"Last sync: {datetime.now().strftime('%Y-%m-%d %H:%M')}",
188
+ "",
189
+ "Areas of the codebase with accumulated technical debt.",
190
+ "",
191
+ ]
192
+
193
+ # Group by severity
194
+ by_severity: dict[str, list[dict]] = {"critical": [], "high": [], "medium": [], "low": []}
195
+
196
+ for p in patterns:
197
+ # Get debt items from snapshot
198
+ items = p.get("debt_items", [])
199
+ for item in items:
200
+ severity = item.get("severity", "medium")
201
+ if severity in by_severity:
202
+ by_severity[severity].append(item)
203
+
204
+ for severity in ["critical", "high", "medium"]:
205
+ if by_severity[severity]:
206
+ lines.append(f"## {severity.upper()} Priority")
207
+ lines.append("")
208
+ for item in by_severity[severity][:10]:
209
+ file_path = item.get("file", "")
210
+ line = item.get("line", "")
211
+ item_type = item.get("type", "")
212
+ content = item.get("content", "")[:100]
213
+ lines.append(f"- **{file_path}:{line}** ({item_type})")
214
+ if content:
215
+ lines.append(f" `{content}`")
216
+ lines.append("")
217
+
218
+ return "\n".join(lines)
219
+
220
+
221
+ def format_coding_patterns_markdown(patterns: list[dict]) -> str:
222
+ """Format general coding patterns as Claude-compatible markdown."""
223
+ lines = [
224
+ "---",
225
+ "paths: **/*",
226
+ "---",
227
+ "",
228
+ "# Coding Patterns (Auto-generated by Empathy)",
229
+ f"Last sync: {datetime.now().strftime('%Y-%m-%d %H:%M')}",
230
+ "",
231
+ "Coding patterns and quality findings from automated inspection.",
232
+ "",
233
+ ]
234
+
235
+ # Group by category
236
+ by_category: dict[str, list[dict]] = {}
237
+
238
+ for p in patterns:
239
+ category = p.get("category", "general")
240
+ if category not in by_category:
241
+ by_category[category] = []
242
+ by_category[category].append(p)
243
+
244
+ for category, cat_patterns in by_category.items():
245
+ category_title = category.replace("_", " ").title()
246
+ lines.append(f"## {category_title}")
247
+ lines.append("")
248
+
249
+ for p in cat_patterns[:10]:
250
+ description = p.get("description", "")
251
+ recommendation = p.get("recommendation", "")
252
+
253
+ if description:
254
+ lines.append(f"- {description}")
255
+ if recommendation:
256
+ lines.append(f" **Recommendation:** {recommendation}")
257
+
258
+ lines.append("")
259
+
260
+ return "\n".join(lines)
261
+
262
+
263
+ def sync_patterns(
264
+ project_root: Path,
265
+ dry_run: bool = False,
266
+ verbose: bool = False,
267
+ ) -> dict[str, Any]:
268
+ """Sync patterns to .claude/rules/empathy/ directory.
269
+
270
+ Args:
271
+ project_root: Project root directory
272
+ dry_run: If True, don't write files
273
+ verbose: If True, print detailed output
274
+
275
+ Returns:
276
+ Summary of sync operation
277
+
278
+ """
279
+ patterns_dir = project_root / "patterns"
280
+ output_dir = project_root / CLAUDE_RULES_DIR
281
+
282
+ results: dict[str, Any] = {
283
+ "synced": [],
284
+ "skipped": [],
285
+ "errors": [],
286
+ "total_patterns": 0,
287
+ }
288
+
289
+ if not patterns_dir.exists():
290
+ if verbose:
291
+ print(f"No patterns directory found at {patterns_dir}")
292
+ return results
293
+
294
+ # Create output directory
295
+ if not dry_run:
296
+ output_dir.mkdir(parents=True, exist_ok=True)
297
+
298
+ # Process each pattern type
299
+ formatters = {
300
+ "debugging": format_bug_patterns_markdown,
301
+ "security": format_security_decisions_markdown,
302
+ "tech_debt": format_tech_debt_markdown,
303
+ "inspection": format_coding_patterns_markdown,
304
+ }
305
+
306
+ for pattern_type, output_file in PATTERN_SOURCES.items():
307
+ source_dir = patterns_dir / pattern_type
308
+ patterns = load_patterns_from_directory(source_dir, pattern_type)
309
+
310
+ if not patterns:
311
+ if verbose:
312
+ print(f"No {pattern_type} patterns found")
313
+ results["skipped"].append(pattern_type)
314
+ continue
315
+
316
+ results["total_patterns"] += len(patterns)
317
+
318
+ # Format patterns
319
+ formatter = formatters.get(pattern_type, format_coding_patterns_markdown)
320
+ markdown_content = formatter(patterns)
321
+
322
+ # Write output
323
+ output_path = output_dir / output_file
324
+
325
+ if dry_run:
326
+ print(f"Would write {len(patterns)} patterns to {output_path}")
327
+ if verbose:
328
+ print(f"--- {output_file} ---")
329
+ print(
330
+ (
331
+ markdown_content[:500] + "..."
332
+ if len(markdown_content) > 500
333
+ else markdown_content
334
+ ),
335
+ )
336
+ print()
337
+ else:
338
+ try:
339
+ with open(output_path, "w") as f:
340
+ f.write(markdown_content)
341
+ results["synced"].append(
342
+ {
343
+ "type": pattern_type,
344
+ "file": str(output_path),
345
+ "patterns": len(patterns),
346
+ },
347
+ )
348
+ if verbose:
349
+ print(f"Synced {len(patterns)} {pattern_type} patterns to {output_path}")
350
+ except OSError as e:
351
+ results["errors"].append(f"{pattern_type}: {e}")
352
+ if verbose:
353
+ print(f"Error writing {output_path}: {e}", file=sys.stderr)
354
+
355
+ return results
356
+
357
+
358
+ def watch_and_sync(project_root: Path, interval: int = 30, verbose: bool = False):
359
+ """Watch patterns directory and sync on changes.
360
+
361
+ Args:
362
+ project_root: Project root directory
363
+ interval: Check interval in seconds
364
+ verbose: Verbose output
365
+
366
+ """
367
+ print(f"Watching for pattern changes (every {interval}s)...")
368
+ print("Press Ctrl+C to stop")
369
+
370
+ patterns_dir = project_root / "patterns"
371
+ last_mtime = 0.0
372
+
373
+ try:
374
+ while True:
375
+ # Check for changes
376
+ current_mtime = 0.0
377
+ if patterns_dir.exists():
378
+ for json_file in patterns_dir.rglob("*.json"):
379
+ file_mtime = json_file.stat().st_mtime
380
+ current_mtime = max(current_mtime, file_mtime)
381
+
382
+ if current_mtime > last_mtime:
383
+ if last_mtime > 0:
384
+ print(f"\n[{datetime.now().strftime('%H:%M:%S')}] Changes detected, syncing...")
385
+ results = sync_patterns(project_root, verbose=verbose)
386
+ print(f"Synced {results['total_patterns']} patterns")
387
+ else:
388
+ # Initial sync
389
+ results = sync_patterns(project_root, verbose=verbose)
390
+ print(f"Initial sync: {results['total_patterns']} patterns")
391
+ last_mtime = current_mtime
392
+
393
+ time.sleep(interval)
394
+
395
+ except KeyboardInterrupt:
396
+ print("\nStopped watching")
397
+
398
+
399
+ def main():
400
+ """Main CLI entry point."""
401
+ parser = argparse.ArgumentParser(
402
+ prog="empathy sync-claude",
403
+ description="Sync Empathy patterns to .claude/rules/empathy/",
404
+ formatter_class=argparse.RawDescriptionHelpFormatter,
405
+ epilog="""
406
+ Examples:
407
+ empathy sync-claude # Sync patterns once
408
+ empathy sync-claude --watch # Watch and auto-sync
409
+ empathy sync-claude --dry-run # Preview without writing
410
+ empathy sync-claude --verbose # Show detailed output
411
+
412
+ Output structure:
413
+ .claude/rules/empathy/
414
+ ├── bug-patterns.md # From patterns/debugging/
415
+ ├── security-decisions.md # From patterns/security/
416
+ ├── tech-debt-hotspots.md # From patterns/tech_debt/
417
+ └── coding-patterns.md # From patterns/inspection/
418
+ """,
419
+ )
420
+
421
+ parser.add_argument(
422
+ "--project-root",
423
+ "-p",
424
+ type=Path,
425
+ default=Path.cwd(),
426
+ help="Project root directory (default: current directory)",
427
+ )
428
+ parser.add_argument(
429
+ "--watch",
430
+ "-w",
431
+ action="store_true",
432
+ help="Watch for changes and auto-sync",
433
+ )
434
+ parser.add_argument(
435
+ "--interval",
436
+ "-i",
437
+ type=int,
438
+ default=30,
439
+ help="Watch interval in seconds (default: 30)",
440
+ )
441
+ parser.add_argument(
442
+ "--dry-run",
443
+ "-n",
444
+ action="store_true",
445
+ help="Show what would be synced without writing files",
446
+ )
447
+ parser.add_argument(
448
+ "--verbose",
449
+ "-v",
450
+ action="store_true",
451
+ help="Verbose output",
452
+ )
453
+
454
+ args = parser.parse_args()
455
+
456
+ project_root = args.project_root.resolve()
457
+
458
+ if args.verbose:
459
+ print(f"Project root: {project_root}")
460
+ print(f"Patterns dir: {project_root / 'patterns'}")
461
+ print(f"Output dir: {project_root / CLAUDE_RULES_DIR}")
462
+ print()
463
+
464
+ if args.watch:
465
+ watch_and_sync(project_root, args.interval, args.verbose)
466
+ else:
467
+ results = sync_patterns(project_root, args.dry_run, args.verbose)
468
+
469
+ if args.dry_run:
470
+ print(f"\nDry run complete: {results['total_patterns']} patterns would be synced")
471
+ else:
472
+ if results["synced"]:
473
+ print(f"\n✓ Synced {results['total_patterns']} patterns to {CLAUDE_RULES_DIR}/")
474
+ for item in results["synced"]:
475
+ print(f" - {item['type']}: {item['patterns']} patterns")
476
+ elif results["skipped"]:
477
+ print("No patterns to sync")
478
+
479
+ if results["errors"]:
480
+ print("\nErrors:", file=sys.stderr)
481
+ for error in results["errors"]:
482
+ print(f" - {error}", file=sys.stderr)
483
+ sys.exit(1)
484
+
485
+
486
+ if __name__ == "__main__":
487
+ main()