devsquad 4.3.0__tar.gz → 4.3.1__tar.gz

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 (448) hide show
  1. {devsquad-4.3.0 → devsquad-4.3.1}/PKG-INFO +2 -2
  2. {devsquad-4.3.0 → devsquad-4.3.1}/README.md +1 -1
  3. {devsquad-4.3.0 → devsquad-4.3.1}/devsquad.egg-info/PKG-INFO +2 -2
  4. {devsquad-4.3.0 → devsquad-4.3.1}/devsquad.egg-info/SOURCES.txt +1 -0
  5. {devsquad-4.3.0 → devsquad-4.3.1}/pyproject.toml +1 -1
  6. devsquad-4.3.1/scripts/collaboration/_version.py +1 -0
  7. devsquad-4.3.1/scripts/collaboration/benchmark_regression_checker.py +378 -0
  8. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/output_validator.py +93 -1
  9. {devsquad-4.3.0 → devsquad-4.3.1}/skills/__init__.py +1 -1
  10. devsquad-4.3.0/scripts/collaboration/_version.py +0 -1
  11. {devsquad-4.3.0 → devsquad-4.3.1}/LICENSE +0 -0
  12. {devsquad-4.3.0 → devsquad-4.3.1}/devsquad.egg-info/dependency_links.txt +0 -0
  13. {devsquad-4.3.0 → devsquad-4.3.1}/devsquad.egg-info/entry_points.txt +0 -0
  14. {devsquad-4.3.0 → devsquad-4.3.1}/devsquad.egg-info/requires.txt +0 -0
  15. {devsquad-4.3.0 → devsquad-4.3.1}/devsquad.egg-info/top_level.txt +0 -0
  16. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/__init__.py +0 -0
  17. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/api/__init__.py +0 -0
  18. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/api/models.py +0 -0
  19. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/api/rate_limit.py +0 -0
  20. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/api/routes/__init__.py +0 -0
  21. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/api/routes/dispatch.py +0 -0
  22. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/api/routes/lifecycle.py +0 -0
  23. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/api/routes/metrics.py +0 -0
  24. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/api/routes/metrics_gates.py +0 -0
  25. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/api/security.py +0 -0
  26. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/api_server.py +0 -0
  27. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/auth.py +0 -0
  28. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/benchmark_async_dispatch.py +0 -0
  29. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/benchmark_ponytail_smart.py +0 -0
  30. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/benchmark_real_llm.py +0 -0
  31. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/check_async_coverage.py +0 -0
  32. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/check_config_consistency.py +0 -0
  33. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/check_constructor_params.py +0 -0
  34. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/check_dependency_lock.py +0 -0
  35. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/check_dependency_sync.py +0 -0
  36. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/check_hidden_content.py +0 -0
  37. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/check_test_pyramid.py +0 -0
  38. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/check_test_quality.py +0 -0
  39. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/check_version_consistency.py +0 -0
  40. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/cli/__init__.py +0 -0
  41. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/cli/cli_visual.py +0 -0
  42. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/cli.py +0 -0
  43. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/cli_dispatch.py +0 -0
  44. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/cli_lifecycle.py +0 -0
  45. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/cli_utils.py +0 -0
  46. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/__init__.py +0 -0
  47. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/adaptive_role_selector.py +0 -0
  48. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/adversarial_verify.py +0 -0
  49. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/agent_briefing.py +0 -0
  50. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/ai_semantic_matcher.py +0 -0
  51. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/anchor_checker.py +0 -0
  52. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/anti_rationalization.py +0 -0
  53. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/async_adapter.py +0 -0
  54. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/async_coordinator.py +0 -0
  55. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/async_llm_backend.py +0 -0
  56. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/audit_logger.py +0 -0
  57. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/autonomous/__init__.py +0 -0
  58. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/autonomous/git_driver.py +0 -0
  59. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/autonomous/loop_controller.py +0 -0
  60. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/autonomous/notes_memory.py +0 -0
  61. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/autonomous/run_state.py +0 -0
  62. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/autonomous/sleep_guard.py +0 -0
  63. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/autonomous/smart_confirmation.py +0 -0
  64. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/batch_scheduler.py +0 -0
  65. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/cache_interface.py +0 -0
  66. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/ccr_store.py +0 -0
  67. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/checkpoint_manager.py +0 -0
  68. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/ci_feedback_adapter.py +0 -0
  69. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/cli_command_classifier.py +0 -0
  70. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/code_graph_query.py +0 -0
  71. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/code_graph_storage.py +0 -0
  72. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/code_knowledge_graph.py +0 -0
  73. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/code_map_generator.py +0 -0
  74. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/concern_pack_loader.py +0 -0
  75. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/confidence_score.py +0 -0
  76. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/config_manager.py +0 -0
  77. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/consensus.py +0 -0
  78. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/consensus_gate.py +0 -0
  79. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/constants.py +0 -0
  80. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/content_cache.py +0 -0
  81. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/content_crusher.py +0 -0
  82. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/context_compressor.py +0 -0
  83. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/coordinator.py +0 -0
  84. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dashboard_live_mode.py +0 -0
  85. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/debt_collector.py +0 -0
  86. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dependency_hallucination_checker.py +0 -0
  87. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/deployment_compliance_checker.py +0 -0
  88. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatch_audit.py +0 -0
  89. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatch_component_factory.py +0 -0
  90. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatch_hooks.py +0 -0
  91. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatch_lifecycle.py +0 -0
  92. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatch_models.py +0 -0
  93. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatch_performance.py +0 -0
  94. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatch_pre_steps.py +0 -0
  95. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatch_rbac.py +0 -0
  96. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatch_result_assembler.py +0 -0
  97. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatch_services.py +0 -0
  98. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatch_steps.py +0 -0
  99. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatch_steps_base.py +0 -0
  100. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatch_steps_consensus_mixin.py +0 -0
  101. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatch_steps_feedback_mixin.py +0 -0
  102. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatch_steps_mixins.py +0 -0
  103. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatch_steps_quality_mixin.py +0 -0
  104. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatch_steps_services_mixin.py +0 -0
  105. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatcher.py +0 -0
  106. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatcher_async_mixin.py +0 -0
  107. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatcher_audit_mixin.py +0 -0
  108. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatcher_base.py +0 -0
  109. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatcher_config.py +0 -0
  110. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatcher_error_mixin.py +0 -0
  111. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatcher_factory.py +0 -0
  112. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatcher_lifecycle_mixin.py +0 -0
  113. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatcher_mixins.py +0 -0
  114. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatcher_status_mixin.py +0 -0
  115. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dispatcher_utils_mixin.py +0 -0
  116. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/dual_layer_context.py +0 -0
  117. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/enhanced_worker.py +0 -0
  118. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/enterprise_feature.py +0 -0
  119. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/event_bus.py +0 -0
  120. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/execution_guard.py +0 -0
  121. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/feature_usage_tracker.py +0 -0
  122. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/feedback_control_loop.py +0 -0
  123. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/five_axis_consensus.py +0 -0
  124. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/input_validator.py +0 -0
  125. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/intent_workflow_mapper.py +0 -0
  126. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/judge_agent.py +0 -0
  127. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/language_parsers.py +0 -0
  128. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/learned_rule_store.py +0 -0
  129. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/lifecycle_gate.py +0 -0
  130. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/lifecycle_protocol.py +0 -0
  131. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/lifecycle_shortcut_adapter.py +0 -0
  132. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/lifecycle_shortcut_helpers.py +0 -0
  133. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/lifecycle_templates.py +0 -0
  134. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/llm_backend.py +0 -0
  135. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/llm_cache.py +0 -0
  136. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/llm_cache_async.py +0 -0
  137. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/llm_cache_base.py +0 -0
  138. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/llm_retry.py +0 -0
  139. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/llm_retry_async.py +0 -0
  140. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/llm_retry_base.py +0 -0
  141. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/loop_engineering/__init__.py +0 -0
  142. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/loop_engineering/discovery_probe.py +0 -0
  143. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/loop_engineering/handoff_adapter.py +0 -0
  144. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/loop_engineering/independent_evaluator.py +0 -0
  145. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/loop_engineering/kernel.py +0 -0
  146. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/loop_engineering/loop_scheduler.py +0 -0
  147. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/loop_engineering/models.py +0 -0
  148. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/loop_engineering/protocols.py +0 -0
  149. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/loop_engineering/rollback_strategy.py +0 -0
  150. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/loop_engineering/unified_memory.py +0 -0
  151. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/mce_adapter.py +0 -0
  152. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/memory_bridge.py +0 -0
  153. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/memory_claw_source.py +0 -0
  154. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/memory_forgetting.py +0 -0
  155. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/memory_index.py +0 -0
  156. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/memory_query.py +0 -0
  157. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/memory_serializer.py +0 -0
  158. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/memory_types.py +0 -0
  159. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/meta_skill_layering.py +0 -0
  160. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/micro_task_planner.py +0 -0
  161. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/models.py +0 -0
  162. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/models_base.py +0 -0
  163. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/models_dispatch.py +0 -0
  164. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/models_lifecycle.py +0 -0
  165. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/multi_host_adapter.py +0 -0
  166. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/multi_level_cache.py +0 -0
  167. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/multi_tenant.py +0 -0
  168. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/null_providers.py +0 -0
  169. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/operation_classifier.py +0 -0
  170. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/output_slicer.py +0 -0
  171. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/performance_fingerprint.py +0 -0
  172. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/performance_monitor.py +0 -0
  173. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/permission_guard.py +0 -0
  174. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/plugins/__init__.py +0 -0
  175. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/plugins/hot_loader.py +0 -0
  176. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/ponytail_rule_injector.py +0 -0
  177. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/prometheus_metrics.py +0 -0
  178. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/prompt_assembler.py +0 -0
  179. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/prompt_assembler_base.py +0 -0
  180. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/prompt_assembler_formatting_mixin.py +0 -0
  181. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/prompt_assembler_mixins.py +0 -0
  182. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/prompt_assembler_substitution_mixin.py +0 -0
  183. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/prompt_assembler_template_mixin.py +0 -0
  184. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/prompt_assembler_validation_mixin.py +0 -0
  185. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/prompt_dials.py +0 -0
  186. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/protocols.py +0 -0
  187. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/rbac_engine.py +0 -0
  188. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/redesign_auditor.py +0 -0
  189. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/redesign_checkers.py +0 -0
  190. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/redis_cache.py +0 -0
  191. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/report_formatter.py +0 -0
  192. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/requirement_tracer.py +0 -0
  193. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/retrospective.py +0 -0
  194. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/review_checkers.py +0 -0
  195. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/role_matcher.py +0 -0
  196. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/role_skill_loader.py +0 -0
  197. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/rule_collector.py +0 -0
  198. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/scratchpad.py +0 -0
  199. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/secret_patterns.py +0 -0
  200. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/severity_router.py +0 -0
  201. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/similar_task_recommender.py +0 -0
  202. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/skill_extractor.py +0 -0
  203. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/skill_registry.py +0 -0
  204. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/skill_storage.py +0 -0
  205. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/skillifier.py +0 -0
  206. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/standardized_role_template.py +0 -0
  207. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/task_completion_checker.py +0 -0
  208. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/tech_debt_manager.py +0 -0
  209. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/test_quality_guard.py +0 -0
  210. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/todo_drift_monitor.py +0 -0
  211. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/two_stage_review_gate.py +0 -0
  212. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/ue_test_accessibility_mixin.py +0 -0
  213. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/ue_test_framework.py +0 -0
  214. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/ue_test_framework_base.py +0 -0
  215. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/ue_test_heuristic_mixin.py +0 -0
  216. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/ue_test_journey_mixin.py +0 -0
  217. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/ue_test_mixins.py +0 -0
  218. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/ue_test_persona_mixin.py +0 -0
  219. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/unified_gate_engine.py +0 -0
  220. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/usage_tracker.py +0 -0
  221. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/user_friendly_error.py +0 -0
  222. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/verification_gate.py +0 -0
  223. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/warmup_manager.py +0 -0
  224. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/worker.py +0 -0
  225. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/workflow_engine.py +0 -0
  226. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/workflow_engine_base.py +0 -0
  227. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/workflow_engine_lifecycle_mixin.py +0 -0
  228. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/workflow_engine_mixins.py +0 -0
  229. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/workflow_engine_persistence_mixin.py +0 -0
  230. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/workflow_engine_state_mixin.py +0 -0
  231. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/workflow_engine_transition_mixin.py +0 -0
  232. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/collaboration/yagni_checker.py +0 -0
  233. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/dashboard/__init__.py +0 -0
  234. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/dashboard/app.py +0 -0
  235. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/dashboard/auth_views.py +0 -0
  236. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/dashboard/components.py +0 -0
  237. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/dashboard/dag_views.py +0 -0
  238. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/dashboard/dispatch_views.py +0 -0
  239. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/dashboard/i18n.py +0 -0
  240. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/dashboard/lifecycle_views.py +0 -0
  241. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/dashboard/metrics_views.py +0 -0
  242. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/dashboard/state.py +0 -0
  243. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/dashboard/v43_panels.py +0 -0
  244. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/dashboard.py +0 -0
  245. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/generate_benchmark_report.py +0 -0
  246. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/history_manager.py +0 -0
  247. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/mcp_server.py +0 -0
  248. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/qa/__init__.py +0 -0
  249. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/qa/deterministic_rule_engine.py +0 -0
  250. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/qa/models.py +0 -0
  251. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/qa/taste_dials.py +0 -0
  252. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/qa/uiux_analyzer.py +0 -0
  253. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/qa/uiux_subitems.py +0 -0
  254. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/qa/visual_regression.py +0 -0
  255. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/scan_pickle_payloads.py +0 -0
  256. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/utils/__init__.py +0 -0
  257. {devsquad-4.3.0 → devsquad-4.3.1}/scripts/utils/_find_missing_hints.py +0 -0
  258. {devsquad-4.3.0 → devsquad-4.3.1}/setup.cfg +0 -0
  259. {devsquad-4.3.0 → devsquad-4.3.1}/skills/_version.py +0 -0
  260. {devsquad-4.3.0 → devsquad-4.3.1}/skills/dispatch/handler.py +0 -0
  261. {devsquad-4.3.0 → devsquad-4.3.1}/skills/intent/handler.py +0 -0
  262. {devsquad-4.3.0 → devsquad-4.3.1}/skills/prototype/handler.py +0 -0
  263. {devsquad-4.3.0 → devsquad-4.3.1}/skills/registry.py +0 -0
  264. {devsquad-4.3.0 → devsquad-4.3.1}/skills/retrospective/__init__.py +0 -0
  265. {devsquad-4.3.0 → devsquad-4.3.1}/skills/retrospective/handler.py +0 -0
  266. {devsquad-4.3.0 → devsquad-4.3.1}/skills/review/handler.py +0 -0
  267. {devsquad-4.3.0 → devsquad-4.3.1}/skills/security/handler.py +0 -0
  268. {devsquad-4.3.0 → devsquad-4.3.1}/skills/teach/handler.py +0 -0
  269. {devsquad-4.3.0 → devsquad-4.3.1}/skills/test/__init__.py +0 -0
  270. {devsquad-4.3.0 → devsquad-4.3.1}/skills/test/handler.py +0 -0
  271. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_4pt_grid.py +0 -0
  272. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_adaptive_role_selector.py +0 -0
  273. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_adversarial_verify.py +0 -0
  274. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_agent_briefing.py +0 -0
  275. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_anchor_retrospective.py +0 -0
  276. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_anti_rationalization.py +0 -0
  277. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_antipattern_bans.py +0 -0
  278. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_api_budget_status_endpoint.py +0 -0
  279. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_api_security.py +0 -0
  280. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_api_server_v362.py +0 -0
  281. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_async_coordinator.py +0 -0
  282. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_async_modules.py +0 -0
  283. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_audit_logger.py +0 -0
  284. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_auth_phase5.py +0 -0
  285. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_autonomous.py +0 -0
  286. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_benchmark_ponytail_smart.py +0 -0
  287. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_cache_interface.py +0 -0
  288. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_ccr_store.py +0 -0
  289. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_check_async_coverage.py +0 -0
  290. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_check_config_consistency.py +0 -0
  291. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_check_constructor_params.py +0 -0
  292. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_check_dependency_lock.py +0 -0
  293. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_check_hidden_content.py +0 -0
  294. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_check_test_pyramid.py +0 -0
  295. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_check_test_quality.py +0 -0
  296. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_check_version_consistency.py +0 -0
  297. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_ci_feedback_adapter.py +0 -0
  298. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_cli_command_classifier.py +0 -0
  299. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_cli_deep_v362.py +0 -0
  300. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_cli_lifecycle.py +0 -0
  301. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_cli_phase5.py +0 -0
  302. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_code_knowledge_graph.py +0 -0
  303. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_claw_integration_test.py +0 -0
  304. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_context_compressor_test.py +0 -0
  305. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_core_test.py +0 -0
  306. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_dispatcher_test.py +0 -0
  307. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_dispatcher_ux_test.py +0 -0
  308. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_e2e_test.py +0 -0
  309. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_enhanced_e2e_test.py +0 -0
  310. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_llm_cache_test.py +0 -0
  311. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_llm_retry_test.py +0 -0
  312. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_mce_adapter_test.py +0 -0
  313. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_memory_bridge_test.py +0 -0
  314. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_performance_monitor_test.py +0 -0
  315. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_permission_guard_test.py +0 -0
  316. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_prompt_optimization_test.py +0 -0
  317. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_role_mapping_test.py +0 -0
  318. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_skillifier_test.py +0 -0
  319. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_test_quality_guard.py +0 -0
  320. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_test_quality_guard_test.py +0 -0
  321. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_upstream_test.py +0 -0
  322. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_collaboration_warmup_manager_test.py +0 -0
  323. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_confidence_score.py +0 -0
  324. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_config_injection.py +0 -0
  325. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_consensus_dissent.py +0 -0
  326. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_consensus_fatigue.py +0 -0
  327. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_consensus_gate.py +0 -0
  328. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_content_cache.py +0 -0
  329. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_content_crusher.py +0 -0
  330. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_coordinator_smart_compression.py +0 -0
  331. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_dag_views.py +0 -0
  332. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_dashboard_live_mode.py +0 -0
  333. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_dashboard_split.py +0 -0
  334. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_dashboard_ui_e2e.py +0 -0
  335. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_dashboard_v43_panels.py +0 -0
  336. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_data_backup.py +0 -0
  337. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_debt_collector.py +0 -0
  338. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_deep_shallow.py +0 -0
  339. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_deletion_test.py +0 -0
  340. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_dependency_hallucination_checker.py +0 -0
  341. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_dependency_lock.py +0 -0
  342. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_deployment_compliance_checker.py +0 -0
  343. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_deterministic_rule_engine.py +0 -0
  344. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_dispatch_audit.py +0 -0
  345. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_dispatch_performance.py +0 -0
  346. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_dispatch_rbac.py +0 -0
  347. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_dispatch_steps.py +0 -0
  348. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_dispatcher_mixins.py +0 -0
  349. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_dispatcher_phase5_core.py +0 -0
  350. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_docker_deployment.py +0 -0
  351. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_dual_layer_context.py +0 -0
  352. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_enhanced_worker.py +0 -0
  353. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_feedback_control_loop.py +0 -0
  354. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_five_axis_consensus.py +0 -0
  355. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_flow_standalone.py +0 -0
  356. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_full_lifecycle_adapter.py +0 -0
  357. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_git_guardrails.py +0 -0
  358. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_glossary_loader.py +0 -0
  359. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_grilling_mode.py +0 -0
  360. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_handoff_redaction.py +0 -0
  361. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_history_manager_v362.py +0 -0
  362. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_input_validator_phase5.py +0 -0
  363. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_input_validator_sensitive.py +0 -0
  364. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_intent_workflow_mapper.py +0 -0
  365. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_judge_agent.py +0 -0
  366. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_learned_rule_phase4.py +0 -0
  367. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_lifecycle_protocol.py +0 -0
  368. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_llm_auto_fallback.py +0 -0
  369. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_llm_cache_protocol.py +0 -0
  370. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_loop_engineering.py +0 -0
  371. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_loop_engineering_rollback.py +0 -0
  372. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_mcp_server_v362.py +0 -0
  373. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_memory_benchmarks.py +0 -0
  374. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_meta_skill_layering.py +0 -0
  375. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_micro_task_planner.py +0 -0
  376. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_multi_host_adapter.py +0 -0
  377. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_multi_tenant.py +0 -0
  378. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_multi_tenant_isolation_e2e.py +0 -0
  379. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_no_op_test.py +0 -0
  380. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_node_type_separation.py +0 -0
  381. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_null_providers.py +0 -0
  382. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_oklch_color.py +0 -0
  383. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_operation_classifier.py +0 -0
  384. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_output_slicer.py +0 -0
  385. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_output_validator_prompt_injection.py +0 -0
  386. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_performance_benchmarks.py +0 -0
  387. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_performance_fingerprint.py +0 -0
  388. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_performance_monitor_protocol.py +0 -0
  389. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_permission_guard_human_gate.py +0 -0
  390. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_permission_guard_phase5.py +0 -0
  391. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_phase4_ghost_feature_defense.py +0 -0
  392. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_pipeline_step19_20.py +0 -0
  393. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_plan_c_unified_architecture.py +0 -0
  394. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_plugins_hot_loader.py +0 -0
  395. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_ponytail_rule_injector.py +0 -0
  396. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_production_features.py +0 -0
  397. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_prometheus_metrics.py +0 -0
  398. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_prompt_dials.py +0 -0
  399. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_protocols.py +0 -0
  400. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_prototype_skill.py +0 -0
  401. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_qa_uiux_visual_regression.py +0 -0
  402. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_quick_bonus.py +0 -0
  403. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_rate_limit.py +0 -0
  404. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_rbac_engine.py +0 -0
  405. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_rbac_fail_closed.py +0 -0
  406. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_red_capable_gate.py +0 -0
  407. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_redesign_auditor.py +0 -0
  408. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_redis_cache.py +0 -0
  409. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_requirement_tracer.py +0 -0
  410. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_retry_jitter_strategies.py +0 -0
  411. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_role_skill_loader.py +0 -0
  412. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_rule_collector.py +0 -0
  413. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_rule_injection_security.py +0 -0
  414. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_secret_patterns.py +0 -0
  415. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_severity_router.py +0 -0
  416. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_similar_task_recommender.py +0 -0
  417. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_skill_registry_coverage.py +0 -0
  418. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_skill_security.py +0 -0
  419. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_sleep_guard.py +0 -0
  420. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_standardized_role_template.py +0 -0
  421. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_start_script.py +0 -0
  422. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_step_node_types.py +0 -0
  423. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_suggested_next_steps.py +0 -0
  424. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_task_completion_checker.py +0 -0
  425. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_taste_dials.py +0 -0
  426. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_tautological_seams.py +0 -0
  427. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_teach_skill.py +0 -0
  428. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_tech_debt_manager.py +0 -0
  429. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_todo_drift_monitor.py +0 -0
  430. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_token_budget_compressed_scratchpad.py +0 -0
  431. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_triage_label.py +0 -0
  432. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_two_stage_review_gate.py +0 -0
  433. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_ue_test_framework.py +0 -0
  434. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_uiux_subitems.py +0 -0
  435. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_usage_tracker_coverage.py +0 -0
  436. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_v39_e2e.py +0 -0
  437. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_v39_performance.py +0 -0
  438. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_v411_security_hardening.py +0 -0
  439. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_verification_gate.py +0 -0
  440. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_version.py +0 -0
  441. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_vertical_slice.py +0 -0
  442. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_workflow_engine.py +0 -0
  443. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_workflow_engine_base.py +0 -0
  444. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_workflow_engine_lifecycle.py +0 -0
  445. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_workflow_engine_state.py +0 -0
  446. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_workflow_engine_transition.py +0 -0
  447. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_workflow_persistence_coverage.py +0 -0
  448. {devsquad-4.3.0 → devsquad-4.3.1}/tests/test_yagni_checker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devsquad
3
- Version: 4.3.0
3
+ Version: 4.3.1
4
4
  Summary: Production-Ready Multi-Role AI Task Orchestrator
5
5
  Author-email: DevSquad Team <devsquad@example.com>
6
6
  License: MIT
@@ -103,7 +103,7 @@ Dynamic: license-file
103
103
  <img alt="Python" src="https://img.shields.io/badge/Python-3.10+-blue?logo=python&logoColor=white" />
104
104
  <img alt="License" src="https://img.shields.io/badge/License-MIT-green" />
105
105
  <img alt="Tests" src="https://img.shields.io/badge/Tests-7681%20passing-brightgreen" />
106
- <img alt="Version" src="https://img.shields.io/badge/V4.3.0-success" />
106
+ <img alt="Version" src="https://img.shields.io/badge/V4.3.1-success" />
107
107
  <img alt="CI" src="https://img.shields.io/badge/CI-GitHub_Actions-blue?logo=githubactions" />
108
108
  <img alt="Quality" src="https://img.shields.io/badge/Code%20Quality-4.3%2F5%20%E2%98%85%E2%98%85%E2%98%85%E2%98%85%E2%98%86-blue" />
109
109
  <img alt="Security" src="https://img.shields.io/badge/Security-5%2F5%20%E2%98%85%E2%98%85%E2%98%85%E2%98%85%E2%98%85-success" />
@@ -10,7 +10,7 @@
10
10
  <img alt="Python" src="https://img.shields.io/badge/Python-3.10+-blue?logo=python&logoColor=white" />
11
11
  <img alt="License" src="https://img.shields.io/badge/License-MIT-green" />
12
12
  <img alt="Tests" src="https://img.shields.io/badge/Tests-7681%20passing-brightgreen" />
13
- <img alt="Version" src="https://img.shields.io/badge/V4.3.0-success" />
13
+ <img alt="Version" src="https://img.shields.io/badge/V4.3.1-success" />
14
14
  <img alt="CI" src="https://img.shields.io/badge/CI-GitHub_Actions-blue?logo=githubactions" />
15
15
  <img alt="Quality" src="https://img.shields.io/badge/Code%20Quality-4.3%2F5%20%E2%98%85%E2%98%85%E2%98%85%E2%98%85%E2%98%86-blue" />
16
16
  <img alt="Security" src="https://img.shields.io/badge/Security-5%2F5%20%E2%98%85%E2%98%85%E2%98%85%E2%98%85%E2%98%85-success" />
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devsquad
3
- Version: 4.3.0
3
+ Version: 4.3.1
4
4
  Summary: Production-Ready Multi-Role AI Task Orchestrator
5
5
  Author-email: DevSquad Team <devsquad@example.com>
6
6
  License: MIT
@@ -103,7 +103,7 @@ Dynamic: license-file
103
103
  <img alt="Python" src="https://img.shields.io/badge/Python-3.10+-blue?logo=python&logoColor=white" />
104
104
  <img alt="License" src="https://img.shields.io/badge/License-MIT-green" />
105
105
  <img alt="Tests" src="https://img.shields.io/badge/Tests-7681%20passing-brightgreen" />
106
- <img alt="Version" src="https://img.shields.io/badge/V4.3.0-success" />
106
+ <img alt="Version" src="https://img.shields.io/badge/V4.3.1-success" />
107
107
  <img alt="CI" src="https://img.shields.io/badge/CI-GitHub_Actions-blue?logo=githubactions" />
108
108
  <img alt="Quality" src="https://img.shields.io/badge/Code%20Quality-4.3%2F5%20%E2%98%85%E2%98%85%E2%98%85%E2%98%85%E2%98%86-blue" />
109
109
  <img alt="Security" src="https://img.shields.io/badge/Security-5%2F5%20%E2%98%85%E2%98%85%E2%98%85%E2%98%85%E2%98%85-success" />
@@ -55,6 +55,7 @@ scripts/collaboration/async_coordinator.py
55
55
  scripts/collaboration/async_llm_backend.py
56
56
  scripts/collaboration/audit_logger.py
57
57
  scripts/collaboration/batch_scheduler.py
58
+ scripts/collaboration/benchmark_regression_checker.py
58
59
  scripts/collaboration/cache_interface.py
59
60
  scripts/collaboration/ccr_store.py
60
61
  scripts/collaboration/checkpoint_manager.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "devsquad"
7
- version = "4.3.0"
7
+ version = "4.3.1"
8
8
  description = "Production-Ready Multi-Role AI Task Orchestrator"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -0,0 +1 @@
1
+ __version__ = "4.3.1"
@@ -0,0 +1,378 @@
1
+ #!/usr/bin/env python3
2
+ """BenchmarkRegressionChecker -- V4.3.1 Phase 1 P1-1.
3
+
4
+ P11 lifecycle gate checker that detects performance benchmark
5
+ regressions by comparing a current snapshot against a baseline.
6
+
7
+ Architecture reference: docs/analysis/2026-07-25_V4.3.1_plan.md sec 3.1
8
+ Test plan: tests/unit/test_benchmark_regression_checker.py
9
+
10
+ Skill integration (anti-ghost feature):
11
+ - Integration point: ``unified_gate_engine.py`` P11 lifecycle gate
12
+ - Trigger: dispatcher auto-invokes via
13
+ ``lifecycle_gate_check(phase="P11", ...)``
14
+ - User visibility: Markdown report "Benchmark Regression" section
15
+ - CI check: module call count > 0 (verified by
16
+ ``check_module_activation.py``)
17
+
18
+ Regression model
19
+ ----------------
20
+ For each metric present in both snapshots::
21
+
22
+ regression_percent = (current - baseline) / baseline * 100
23
+
24
+ Positive values indicate slowdown (regression); negative values
25
+ indicate speedup (improvement). A metric is flagged as regressed when
26
+ its regression percentage strictly exceeds ``threshold_percent``. The
27
+ report's ``regression_percent`` is the maximum across all comparable
28
+ metrics, so a single slow metric raises the overall number even if
29
+ others improved.
30
+ """
31
+
32
+ from __future__ import annotations
33
+
34
+ import logging
35
+ import time
36
+ from dataclasses import dataclass, field
37
+ from typing import Literal
38
+
39
+ from scripts.collaboration._version import __version__
40
+
41
+ logger = logging.getLogger(__name__)
42
+
43
+ RegressionLevel = Literal["none", "minor", "major", "critical"]
44
+
45
+
46
+ @dataclass(slots=True)
47
+ class BenchmarkMetric:
48
+ """A single benchmark measurement.
49
+
50
+ Attributes
51
+ ----------
52
+ name:
53
+ Metric identifier (e.g. ``"dispatch_p95_ms"``,
54
+ ``"memory_peak_mb"``).
55
+ value:
56
+ Measured value (float for latencies, int for counts).
57
+ unit:
58
+ Unit string (e.g. ``"ms"``, ``"MB"``, ``"ops/sec"``).
59
+ """
60
+
61
+ name: str
62
+ value: float
63
+ unit: str
64
+
65
+
66
+ @dataclass(slots=True)
67
+ class BenchmarkSnapshot:
68
+ """A versioned benchmark snapshot.
69
+
70
+ Attributes
71
+ ----------
72
+ version:
73
+ DevSquad version string (e.g. ``"4.3.0"``).
74
+ timestamp:
75
+ Unix timestamp of snapshot collection.
76
+ metrics:
77
+ List of :class:`BenchmarkMetric` instances.
78
+ """
79
+
80
+ version: str
81
+ timestamp: float
82
+ metrics: list[BenchmarkMetric] = field(default_factory=list)
83
+
84
+
85
+ @dataclass(slots=True)
86
+ class BenchmarkReport:
87
+ """Result of comparing current metrics against a baseline.
88
+
89
+ Attributes
90
+ ----------
91
+ regression_detected:
92
+ ``True`` if any metric regressed beyond its threshold.
93
+ regression_percent:
94
+ Maximum regression percentage across all comparable metrics
95
+ (``0.0`` when no metrics overlap). Positive value means
96
+ slowdown; negative means speedup.
97
+ regressed_metrics:
98
+ Names of metrics that exceeded the regression threshold.
99
+ baseline_version:
100
+ Version string of the baseline snapshot.
101
+ current_version:
102
+ Version string of the current snapshot.
103
+ threshold_percent:
104
+ Regression threshold in percent (default ``10.0``).
105
+ """
106
+
107
+ regression_detected: bool
108
+ regression_percent: float
109
+ regressed_metrics: list[str] = field(default_factory=list)
110
+ baseline_version: str = ""
111
+ current_version: str = ""
112
+ threshold_percent: float = 10.0
113
+
114
+ def to_markdown(self) -> str:
115
+ """Render the report as a Markdown section.
116
+
117
+ Returns
118
+ -------
119
+ str
120
+ Markdown text with a ``Benchmark Regression`` header and
121
+ fields for baseline/current version, threshold, max
122
+ regression percentage, regressed metric names, and a
123
+ status line.
124
+ """
125
+ status = "REGRESSION DETECTED" if self.regression_detected else "OK"
126
+ regressed_str = (
127
+ ", ".join(self.regressed_metrics) if self.regressed_metrics else "(none)"
128
+ )
129
+ lines = [
130
+ "## Benchmark Regression",
131
+ "",
132
+ f"- **Baseline version**: {self.baseline_version}",
133
+ f"- **Current version**: {self.current_version}",
134
+ f"- **Threshold**: {self.threshold_percent}%",
135
+ f"- **Max regression**: {self.regression_percent}%",
136
+ f"- **Regressed metrics**: {regressed_str}",
137
+ f"- **Status**: {status}",
138
+ ]
139
+ return "\n".join(lines)
140
+
141
+
142
+ def _compute_regression_percent(baseline_value: float, current_value: float) -> float:
143
+ """Compute the regression percentage for a single metric.
144
+
145
+ Regression percent = ``(current - baseline) / baseline * 100``.
146
+ Positive means slowdown; negative means speedup. When the
147
+ baseline is ``0``, returns ``0.0`` to avoid division-by-zero
148
+ (a zero baseline carries no meaningful ratio).
149
+
150
+ Parameters
151
+ ----------
152
+ baseline_value:
153
+ The baseline metric value.
154
+ current_value:
155
+ The current metric value.
156
+
157
+ Returns
158
+ -------
159
+ float
160
+ The regression percentage.
161
+ """
162
+ if baseline_value == 0:
163
+ return 0.0
164
+ return (current_value - baseline_value) / baseline_value * 100.0
165
+
166
+
167
+ class BenchmarkRegressionChecker:
168
+ """Detects performance benchmark regressions between two snapshots.
169
+
170
+ Compares a current :class:`BenchmarkSnapshot` against a baseline
171
+ and flags any metric whose value increased (slowed down) beyond a
172
+ configurable threshold.
173
+
174
+ Parameters
175
+ ----------
176
+ threshold_percent:
177
+ Regression threshold in percent. A metric is flagged when its
178
+ regression percentage strictly exceeds this value. Defaults to
179
+ ``10.0`` (a 10% slowdown is tolerated, but ``10.01%`` is
180
+ flagged).
181
+
182
+ Example
183
+ -------
184
+ >>> checker = BenchmarkRegressionChecker(threshold_percent=10.0)
185
+ >>> baseline = BenchmarkSnapshot("4.2.9", 0.0, [
186
+ ... BenchmarkMetric("dispatch_p95_ms", 100.0, "ms"),
187
+ ... ])
188
+ >>> current = BenchmarkSnapshot("4.3.0", 0.0, [
189
+ ... BenchmarkMetric("dispatch_p95_ms", 125.0, "ms"),
190
+ ... ])
191
+ >>> report = checker.compare(baseline, current)
192
+ >>> report.regression_detected
193
+ True
194
+ """
195
+
196
+ def __init__(self, threshold_percent: float = 10.0) -> None:
197
+ self.threshold_percent = threshold_percent
198
+
199
+ def compare(
200
+ self,
201
+ baseline: BenchmarkSnapshot,
202
+ current: BenchmarkSnapshot,
203
+ ) -> BenchmarkReport:
204
+ """Compare two snapshots and return a regression report.
205
+
206
+ Only metrics present in both snapshots are compared. The
207
+ report's ``regression_percent`` is the maximum regression
208
+ percentage across all comparable metrics (``0.0`` when no
209
+ metrics overlap). A metric is added to ``regressed_metrics``
210
+ when its regression percentage strictly exceeds
211
+ ``threshold_percent``.
212
+
213
+ Parameters
214
+ ----------
215
+ baseline:
216
+ The baseline snapshot to compare against.
217
+ current:
218
+ The current snapshot to evaluate.
219
+
220
+ Returns
221
+ -------
222
+ BenchmarkReport
223
+ The regression report with version fields populated from
224
+ the snapshots.
225
+ """
226
+ baseline_map = {m.name: m.value for m in baseline.metrics}
227
+ current_map = {m.name: m.value for m in current.metrics}
228
+
229
+ regressions: list[tuple[str, float]] = []
230
+ for name, current_value in current_map.items():
231
+ if name not in baseline_map:
232
+ continue
233
+ baseline_value = baseline_map[name]
234
+ regression = _compute_regression_percent(baseline_value, current_value)
235
+ regressions.append((name, regression))
236
+
237
+ if not regressions:
238
+ max_regression = 0.0
239
+ regressed_names: list[str] = []
240
+ else:
241
+ max_regression = max(r for _, r in regressions)
242
+ regressed_names = [
243
+ name for name, r in regressions if r > self.threshold_percent
244
+ ]
245
+
246
+ return BenchmarkReport(
247
+ regression_detected=len(regressed_names) > 0,
248
+ regression_percent=max_regression,
249
+ regressed_metrics=regressed_names,
250
+ baseline_version=baseline.version,
251
+ current_version=current.version,
252
+ threshold_percent=self.threshold_percent,
253
+ )
254
+
255
+ def run_live_benchmark(self) -> BenchmarkSnapshot:
256
+ """Run a live benchmark and return the snapshot.
257
+
258
+ This is a mock implementation that returns representative
259
+ metrics. In production, this would invoke the actual benchmark
260
+ suite (e.g. ``pytest --benchmark``). The mock metrics model a
261
+ typical dispatch pipeline: ``dispatch_p95_ms`` and
262
+ ``memory_peak_mb``.
263
+
264
+ Returns
265
+ -------
266
+ BenchmarkSnapshot
267
+ A snapshot tagged with the current package version, the
268
+ current wall-clock timestamp, and mock metrics
269
+ (``dispatch_p95_ms=120.0ms``, ``memory_peak_mb=200.0MB``).
270
+ """
271
+ metrics = [
272
+ BenchmarkMetric("dispatch_p95_ms", 120.0, "ms"),
273
+ BenchmarkMetric("memory_peak_mb", 200.0, "MB"),
274
+ ]
275
+ return BenchmarkSnapshot(
276
+ version=__version__,
277
+ timestamp=time.time(),
278
+ metrics=metrics,
279
+ )
280
+
281
+
282
+ def _default_baseline(baseline_version: str) -> BenchmarkSnapshot:
283
+ """Build the default baseline snapshot for lifecycle_gate_check.
284
+
285
+ Parameters
286
+ ----------
287
+ baseline_version:
288
+ Version string to embed in the baseline snapshot.
289
+
290
+ Returns
291
+ -------
292
+ BenchmarkSnapshot
293
+ Baseline with ``dispatch_p95_ms=100.0ms`` and
294
+ ``memory_peak_mb=200.0MB``.
295
+ """
296
+ return BenchmarkSnapshot(
297
+ version=baseline_version,
298
+ timestamp=0.0,
299
+ metrics=[
300
+ BenchmarkMetric("dispatch_p95_ms", 100.0, "ms"),
301
+ BenchmarkMetric("memory_peak_mb", 200.0, "MB"),
302
+ ],
303
+ )
304
+
305
+
306
+ def lifecycle_gate_check(
307
+ phase: str,
308
+ baseline_version: str,
309
+ current_version: str | None = None,
310
+ threshold_percent: float = 10.0,
311
+ baseline_snapshot: BenchmarkSnapshot | None = None,
312
+ current_snapshot: BenchmarkSnapshot | None = None,
313
+ ) -> BenchmarkReport:
314
+ """P11 lifecycle gate entry point.
315
+
316
+ Args:
317
+ phase: Lifecycle phase, must be ``"P11"``.
318
+ baseline_version: Version string of the baseline.
319
+ current_version: Current version (defaults to package
320
+ ``__version__``).
321
+ threshold_percent: Regression threshold in percent.
322
+ baseline_snapshot: Injected baseline (for testing). If
323
+ ``None``, uses the default baseline (100ms / 200MB).
324
+ current_snapshot: Injected current metrics (for testing). If
325
+ ``None``, runs the live benchmark.
326
+
327
+ Returns:
328
+ BenchmarkReport with ``regression_detected`` flag. The
329
+ ``baseline_version`` / ``current_version`` fields are set from
330
+ the function arguments (parameters take precedence over
331
+ snapshot-embedded versions).
332
+
333
+ Raises:
334
+ ValueError: If ``phase != "P11"``.
335
+
336
+ Example
337
+ -------
338
+ >>> report = lifecycle_gate_check(
339
+ ... phase="P11",
340
+ ... baseline_version="4.2.9",
341
+ ... current_version="4.3.0",
342
+ ... )
343
+ >>> isinstance(report, BenchmarkReport)
344
+ True
345
+ """
346
+ if phase != "P11":
347
+ raise ValueError("BenchmarkRegressionChecker only supports P11 phase")
348
+
349
+ resolved_current_version = (
350
+ current_version if current_version is not None else __version__
351
+ )
352
+ baseline = (
353
+ baseline_snapshot
354
+ if baseline_snapshot is not None
355
+ else _default_baseline(baseline_version)
356
+ )
357
+ current = (
358
+ current_snapshot
359
+ if current_snapshot is not None
360
+ else BenchmarkRegressionChecker().run_live_benchmark()
361
+ )
362
+
363
+ checker = BenchmarkRegressionChecker(threshold_percent)
364
+ report = checker.compare(baseline, current)
365
+ # Function parameters take precedence over snapshot-embedded versions.
366
+ report.baseline_version = baseline_version
367
+ report.current_version = resolved_current_version
368
+ return report
369
+
370
+
371
+ __all__ = [
372
+ "BenchmarkMetric",
373
+ "BenchmarkSnapshot",
374
+ "BenchmarkReport",
375
+ "RegressionLevel",
376
+ "lifecycle_gate_check",
377
+ "BenchmarkRegressionChecker",
378
+ ]
@@ -29,6 +29,7 @@ deferred to Phase 3.
29
29
 
30
30
  from __future__ import annotations
31
31
 
32
+ import base64
32
33
  import logging
33
34
  import re
34
35
  from dataclasses import dataclass, field
@@ -37,7 +38,14 @@ from typing import Literal
37
38
  logger = logging.getLogger(__name__)
38
39
 
39
40
 
40
- FindingCategory = Literal["code_injection", "sensitive_info", "path_leak", "prompt_injection"]
41
+ FindingCategory = Literal[
42
+ "code_injection",
43
+ "sensitive_info",
44
+ "path_leak",
45
+ "prompt_injection",
46
+ "base64_encoded_leak",
47
+ "unicode_homoglyph",
48
+ ]
41
49
  FindingSeverity = Literal["low", "medium", "high"]
42
50
 
43
51
 
@@ -213,11 +221,44 @@ class OutputValidator:
213
221
  (r"(?i)\bshutdown\s+(?:now|immediately|-h\s+now)\b", "destructive_shutdown", "high"),
214
222
  ]
215
223
 
224
+ # V4.3.1: Base64-encoded sensitive content leakage detection.
225
+ # Strategy: detect JWT-like 3-segment base64 (eyJ prefix) and long
226
+ # base64 blobs (>=64 chars). For long blobs, attempt to decode and
227
+ # check if decoded content contains known sensitive patterns.
228
+ BASE64_ENCODED_LEAK_PATTERNS: list[tuple[str, str, FindingSeverity]] = [
229
+ # JWT-like 3-segment base64 (eyJ prefix)
230
+ (r"\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b",
231
+ "base64_jwt_token", "high"),
232
+ # Long base64 string (>=64 chars, may encode keys/credentials)
233
+ (r"\b[A-Za-z0-9+/]{64,}={0,2}\b", "base64_long_blob", "medium"),
234
+ ]
235
+
236
+ # V4.3.1: Unicode homoglyph attack detection.
237
+ # Strategy: detect common confusable characters (Cyrillic/Greek
238
+ # substitutes for Latin letters) using a static whitelist (no
239
+ # external dependency on a confusables database).
240
+ UNICODE_HOMOGLYPH_PATTERNS: list[tuple[str, str, FindingSeverity]] = [
241
+ # Cyrillic 'a' (U+0430 lowercase, U+0410 uppercase) for Latin 'a'
242
+ (r"[\u0430\u0410]", "homoglyph_cyrillic_a", "medium"),
243
+ # Cyrillic 'e' (U+0435 lowercase, U+0415 uppercase) for Latin 'e'
244
+ (r"[\u0435\u0415]", "homoglyph_cyrillic_e", "medium"),
245
+ # Cyrillic 'o' (U+043E lowercase, U+041E uppercase) for Latin 'o'
246
+ (r"[\u043e\u041e]", "homoglyph_cyrillic_o", "medium"),
247
+ # Cyrillic 'p' (U+0440 lowercase, U+0420 uppercase) for Latin 'p'
248
+ (r"[\u0440\u0420]", "homoglyph_cyrillic_p", "medium"),
249
+ # Cyrillic 'c' (U+0441 lowercase, U+0421 uppercase) for Latin 'c'
250
+ (r"[\u0441\u0421]", "homoglyph_cyrillic_c", "medium"),
251
+ # Greek 'o' (U+03BF lowercase, U+039F uppercase) for Latin 'o'
252
+ (r"[\u03bf\u039f]", "homoglyph_greek_o", "medium"),
253
+ ]
254
+
216
255
  # Compiled pattern cache (class-level for reuse).
217
256
  _COMPILED_CODE_INJECTION: list[tuple[re.Pattern[str], str, FindingSeverity]] = []
218
257
  _COMPILED_SENSITIVE_INFO: list[tuple[re.Pattern[str], str, FindingSeverity]] = []
219
258
  _COMPILED_PATH_LEAK: list[tuple[re.Pattern[str], str, FindingSeverity]] = []
220
259
  _COMPILED_PROMPT_INJECTION: list[tuple[re.Pattern[str], str, FindingSeverity]] = []
260
+ _COMPILED_BASE64: list[tuple[re.Pattern[str], str, FindingSeverity]] = []
261
+ _COMPILED_HOMOGLYPH: list[tuple[re.Pattern[str], str, FindingSeverity]] = []
221
262
 
222
263
  def __init__(self) -> None:
223
264
  # Compile once at instance construction (deferred from class-level
@@ -235,6 +276,12 @@ class OutputValidator:
235
276
  OutputValidator._COMPILED_PROMPT_INJECTION = [
236
277
  (re.compile(p), name, sev) for p, name, sev in self.PROMPT_INJECTION_PATTERNS
237
278
  ]
279
+ OutputValidator._COMPILED_BASE64 = [
280
+ (re.compile(p), name, sev) for p, name, sev in self.BASE64_ENCODED_LEAK_PATTERNS
281
+ ]
282
+ OutputValidator._COMPILED_HOMOGLYPH = [
283
+ (re.compile(p), name, sev) for p, name, sev in self.UNICODE_HOMOGLYPH_PATTERNS
284
+ ]
238
285
 
239
286
  # ------------------------------------------------------------------
240
287
  # Public API
@@ -256,6 +303,8 @@ class OutputValidator:
256
303
  findings.extend(self._scan_sensitive_info(text))
257
304
  findings.extend(self._scan_path_leak(text))
258
305
  findings.extend(self._scan_prompt_injection(text))
306
+ findings.extend(self._scan_base64(text))
307
+ findings.extend(self._scan_unicode_homoglyph(text))
259
308
 
260
309
  # Sort by span start so redaction offsets are processed left-to-right.
261
310
  findings.sort(key=lambda f: f.span[0])
@@ -288,6 +337,49 @@ class OutputValidator:
288
337
  def _scan_prompt_injection(self, text: str) -> list[OutputFinding]:
289
338
  return self._scan(text, self._COMPILED_PROMPT_INJECTION, "prompt_injection")
290
339
 
340
+ def _scan_base64(self, text: str) -> list[OutputFinding]:
341
+ """Scan for base64-encoded sensitive content.
342
+
343
+ For long base64 blobs, attempt to decode and check if the decoded
344
+ content contains known sensitive patterns (sk-/password=/AKIA...).
345
+ If decoded content matches sensitive patterns, escalate severity
346
+ from medium to high.
347
+
348
+ Fail-secure: if base64 decode fails, keep medium severity.
349
+ """
350
+ findings = self._scan(text, self._COMPILED_BASE64, "base64_encoded_leak")
351
+ escalated: list[OutputFinding] = []
352
+ for f in findings:
353
+ if f.pattern_name == "base64_long_blob" and f.severity == "medium":
354
+ try:
355
+ decoded_bytes = base64.b64decode(f.matched_text, validate=True)
356
+ decoded = decoded_bytes.decode("utf-8", errors="ignore")
357
+ if (
358
+ re.search(r"sk-[A-Za-z0-9]{20,}", decoded)
359
+ or re.search(r"(?i)password\s*[=:]", decoded)
360
+ or re.search(r"AKIA[0-9A-Z]{16}", decoded)
361
+ ):
362
+ escalated.append(
363
+ OutputFinding(
364
+ category=f.category,
365
+ severity="high",
366
+ pattern_name=f.pattern_name + "_sensitive",
367
+ matched_text=f.matched_text,
368
+ redacted_text=f.redacted_text,
369
+ span=f.span,
370
+ )
371
+ )
372
+ continue
373
+ except Exception:
374
+ # Fail-secure: keep medium severity if decode fails.
375
+ pass
376
+ escalated.append(f)
377
+ return escalated
378
+
379
+ def _scan_unicode_homoglyph(self, text: str) -> list[OutputFinding]:
380
+ """Scan for Unicode homoglyph attacks."""
381
+ return self._scan(text, self._COMPILED_HOMOGLYPH, "unicode_homoglyph")
382
+
291
383
  @staticmethod
292
384
  def _scan(
293
385
  text: str,
@@ -1,5 +1,5 @@
1
1
  """
2
- DevSquad V4.3.0 — Layered Sub-Skill Architecture
2
+ DevSquad V4.3.1 — Layered Sub-Skill Architecture
3
3
 
4
4
  This package provides fine-grained, independently usable skills that wrap
5
5
  DevSquad's core modules. Each sub-skill is a thin handler (~50 lines) that
@@ -1 +0,0 @@
1
- __version__ = "4.3.0"
File without changes
File without changes
File without changes
File without changes
File without changes