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,504 @@
1
+ """Project Index Data Models
2
+
3
+ Defines the structure of file metadata and project summaries.
4
+
5
+ Copyright 2025 Smart AI Memory, LLC
6
+ Licensed under Fair Source 0.9
7
+ """
8
+
9
+ from dataclasses import dataclass, field
10
+ from datetime import datetime
11
+ from enum import Enum
12
+ from typing import Any
13
+
14
+
15
+ class FileCategory(str, Enum):
16
+ """Categories of files in a project."""
17
+
18
+ SOURCE = "source" # Production code
19
+ TEST = "test" # Test files
20
+ CONFIG = "config" # Configuration files
21
+ DOCS = "docs" # Documentation
22
+ ASSET = "asset" # Static assets
23
+ GENERATED = "generated" # Auto-generated files
24
+ BUILD = "build" # Build artifacts
25
+ UNKNOWN = "unknown"
26
+
27
+
28
+ class TestRequirement(str, Enum):
29
+ """Whether a file requires tests."""
30
+
31
+ REQUIRED = "required" # Should have tests
32
+ OPTIONAL = "optional" # Tests nice to have
33
+ NOT_APPLICABLE = "not_applicable" # Doesn't need tests
34
+ EXCLUDED = "excluded" # Explicitly excluded
35
+
36
+
37
+ @dataclass
38
+ class FileRecord:
39
+ """Metadata record for a single file in the project.
40
+
41
+ This is the core data structure that workflows and agents
42
+ can read and write to track file state.
43
+ """
44
+
45
+ # Identity
46
+ path: str # Relative path from project root
47
+ name: str # File name
48
+ category: FileCategory = FileCategory.UNKNOWN
49
+ language: str = "" # python, typescript, etc.
50
+
51
+ # Testing metadata
52
+ test_requirement: TestRequirement = TestRequirement.REQUIRED
53
+ test_file_path: str | None = None
54
+ tests_exist: bool = False
55
+ test_count: int = 0
56
+ coverage_percent: float = 0.0
57
+
58
+ # Timestamps
59
+ last_modified: datetime | None = None
60
+ tests_last_modified: datetime | None = None
61
+ last_indexed: datetime | None = None
62
+
63
+ # Staleness (days since source changed but tests didn't)
64
+ staleness_days: int = 0
65
+ is_stale: bool = False
66
+
67
+ # Code metrics
68
+ lines_of_code: int = 0
69
+ lines_of_test: int = 0
70
+ complexity_score: float = 0.0
71
+
72
+ # Quality indicators
73
+ has_docstrings: bool = False
74
+ has_type_hints: bool = False
75
+ lint_issues: int = 0
76
+
77
+ # Dependencies
78
+ imports: list[str] = field(default_factory=list)
79
+ imported_by: list[str] = field(default_factory=list)
80
+ import_count: int = 0
81
+ imported_by_count: int = 0
82
+
83
+ # Impact scoring (higher = more critical)
84
+ impact_score: float = 0.0
85
+
86
+ # Custom metadata (for workflow-specific data)
87
+ metadata: dict[str, Any] = field(default_factory=dict)
88
+
89
+ # Tracking
90
+ needs_attention: bool = False
91
+ attention_reasons: list[str] = field(default_factory=list)
92
+
93
+ def to_dict(self) -> dict[str, Any]:
94
+ """Convert to dictionary for JSON serialization."""
95
+ return {
96
+ "path": self.path,
97
+ "name": self.name,
98
+ "category": self.category.value,
99
+ "language": self.language,
100
+ "test_requirement": self.test_requirement.value,
101
+ "test_file_path": self.test_file_path,
102
+ "tests_exist": self.tests_exist,
103
+ "test_count": self.test_count,
104
+ "coverage_percent": self.coverage_percent,
105
+ "last_modified": self.last_modified.isoformat() if self.last_modified else None,
106
+ "tests_last_modified": (
107
+ self.tests_last_modified.isoformat() if self.tests_last_modified else None
108
+ ),
109
+ "last_indexed": self.last_indexed.isoformat() if self.last_indexed else None,
110
+ "staleness_days": self.staleness_days,
111
+ "is_stale": self.is_stale,
112
+ "lines_of_code": self.lines_of_code,
113
+ "lines_of_test": self.lines_of_test,
114
+ "complexity_score": self.complexity_score,
115
+ "has_docstrings": self.has_docstrings,
116
+ "has_type_hints": self.has_type_hints,
117
+ "lint_issues": self.lint_issues,
118
+ "imports": self.imports,
119
+ "imported_by": self.imported_by,
120
+ "import_count": self.import_count,
121
+ "imported_by_count": self.imported_by_count,
122
+ "impact_score": self.impact_score,
123
+ "metadata": self.metadata,
124
+ "needs_attention": self.needs_attention,
125
+ "attention_reasons": self.attention_reasons,
126
+ }
127
+
128
+ @classmethod
129
+ def from_dict(cls, data: dict[str, Any]) -> "FileRecord":
130
+ """Create from dictionary."""
131
+ return cls(
132
+ path=data.get("path", ""),
133
+ name=data.get("name", ""),
134
+ category=FileCategory(data.get("category", "unknown")),
135
+ language=data.get("language", ""),
136
+ test_requirement=TestRequirement(data.get("test_requirement", "required")),
137
+ test_file_path=data.get("test_file_path"),
138
+ tests_exist=data.get("tests_exist", False),
139
+ test_count=data.get("test_count", 0),
140
+ coverage_percent=data.get("coverage_percent", 0.0),
141
+ last_modified=(
142
+ datetime.fromisoformat(data["last_modified"]) if data.get("last_modified") else None
143
+ ),
144
+ tests_last_modified=(
145
+ datetime.fromisoformat(data["tests_last_modified"])
146
+ if data.get("tests_last_modified")
147
+ else None
148
+ ),
149
+ last_indexed=(
150
+ datetime.fromisoformat(data["last_indexed"]) if data.get("last_indexed") else None
151
+ ),
152
+ staleness_days=data.get("staleness_days", 0),
153
+ is_stale=data.get("is_stale", False),
154
+ lines_of_code=data.get("lines_of_code", 0),
155
+ lines_of_test=data.get("lines_of_test", 0),
156
+ complexity_score=data.get("complexity_score", 0.0),
157
+ has_docstrings=data.get("has_docstrings", False),
158
+ has_type_hints=data.get("has_type_hints", False),
159
+ lint_issues=data.get("lint_issues", 0),
160
+ imports=data.get("imports", []),
161
+ imported_by=data.get("imported_by", []),
162
+ import_count=data.get("import_count", 0),
163
+ imported_by_count=data.get("imported_by_count", 0),
164
+ impact_score=data.get("impact_score", 0.0),
165
+ metadata=data.get("metadata", {}),
166
+ needs_attention=data.get("needs_attention", False),
167
+ attention_reasons=data.get("attention_reasons", []),
168
+ )
169
+
170
+
171
+ @dataclass
172
+ class ProjectSummary:
173
+ """High-level summary of project health.
174
+
175
+ Updated each time the index is regenerated.
176
+ """
177
+
178
+ # Counts
179
+ total_files: int = 0
180
+ source_files: int = 0
181
+ test_files: int = 0
182
+ config_files: int = 0
183
+ doc_files: int = 0
184
+
185
+ # Testing health
186
+ files_requiring_tests: int = 0
187
+ files_with_tests: int = 0
188
+ files_without_tests: int = 0
189
+ test_coverage_avg: float = 0.0
190
+ total_test_count: int = 0
191
+
192
+ # Staleness
193
+ stale_file_count: int = 0
194
+ avg_staleness_days: float = 0.0
195
+ most_stale_files: list[str] = field(default_factory=list)
196
+
197
+ # Code metrics
198
+ total_lines_of_code: int = 0
199
+ total_lines_of_test: int = 0
200
+ test_to_code_ratio: float = 0.0
201
+ avg_complexity: float = 0.0
202
+
203
+ # Quality
204
+ files_with_docstrings_pct: float = 0.0
205
+ files_with_type_hints_pct: float = 0.0
206
+ total_lint_issues: int = 0
207
+
208
+ # Impact analysis
209
+ high_impact_files: list[str] = field(default_factory=list)
210
+ critical_untested_files: list[str] = field(default_factory=list)
211
+
212
+ # Attention needed
213
+ files_needing_attention: int = 0
214
+ top_attention_files: list[str] = field(default_factory=list)
215
+
216
+ def to_dict(self) -> dict[str, Any]:
217
+ """Convert to dictionary."""
218
+ return {
219
+ "total_files": self.total_files,
220
+ "source_files": self.source_files,
221
+ "test_files": self.test_files,
222
+ "config_files": self.config_files,
223
+ "doc_files": self.doc_files,
224
+ "files_requiring_tests": self.files_requiring_tests,
225
+ "files_with_tests": self.files_with_tests,
226
+ "files_without_tests": self.files_without_tests,
227
+ "test_coverage_avg": self.test_coverage_avg,
228
+ "total_test_count": self.total_test_count,
229
+ "stale_file_count": self.stale_file_count,
230
+ "avg_staleness_days": self.avg_staleness_days,
231
+ "most_stale_files": self.most_stale_files,
232
+ "total_lines_of_code": self.total_lines_of_code,
233
+ "total_lines_of_test": self.total_lines_of_test,
234
+ "test_to_code_ratio": self.test_to_code_ratio,
235
+ "avg_complexity": self.avg_complexity,
236
+ "files_with_docstrings_pct": self.files_with_docstrings_pct,
237
+ "files_with_type_hints_pct": self.files_with_type_hints_pct,
238
+ "total_lint_issues": self.total_lint_issues,
239
+ "high_impact_files": self.high_impact_files,
240
+ "critical_untested_files": self.critical_untested_files,
241
+ "files_needing_attention": self.files_needing_attention,
242
+ "top_attention_files": self.top_attention_files,
243
+ }
244
+
245
+ @classmethod
246
+ def from_dict(cls, data: dict[str, Any]) -> "ProjectSummary":
247
+ """Create from dictionary."""
248
+ return cls(
249
+ total_files=data.get("total_files", 0),
250
+ source_files=data.get("source_files", 0),
251
+ test_files=data.get("test_files", 0),
252
+ config_files=data.get("config_files", 0),
253
+ doc_files=data.get("doc_files", 0),
254
+ files_requiring_tests=data.get("files_requiring_tests", 0),
255
+ files_with_tests=data.get("files_with_tests", 0),
256
+ files_without_tests=data.get("files_without_tests", 0),
257
+ test_coverage_avg=data.get("test_coverage_avg", 0.0),
258
+ total_test_count=data.get("total_test_count", 0),
259
+ stale_file_count=data.get("stale_file_count", 0),
260
+ avg_staleness_days=data.get("avg_staleness_days", 0.0),
261
+ most_stale_files=data.get("most_stale_files", []),
262
+ total_lines_of_code=data.get("total_lines_of_code", 0),
263
+ total_lines_of_test=data.get("total_lines_of_test", 0),
264
+ test_to_code_ratio=data.get("test_to_code_ratio", 0.0),
265
+ avg_complexity=data.get("avg_complexity", 0.0),
266
+ files_with_docstrings_pct=data.get("files_with_docstrings_pct", 0.0),
267
+ files_with_type_hints_pct=data.get("files_with_type_hints_pct", 0.0),
268
+ total_lint_issues=data.get("total_lint_issues", 0),
269
+ high_impact_files=data.get("high_impact_files", []),
270
+ critical_untested_files=data.get("critical_untested_files", []),
271
+ files_needing_attention=data.get("files_needing_attention", 0),
272
+ top_attention_files=data.get("top_attention_files", []),
273
+ )
274
+
275
+
276
+ @dataclass
277
+ class IndexConfig:
278
+ """Configuration for the project index.
279
+
280
+ Defines exclusion patterns, staleness thresholds, etc.
281
+ """
282
+
283
+ # File patterns to exclude from indexing
284
+ exclude_patterns: list[str] = field(
285
+ default_factory=lambda: [
286
+ # Python cache and bytecode
287
+ "**/__pycache__/**",
288
+ "**/*.pyc",
289
+ "**/*.pyo",
290
+ # Version control
291
+ "**/.git/**",
292
+ # Environment files (contain secrets)
293
+ "**/.env",
294
+ "**/.env.*",
295
+ "**/*.env",
296
+ # Virtual environments
297
+ "**/.venv/**",
298
+ "**/venv/**",
299
+ "**/env/**",
300
+ # Package managers
301
+ "**/node_modules/**",
302
+ # Build outputs
303
+ "**/dist/**",
304
+ "**/build/**",
305
+ "**/.next/**",
306
+ "**/site/**",
307
+ "**/*.egg-info/**",
308
+ "**/out/**",
309
+ # Test cache and coverage
310
+ "**/htmlcov/**",
311
+ "**/.pytest_cache/**",
312
+ "**/.mypy_cache/**",
313
+ "**/.ruff_cache/**",
314
+ "**/.coverage*",
315
+ "**/coverage.xml",
316
+ "**/coverage.json",
317
+ "**/.tox/**",
318
+ "**/.nox/**",
319
+ # Generated/binary files
320
+ "**/*.pack",
321
+ "**/dump.rdb",
322
+ # Logs
323
+ "**/logs/**",
324
+ "**/*.log",
325
+ "**/*.jsonl",
326
+ # OS files
327
+ "**/.DS_Store",
328
+ "**/Thumbs.db",
329
+ # IDE/Editor files
330
+ "**/.idea/**",
331
+ "**/.vscode/**",
332
+ "**/*.swp",
333
+ "**/*.swo",
334
+ # External/archived directories (project-specific)
335
+ "**/website/**",
336
+ "**/ebook-site/**",
337
+ "**/anthropic-cookbook/**",
338
+ "**/salvaged/**",
339
+ "**/10_9_2025_ai_nurse_florence/**",
340
+ "**/book-indesign/**",
341
+ "**/examples/**",
342
+ # Binary/asset files
343
+ "**/*.pdf",
344
+ "**/*.jpeg",
345
+ "**/*.jpg",
346
+ "**/*.png",
347
+ "**/*.gif",
348
+ "**/*.ico",
349
+ "**/*.svg",
350
+ "**/*.woff",
351
+ "**/*.woff2",
352
+ "**/*.ttf",
353
+ "**/*.eot",
354
+ "**/*.mp3",
355
+ "**/*.mp4",
356
+ "**/*.wav",
357
+ "**/*.zip",
358
+ "**/*.tar",
359
+ "**/*.gz",
360
+ # Adobe/Design files
361
+ "**/*.indd",
362
+ "**/*.psd",
363
+ "**/*.ai",
364
+ "**/*.sketch",
365
+ "**/*.figma",
366
+ # Lock files
367
+ "**/package-lock.json",
368
+ "**/yarn.lock",
369
+ "**/poetry.lock",
370
+ "**/Pipfile.lock",
371
+ # Archive directories
372
+ "**/archived_workflows/**",
373
+ ],
374
+ )
375
+
376
+ # Patterns for files that don't require tests
377
+ no_test_patterns: list[str] = field(
378
+ default_factory=lambda: [
379
+ # Python special files
380
+ "**/__init__.py",
381
+ "**/__main__.py",
382
+ "**/conftest.py",
383
+ "**/setup.py",
384
+ "**/setup.cfg",
385
+ # Configuration files
386
+ "**/*.yml",
387
+ "**/*.yaml",
388
+ "**/*.json",
389
+ "**/*.toml",
390
+ "**/*.ini",
391
+ "**/*.cfg",
392
+ "**/*.conf",
393
+ # Documentation
394
+ "**/*.md",
395
+ "**/*.txt",
396
+ "**/*.rst",
397
+ # Frontend assets
398
+ "**/*.css",
399
+ "**/*.scss",
400
+ "**/*.less",
401
+ "**/*.html",
402
+ "**/*.jinja",
403
+ "**/*.jinja2",
404
+ # Database and migrations
405
+ "**/migrations/**",
406
+ "**/alembic/**",
407
+ # Static and templates
408
+ "**/static/**",
409
+ "**/templates/**",
410
+ "**/fixtures/**",
411
+ # Scripts and utilities (typically standalone)
412
+ "**/scripts/**",
413
+ "**/bin/**",
414
+ "**/tools/**",
415
+ "**/*_script.py",
416
+ "**/*_example.py",
417
+ "**/profile_*.py",
418
+ "**/benchmark_*.py",
419
+ # CLI entry points
420
+ "**/*_cli.py",
421
+ "**/cli.py",
422
+ # Type stubs
423
+ "**/*.pyi",
424
+ # Jupyter notebooks
425
+ "**/*.ipynb",
426
+ # Test files themselves don't need tests
427
+ "**/test_*.py",
428
+ "**/tests/**",
429
+ "**/*_test.py",
430
+ # Example and demo files
431
+ "**/*_example.py",
432
+ "**/*_demo.py",
433
+ "**/example_*.py",
434
+ "**/demo_*.py",
435
+ # Prompt templates
436
+ "**/prompts/**",
437
+ # Vscode extension (separate project)
438
+ "**/vscode-extension/**",
439
+ ],
440
+ )
441
+
442
+ # Staleness threshold in days
443
+ staleness_threshold_days: int = 7
444
+
445
+ # Coverage threshold for "needs attention"
446
+ low_coverage_threshold: float = 50.0
447
+
448
+ # Impact score threshold for "high impact"
449
+ high_impact_threshold: float = 5.0
450
+
451
+ # Source directories to scan
452
+ source_dirs: list[str] = field(
453
+ default_factory=lambda: [
454
+ "src",
455
+ "empathy_llm_toolkit",
456
+ "empathy_software_plugin",
457
+ "empathy_healthcare_plugin",
458
+ ],
459
+ )
460
+
461
+ # Test directory
462
+ test_dir: str = "tests"
463
+
464
+ # Redis settings
465
+ use_redis: bool = False
466
+ redis_key_prefix: str = "empathy:project_index"
467
+
468
+ def to_dict(self) -> dict[str, Any]:
469
+ """Convert to dictionary."""
470
+ return {
471
+ "exclude_patterns": self.exclude_patterns,
472
+ "no_test_patterns": self.no_test_patterns,
473
+ "staleness_threshold_days": self.staleness_threshold_days,
474
+ "low_coverage_threshold": self.low_coverage_threshold,
475
+ "high_impact_threshold": self.high_impact_threshold,
476
+ "source_dirs": self.source_dirs,
477
+ "test_dir": self.test_dir,
478
+ "use_redis": self.use_redis,
479
+ "redis_key_prefix": self.redis_key_prefix,
480
+ }
481
+
482
+ @classmethod
483
+ def from_dict(cls, data: dict[str, Any]) -> "IndexConfig":
484
+ """Create from dictionary."""
485
+ config = cls()
486
+ if "exclude_patterns" in data:
487
+ config.exclude_patterns = data["exclude_patterns"]
488
+ if "no_test_patterns" in data:
489
+ config.no_test_patterns = data["no_test_patterns"]
490
+ if "staleness_threshold_days" in data:
491
+ config.staleness_threshold_days = data["staleness_threshold_days"]
492
+ if "low_coverage_threshold" in data:
493
+ config.low_coverage_threshold = data["low_coverage_threshold"]
494
+ if "high_impact_threshold" in data:
495
+ config.high_impact_threshold = data["high_impact_threshold"]
496
+ if "source_dirs" in data:
497
+ config.source_dirs = data["source_dirs"]
498
+ if "test_dir" in data:
499
+ config.test_dir = data["test_dir"]
500
+ if "use_redis" in data:
501
+ config.use_redis = data["use_redis"]
502
+ if "redis_key_prefix" in data:
503
+ config.redis_key_prefix = data["redis_key_prefix"]
504
+ return config