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,120 @@
1
+ """CLI tools for the Empathy Software Plugin.
2
+
3
+ This package exists alongside a legacy ``cli.py`` module at the
4
+ package root. To maintain backwards compatibility with existing
5
+ callers and tests, we dynamically import the root ``cli.py`` and
6
+ re-export its public API from here.
7
+
8
+ Tests also expect a couple of small helper functions to exist at the
9
+ package level:
10
+
11
+ * ``get_logger()`` – returns the configured logger instance
12
+ * ``get_global_registry()`` – indirection around the plugin registry
13
+
14
+ These helpers make the CLI easier to patch in tests while keeping the
15
+ core implementation in the shared registry module.
16
+ """
17
+
18
+ import importlib.util
19
+ import os
20
+ from typing import Any
21
+
22
+ from .inspect import main as inspect_main
23
+
24
+ # Re-export from parent cli.py module for backwards compatibility
25
+ # This handles the cli/ package shadowing the cli.py file
26
+ _parent_dir = os.path.dirname(os.path.dirname(__file__))
27
+ _cli_module_path = os.path.join(_parent_dir, "cli.py")
28
+
29
+ logger = None # Will be populated if cli.py is found
30
+ Colors = None # type: ignore[assignment]
31
+ analyze_project = None # type: ignore[assignment]
32
+ display_wizard_results = None # type: ignore[assignment]
33
+ gather_project_context = None # type: ignore[assignment]
34
+ list_wizards = None # type: ignore[assignment]
35
+ main = None # type: ignore[assignment]
36
+ scan_command = None # type: ignore[assignment]
37
+ wizard_info = None # type: ignore[assignment]
38
+ print_header = None # type: ignore[assignment]
39
+ print_alert = None # type: ignore[assignment]
40
+ print_success = None # type: ignore[assignment]
41
+ print_error = None # type: ignore[assignment]
42
+ print_info = None # type: ignore[assignment]
43
+ print_summary = None # type: ignore[assignment]
44
+ parse_ai_calls = None # type: ignore[assignment]
45
+ parse_git_history = None # type: ignore[assignment]
46
+ prepare_wizard_context = None # type: ignore[assignment]
47
+
48
+
49
+ if os.path.exists(_cli_module_path):
50
+ _spec = importlib.util.spec_from_file_location("_cli_module", _cli_module_path)
51
+ if _spec is not None and _spec.loader is not None:
52
+ _cli_module = importlib.util.module_from_spec(_spec)
53
+ _spec.loader.exec_module(_cli_module)
54
+
55
+ # Re-export all items from cli.py
56
+ logger = _cli_module.logger
57
+ Colors = _cli_module.Colors
58
+ analyze_project = _cli_module.analyze_project
59
+ display_wizard_results = _cli_module.display_wizard_results
60
+ gather_project_context = _cli_module.gather_project_context
61
+ list_wizards = _cli_module.list_wizards
62
+ main = _cli_module.main
63
+ scan_command = _cli_module.scan_command
64
+ wizard_info = _cli_module.wizard_info
65
+ print_header = _cli_module.print_header
66
+ print_alert = _cli_module.print_alert
67
+ print_success = _cli_module.print_success
68
+ print_error = _cli_module.print_error
69
+ print_info = _cli_module.print_info
70
+ print_summary = _cli_module.print_summary
71
+ parse_ai_calls = _cli_module.parse_ai_calls
72
+ parse_git_history = _cli_module.parse_git_history
73
+ prepare_wizard_context = _cli_module.prepare_wizard_context
74
+
75
+
76
+ def get_logger():
77
+ """Return the CLI logger instance.
78
+
79
+ This thin wrapper exists so tests can patch the logger via
80
+ ``empathy_software_plugin.cli.get_logger`` without reaching into
81
+ the underlying implementation module.
82
+ """
83
+ return logger
84
+
85
+
86
+ def get_global_registry() -> Any:
87
+ """Return the global plugin registry used by the software plugin.
88
+
89
+ The concrete implementation lives in the core plugin registry
90
+ module. We import lazily to avoid import cycles and to keep this
91
+ function easy to patch in tests via ``unittest.mock.patch``.
92
+ """
93
+ from attune.plugins.registry import get_global_registry as _get_global_registry
94
+
95
+ return _get_global_registry()
96
+
97
+
98
+ __all__ = [
99
+ "Colors",
100
+ "analyze_project",
101
+ "display_wizard_results",
102
+ "gather_project_context",
103
+ "get_global_registry",
104
+ "get_logger",
105
+ "inspect_main",
106
+ "list_wizards",
107
+ "logger",
108
+ "main",
109
+ "parse_ai_calls",
110
+ "parse_git_history",
111
+ "prepare_wizard_context",
112
+ "print_alert",
113
+ "print_error",
114
+ "print_header",
115
+ "print_info",
116
+ "print_success",
117
+ "print_summary",
118
+ "scan_command",
119
+ "wizard_info",
120
+ ]
@@ -0,0 +1,362 @@
1
+ """Code Inspection CLI
2
+
3
+ Command-line interface for the Code Inspection Agent Pipeline.
4
+
5
+ Usage:
6
+ empathy-inspect [path] [options]
7
+
8
+ Examples:
9
+ empathy-inspect . # Inspect current directory
10
+ empathy-inspect ./src --parallel # Parallel mode
11
+ empathy-inspect . --format json # JSON output
12
+ empathy-inspect . --staged # Only staged changes
13
+ empathy-inspect . --fix # Auto-fix safe issues
14
+
15
+ Copyright 2025 Smart AI Memory, LLC
16
+ Licensed under Fair Source 0.9
17
+
18
+ """
19
+
20
+ import argparse
21
+ import asyncio
22
+ import sys
23
+ from pathlib import Path
24
+
25
+
26
+ async def run_auto_fix(project_path: str, verbose: bool = False) -> int:
27
+ """Run auto-fix using ruff.
28
+
29
+ Args:
30
+ project_path: Path to project to fix
31
+ verbose: Whether to show verbose output
32
+
33
+ Returns:
34
+ Number of issues fixed
35
+
36
+ """
37
+ import subprocess
38
+
39
+ fixed_count = 0
40
+
41
+ # Run ruff check with --fix
42
+ try:
43
+ print("\nRunning ruff --fix...")
44
+ result = subprocess.run(
45
+ ["ruff", "check", project_path, "--fix", "--exit-zero"],
46
+ check=False,
47
+ capture_output=True,
48
+ text=True,
49
+ )
50
+
51
+ if verbose and result.stdout:
52
+ print(result.stdout)
53
+
54
+ # Count fixes from output
55
+ if "Fixed" in result.stdout:
56
+ # Parse "Fixed X errors" or similar
57
+ import re
58
+
59
+ match = re.search(r"Fixed (\d+)", result.stdout)
60
+ if match:
61
+ fixed_count += int(match.group(1))
62
+
63
+ except FileNotFoundError:
64
+ print("Warning: ruff not found. Install with: pip install ruff")
65
+ except Exception as e:
66
+ print(f"Warning: ruff fix failed: {e}")
67
+
68
+ # Run ruff format for formatting fixes
69
+ try:
70
+ print("Running ruff format...")
71
+ result = subprocess.run(
72
+ ["ruff", "format", project_path],
73
+ check=False,
74
+ capture_output=True,
75
+ text=True,
76
+ )
77
+
78
+ if verbose and result.stdout:
79
+ print(result.stdout)
80
+
81
+ # Count formatted files
82
+ if "file" in result.stderr.lower():
83
+ import re
84
+
85
+ match = re.search(r"(\d+) file", result.stderr)
86
+ if match:
87
+ fixed_count += int(match.group(1))
88
+
89
+ except FileNotFoundError:
90
+ pass # Already warned above
91
+ except Exception as e:
92
+ if verbose:
93
+ print(f"Warning: ruff format failed: {e}")
94
+
95
+ # Run isort for import sorting
96
+ try:
97
+ print("Running isort...")
98
+ result = subprocess.run(
99
+ ["isort", project_path, "--profile", "black"],
100
+ check=False,
101
+ capture_output=True,
102
+ text=True,
103
+ )
104
+
105
+ if verbose and result.stdout:
106
+ print(result.stdout)
107
+
108
+ # isort shows "Fixing" for each file
109
+ if "Fixing" in result.stdout:
110
+ fixed_count += result.stdout.count("Fixing")
111
+
112
+ except FileNotFoundError:
113
+ if verbose:
114
+ print("Note: isort not found. Install with: pip install isort")
115
+ except Exception as e:
116
+ if verbose:
117
+ print(f"Warning: isort failed: {e}")
118
+
119
+ return fixed_count
120
+
121
+
122
+ def parse_args() -> argparse.Namespace:
123
+ """Parse command-line arguments."""
124
+ parser = argparse.ArgumentParser(
125
+ prog="empathy-inspect",
126
+ description="Code Inspection Agent Pipeline",
127
+ formatter_class=argparse.RawDescriptionHelpFormatter,
128
+ epilog="""
129
+ Examples:
130
+ empathy-inspect . Inspect current directory
131
+ empathy-inspect ./src --parallel Run static checks in parallel
132
+ empathy-inspect . --format json Output as JSON
133
+ empathy-inspect . --staged Inspect staged git changes only
134
+ empathy-inspect . --quick Quick mode (skip slow checks)
135
+ """,
136
+ )
137
+
138
+ parser.add_argument(
139
+ "path",
140
+ nargs="?",
141
+ default=".",
142
+ help="Path to inspect (default: current directory)",
143
+ )
144
+
145
+ parser.add_argument(
146
+ "--parallel",
147
+ action="store_true",
148
+ default=True,
149
+ help="Run Phase 1 tools in parallel (default: True)",
150
+ )
151
+
152
+ parser.add_argument(
153
+ "--no-parallel",
154
+ action="store_true",
155
+ help="Disable parallel execution",
156
+ )
157
+
158
+ parser.add_argument(
159
+ "--learning",
160
+ action="store_true",
161
+ default=True,
162
+ help="Enable pattern learning (default: True)",
163
+ )
164
+
165
+ parser.add_argument(
166
+ "--no-learning",
167
+ action="store_true",
168
+ help="Disable pattern learning",
169
+ )
170
+
171
+ parser.add_argument(
172
+ "--format",
173
+ "-f",
174
+ choices=["terminal", "json", "markdown", "sarif", "html"],
175
+ default="terminal",
176
+ help="Output format (default: terminal). Use 'sarif' for GitHub Actions.",
177
+ )
178
+
179
+ parser.add_argument(
180
+ "--staged",
181
+ action="store_true",
182
+ help="Only inspect staged git changes",
183
+ )
184
+
185
+ parser.add_argument(
186
+ "--changed",
187
+ action="store_true",
188
+ help="Only inspect changed files (vs HEAD)",
189
+ )
190
+
191
+ parser.add_argument(
192
+ "--quick",
193
+ "-q",
194
+ action="store_true",
195
+ help="Quick mode (skip slow checks like deep debugging)",
196
+ )
197
+
198
+ parser.add_argument(
199
+ "--fix",
200
+ action="store_true",
201
+ help="Auto-fix safe issues (formatting, imports)",
202
+ )
203
+
204
+ parser.add_argument(
205
+ "--verbose",
206
+ "-v",
207
+ action="store_true",
208
+ help="Verbose output",
209
+ )
210
+
211
+ parser.add_argument(
212
+ "--output",
213
+ "-o",
214
+ type=str,
215
+ help="Write report to file",
216
+ )
217
+
218
+ parser.add_argument(
219
+ "--exclude",
220
+ "-e",
221
+ type=str,
222
+ action="append",
223
+ default=[],
224
+ help="Glob patterns to exclude (can be used multiple times)",
225
+ )
226
+
227
+ # Baseline/suppression options
228
+ parser.add_argument(
229
+ "--no-baseline",
230
+ action="store_true",
231
+ help="Disable baseline filtering (show all findings)",
232
+ )
233
+
234
+ parser.add_argument(
235
+ "--baseline-init",
236
+ action="store_true",
237
+ help="Create an empty .empathy-baseline.json file",
238
+ )
239
+
240
+ parser.add_argument(
241
+ "--baseline-cleanup",
242
+ action="store_true",
243
+ help="Remove expired suppressions from baseline",
244
+ )
245
+
246
+ return parser.parse_args()
247
+
248
+
249
+ async def run_inspection(args: argparse.Namespace) -> int:
250
+ """Run the inspection and return exit code."""
251
+ # Import here to avoid slow startup
252
+ from agents.code_inspection import CodeInspectionAgent
253
+
254
+ # Resolve path
255
+ project_path = str(Path(args.path).resolve())
256
+
257
+ # Determine target mode
258
+ if args.staged:
259
+ target_mode = "staged"
260
+ elif args.changed:
261
+ target_mode = "changed"
262
+ else:
263
+ target_mode = "all"
264
+
265
+ # Create agent
266
+ agent = CodeInspectionAgent(
267
+ parallel_mode=args.parallel and not args.no_parallel,
268
+ learning_enabled=args.learning and not args.no_learning,
269
+ baseline_enabled=not args.no_baseline,
270
+ )
271
+
272
+ # Configure verbose logging
273
+ if args.verbose:
274
+ import logging
275
+
276
+ logging.basicConfig(level=logging.DEBUG)
277
+
278
+ # Run inspection
279
+ state = await agent.inspect(
280
+ project_path=project_path,
281
+ target_mode=target_mode,
282
+ exclude_patterns=args.exclude if args.exclude else None,
283
+ )
284
+
285
+ # Format report
286
+ report = agent.format_report(state, args.format)
287
+
288
+ # Output
289
+ if args.output:
290
+ output_path = Path(args.output)
291
+ output_path.write_text(report)
292
+ print(f"Report written to {output_path}")
293
+ else:
294
+ print(report)
295
+
296
+ # Auto-fix if requested
297
+ if args.fix:
298
+ fixed_count = await run_auto_fix(project_path, args.verbose)
299
+ if fixed_count > 0:
300
+ print(f"\nAuto-fixed {fixed_count} issues. Run inspection again to verify.")
301
+
302
+ # Return exit code based on health status
303
+ if state["health_status"] == "fail":
304
+ return 1
305
+ if state["health_status"] == "warn":
306
+ return 0 # Warn but don't fail
307
+ return 0
308
+
309
+
310
+ def handle_baseline_commands(args: argparse.Namespace) -> bool:
311
+ """Handle baseline-specific commands.
312
+
313
+ Returns:
314
+ True if a baseline command was handled (and should exit)
315
+
316
+ """
317
+ from agents.code_inspection.baseline import BaselineManager, create_baseline_file
318
+
319
+ project_path = str(Path(args.path).resolve())
320
+
321
+ if args.baseline_init:
322
+ baseline_path = create_baseline_file(project_path)
323
+ print(f"Created baseline file: {baseline_path}")
324
+ return True
325
+
326
+ if args.baseline_cleanup:
327
+ manager = BaselineManager(project_path)
328
+ if manager.load():
329
+ removed = manager.cleanup_expired()
330
+ print(f"Removed {removed} expired suppressions")
331
+ else:
332
+ print("No baseline file found")
333
+ return True
334
+
335
+ return False
336
+
337
+
338
+ def main():
339
+ """Main entry point for CLI."""
340
+ args = parse_args()
341
+
342
+ try:
343
+ # Handle baseline commands first
344
+ if handle_baseline_commands(args):
345
+ sys.exit(0)
346
+
347
+ exit_code = asyncio.run(run_inspection(args))
348
+ sys.exit(exit_code)
349
+ except KeyboardInterrupt:
350
+ print("\nInspection cancelled.")
351
+ sys.exit(130)
352
+ except Exception as e:
353
+ print(f"Error: {e}", file=sys.stderr)
354
+ if args.verbose:
355
+ import traceback
356
+
357
+ traceback.print_exc()
358
+ sys.exit(1)
359
+
360
+
361
+ if __name__ == "__main__":
362
+ main()