dialectical-framework 1.6.2__tar.gz → 1.6.4__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 (191) hide show
  1. dialectical_framework-1.6.4/PATENTS +79 -0
  2. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/PKG-INFO +10 -1
  3. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/README.md +10 -1
  4. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/pyproject.toml +2 -1
  5. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/analyst/analyst.py +48 -0
  6. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/analyst/skills/find_polarities.py +215 -45
  7. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/analyst/system_prompts.py +37 -0
  8. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/apps.py +1 -1
  9. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/ac_re_taxonomy.py +0 -2
  10. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/antithesis_classification.py +1 -1
  11. dialectical_framework-1.6.4/src/dialectical_framework/concerns/antithetical_thesis_detection.py +338 -0
  12. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/LICENSE +0 -0
  13. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/__init__.py +0 -0
  14. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/__init__.py +0 -0
  15. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/advisor/__init__.py +0 -0
  16. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/advisor/advisor.py +0 -0
  17. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/advisor/system_prompts.py +0 -0
  18. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/advisor/tools/__init__.py +0 -0
  19. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/advisor/tools/anchor.py +0 -0
  20. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/advisor/tools/explore.py +0 -0
  21. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/advisor/tools/ingest.py +0 -0
  22. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/advisor/tools/sync.py +0 -0
  23. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/agent_context.py +0 -0
  24. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/analyst/__init__.py +0 -0
  25. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/analyst/skills/__init__.py +0 -0
  26. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/analyst/skills/anchor_theses.py +0 -0
  27. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/analyst/skills/edit_perspective.py +0 -0
  28. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/analyst/skills/expand_polarities.py +0 -0
  29. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/analyst/skills/introduce_polarity.py +0 -0
  30. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/analyst/skills/surface_theses.py +0 -0
  31. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/analyst/tools/__init__.py +0 -0
  32. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/analyst/tools/create_dx_input.py +0 -0
  33. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/analyst/tools/place_statement.py +0 -0
  34. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/conversation_facilitator.py +0 -0
  35. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/execution_report.py +0 -0
  36. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/explorer/__init__.py +0 -0
  37. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/explorer/explorer.py +0 -0
  38. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/explorer/skills/__init__.py +0 -0
  39. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/explorer/skills/build_wheels.py +0 -0
  40. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/explorer/skills/explore_transformations.py +0 -0
  41. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/explorer/skills/generate_synthesis.py +0 -0
  42. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/explorer/system_prompts.py +0 -0
  43. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/explorer/tools/__init__.py +0 -0
  44. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/explorer/tools/create_nexus.py +0 -0
  45. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/explorer/tools/expand_nexus.py +0 -0
  46. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/explorer/tools/generate_synthesis.py +0 -0
  47. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/explorer/tools/present_exploration.py +0 -0
  48. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/orchestrator/__init__.py +0 -0
  49. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/orchestrator/tools/__init__.py +0 -0
  50. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/orchestrator/tools/add_input.py +0 -0
  51. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/orchestrator/tools/digest_input.py +0 -0
  52. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/orchestrator/tools/discard.py +0 -0
  53. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/orchestrator/tools/get_schema.py +0 -0
  54. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/orchestrator/tools/inspect_node.py +0 -0
  55. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/orchestrator/tools/present_analysis.py +0 -0
  56. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/orchestrator/tools/query_graph.py +0 -0
  57. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/orchestrator/tools/read_digest.py +0 -0
  58. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/orchestrator/tools/read_input.py +0 -0
  59. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/reasonable_concern.py +0 -0
  60. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/agents/stream_events.py +0 -0
  61. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/__init__.py +0 -0
  62. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/action_extraction.py +0 -0
  63. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/add_input.py +0 -0
  64. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/ai_dto/__init__.py +0 -0
  65. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/ai_dto/statement_dto.py +0 -0
  66. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/ai_dto/statements_deck_dto.py +0 -0
  67. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/antithesis_extraction.py +0 -0
  68. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/aspect_classification.py +0 -0
  69. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/aspect_generation.py +0 -0
  70. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/causality/__init__.py +0 -0
  71. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/causality/causality_estimator.py +0 -0
  72. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/causality/causality_estimator_balanced.py +0 -0
  73. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/causality/causality_estimator_criteria.py +0 -0
  74. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/causality/causality_estimator_desirable.py +0 -0
  75. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/causality/causality_estimator_feasible.py +0 -0
  76. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/causality/causality_estimator_realistic.py +0 -0
  77. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/causality/causality_normalizer.py +0 -0
  78. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/causality/estimator_resolver.py +0 -0
  79. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/causality_estimation.py +0 -0
  80. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/control_statements_check.py +0 -0
  81. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/create_dx_input.py +0 -0
  82. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/create_nexus.py +0 -0
  83. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/diagonal_oppositions_check.py +0 -0
  84. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/dialectical_context.py +0 -0
  85. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/discard.py +0 -0
  86. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/display_text_edit.py +0 -0
  87. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/expand_nexus.py +0 -0
  88. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/perspective_combination.py +0 -0
  89. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/perspective_validation.py +0 -0
  90. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/positive_ac_re_apex_derivation.py +0 -0
  91. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/scoring_scales.py +0 -0
  92. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/source_digest.py +0 -0
  93. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/statement_classification.py +0 -0
  94. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/statement_deduplication.py +0 -0
  95. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/statement_headline.py +0 -0
  96. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/statement_placement.py +0 -0
  97. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/synthesis_generation.py +0 -0
  98. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/thesis_extraction.py +0 -0
  99. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/transformation_audit.py +0 -0
  100. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/concerns/transformation_generation.py +0 -0
  101. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/dialectical_reasoning.py +0 -0
  102. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/enums/__init__.py +0 -0
  103. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/enums/causality_preset.py +0 -0
  104. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/enums/di.py +0 -0
  105. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/events/__init__.py +0 -0
  106. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/events/graph_event.py +0 -0
  107. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/events/graph_event_bus.py +0 -0
  108. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/exceptions/__init__.py +0 -0
  109. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/exceptions/node_errors.py +0 -0
  110. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/exceptions/resolver_errors.py +0 -0
  111. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/__init__.py +0 -0
  112. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/composite_input_resolver.py +0 -0
  113. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/dialexity_input_resolver.py +0 -0
  114. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/estimation_manager.py +0 -0
  115. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/mixins/__init__.py +0 -0
  116. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/mixins/incremental_build_mixin.py +0 -0
  117. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/mixins/intent_mixin.py +0 -0
  118. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/mixins/persistable_mixin.py +0 -0
  119. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/nodes/__init__.py +0 -0
  120. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/nodes/assessable_entity.py +0 -0
  121. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/nodes/base_node.py +0 -0
  122. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/nodes/case.py +0 -0
  123. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/nodes/cycle.py +0 -0
  124. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/nodes/estimation.py +0 -0
  125. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/nodes/ideas.py +0 -0
  126. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/nodes/input.py +0 -0
  127. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/nodes/nexus.py +0 -0
  128. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/nodes/perspective.py +0 -0
  129. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/nodes/polarity.py +0 -0
  130. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/nodes/rationale.py +0 -0
  131. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/nodes/statement.py +0 -0
  132. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/nodes/synthesis.py +0 -0
  133. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/nodes/transformation.py +0 -0
  134. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/nodes/transition.py +0 -0
  135. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/nodes/wheel.py +0 -0
  136. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationship_manager.py +0 -0
  137. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/__init__.py +0 -0
  138. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/action_reflection_relationship.py +0 -0
  139. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/belongs_to_cycle_relationship.py +0 -0
  140. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/belongs_to_nexus_relationship.py +0 -0
  141. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/changed_to_relationship.py +0 -0
  142. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/contradiction_of_relationship.py +0 -0
  143. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/critiques_relationship.py +0 -0
  144. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/distilled_to_relationship.py +0 -0
  145. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/estimates_relationship.py +0 -0
  146. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/explains_relationship.py +0 -0
  147. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/has_input_relationship.py +0 -0
  148. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/has_statement_relationship.py +0 -0
  149. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/has_wheel_relationship.py +0 -0
  150. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/immutable_structure.py +0 -0
  151. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/is_source_of_relationship.py +0 -0
  152. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/is_target_of_relationship.py +0 -0
  153. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/negative_side_of_relationship.py +0 -0
  154. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/opposite_direction_relationship.py +0 -0
  155. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/opposite_of_relationship.py +0 -0
  156. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/polarity_relationship.py +0 -0
  157. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/positive_side_of_relationship.py +0 -0
  158. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/provides_relationship.py +0 -0
  159. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/relationships/synthesis_of_relationship.py +0 -0
  160. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/rendering.py +0 -0
  161. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/repositories/__init__.py +0 -0
  162. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/repositories/case_repository.py +0 -0
  163. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/repositories/cycle_repository.py +0 -0
  164. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/repositories/input_repository.py +0 -0
  165. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/repositories/nexus_repository.py +0 -0
  166. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/repositories/node_repository.py +0 -0
  167. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/repositories/perspective_repository.py +0 -0
  168. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/repositories/polarity_repository.py +0 -0
  169. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/repositories/schema_repository.py +0 -0
  170. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/repositories/statement_repository.py +0 -0
  171. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/repositories/transformation_repository.py +0 -0
  172. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/repositories/wheel_repository.py +0 -0
  173. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/scope_context.py +0 -0
  174. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/verbatim_input_resolver.py +0 -0
  175. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/wheel_segment.py +0 -0
  176. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/graph/wheel_segment_polar_pair.py +0 -0
  177. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/protocols/__init__.py +0 -0
  178. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/protocols/has_config.py +0 -0
  179. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/protocols/input_resolver.py +0 -0
  180. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/settings.py +0 -0
  181. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/utils/__init__.py +0 -0
  182. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/utils/bedrock_provider.py +0 -0
  183. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/utils/concurrency.py +0 -0
  184. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/utils/dc_replace.py +0 -0
  185. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/utils/decompose_probability_uniformly.py +0 -0
  186. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/utils/edge_context.py +0 -0
  187. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/utils/effect_logger.py +0 -0
  188. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/utils/input_context.py +0 -0
  189. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/utils/order_transitions.py +0 -0
  190. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/utils/sequence_generation.py +0 -0
  191. {dialectical_framework-1.6.2 → dialectical_framework-1.6.4}/src/dialectical_framework/utils/use_brain.py +0 -0
@@ -0,0 +1,79 @@
1
+ Dialectical Framework
2
+ Copyright (c) 2025 Dialexity
3
+
4
+ ================================================================================
5
+ COPYRIGHT LICENSE
6
+ ================================================================================
7
+
8
+ The source code in this repository is licensed under the MIT License. See the
9
+ LICENSE file for the full terms. The MIT License governs COPYRIGHT ONLY: your
10
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and sell
11
+ copies of the software.
12
+
13
+ ================================================================================
14
+ PATENT NOTICE
15
+ ================================================================================
16
+
17
+ Independently of the copyright license above, Dialexity holds patent rights
18
+ covering methods for applying dialectical reasoning with artificial
19
+ intelligence and machine learning systems.
20
+
21
+ Patent(s) / application(s): see https://dialexity.com/patents
22
+
23
+ The MIT License does not, by itself, grant any patent rights. This file sets
24
+ out the patent terms that apply to this software.
25
+
26
+ --------------------------------------------------------------------------------
27
+ 1. Limited patent grant for use of this software as distributed
28
+ --------------------------------------------------------------------------------
29
+
30
+ Dialexity grants you a worldwide, royalty-free, non-exclusive license under the
31
+ patent(s) identified above, limited strictly to making, using, selling,
32
+ offering for sale, importing, and distributing THIS software as distributed in
33
+ this repository (and modifications of it), to the extent such acts would
34
+ otherwise infringe those patent(s).
35
+
36
+ This grant is coextensive with your use of this software. It extends ONLY to
37
+ the patented methods as embodied in this software and does NOT extend to any
38
+ other implementation of the patented methods.
39
+
40
+ --------------------------------------------------------------------------------
41
+ 2. Reservation of all other patent rights
42
+ --------------------------------------------------------------------------------
43
+
44
+ All patent rights not expressly granted in Section 1 are reserved. In
45
+ particular, and without limiting the foregoing, NO patent license is granted
46
+ for:
47
+
48
+ (a) implementations of the patented methods that are developed independently
49
+ of, or do not incorporate, this software; or
50
+
51
+ (b) products, services, or systems that practice the patented methods without
52
+ using this software as distributed.
53
+
54
+ Practicing the patented methods in any manner outside the limited grant in
55
+ Section 1 requires a separate patent license from Dialexity.
56
+
57
+ --------------------------------------------------------------------------------
58
+ 3. Defensive termination
59
+ --------------------------------------------------------------------------------
60
+
61
+ The patent grant in Section 1 terminates automatically as to any party that
62
+ initiates or joins a patent infringement claim (including a cross-claim or
63
+ counterclaim) alleging that this software, or any contribution to it,
64
+ constitutes patent infringement.
65
+
66
+ --------------------------------------------------------------------------------
67
+ 4. Commercial and patent licensing
68
+ --------------------------------------------------------------------------------
69
+
70
+ For patent licenses beyond the limited grant in Section 1 — including use of
71
+ the patented methods in independent implementations — see the patent listing
72
+ and contact details at:
73
+
74
+ https://dialexity.com/patents
75
+
76
+ ================================================================================
77
+ This file must be included in all copies or substantial portions of the
78
+ software, together with the LICENSE file.
79
+ ================================================================================
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: dialectical-framework
3
- Version: 1.6.2
3
+ Version: 1.6.4
4
4
  Summary: A dialectical framework for augmented intelligence. AI reasoning powered with dialectics supports humans in: system optimization (psychology, engineering, business, politics, etc.); dispute resolution (mediation, conflicts, negotiations, etc.); decision-making (dilemmas, challenging situations, win-win, etc.).
5
5
  License: MIT
6
6
  Keywords: dialectics,dialectical-reasoning,synthesis,thesis-antithesis,ai,artificial-intelligence,llm,reasoning-framework,philosophy,logic,argumentation,conflict-resolution,decision-making,critical-thinking,semantic-graph,mirascope,pydantic,perspectives,polarity-reasoning
@@ -176,3 +176,12 @@ poetry run pytest --real-llm # Hit real LLM provider
176
176
  - [Mirascope](https://mirascope.com/) — LLM abstraction
177
177
  - [GQLAlchemy](https://memgraph.com/docs/gqlalchemy) — Graph ORM
178
178
  - [dependency-injector](https://python-dependency-injector.ets-labs.org/) — DI container
179
+
180
+ ## License & Patents
181
+
182
+ The source code is licensed under the [MIT License](https://github.com/dialexity/dialectical-framework/blob/main/LICENSE) (copyright only).
183
+
184
+ The methods for applying dialectical reasoning with AI are patented. The MIT
185
+ License does not grant patent rights beyond a limited grant for use of this
186
+ software as distributed — see [PATENTS](https://github.com/dialexity/dialectical-framework/blob/main/PATENTS) for the patent terms and
187
+ [dialexity.com/patents](https://dialexity.com/patents) for the patent listing.
@@ -134,4 +134,13 @@ poetry run pytest --real-llm # Hit real LLM provider
134
134
 
135
135
  - [Mirascope](https://mirascope.com/) — LLM abstraction
136
136
  - [GQLAlchemy](https://memgraph.com/docs/gqlalchemy) — Graph ORM
137
- - [dependency-injector](https://python-dependency-injector.ets-labs.org/) — DI container
137
+ - [dependency-injector](https://python-dependency-injector.ets-labs.org/) — DI container
138
+
139
+ ## License & Patents
140
+
141
+ The source code is licensed under the [MIT License](https://github.com/dialexity/dialectical-framework/blob/main/LICENSE) (copyright only).
142
+
143
+ The methods for applying dialectical reasoning with AI are patented. The MIT
144
+ License does not grant patent rights beyond a limited grant for use of this
145
+ software as distributed — see [PATENTS](https://github.com/dialexity/dialectical-framework/blob/main/PATENTS) for the patent terms and
146
+ [dialexity.com/patents](https://dialexity.com/patents) for the patent listing.
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "dialectical-framework"
3
- version = "1.6.2"
3
+ version = "1.6.4"
4
4
  description = "A dialectical framework for augmented intelligence. AI reasoning powered with dialectics supports humans in: system optimization (psychology, engineering, business, politics, etc.); dispute resolution (mediation, conflicts, negotiations, etc.); decision-making (dilemmas, challenging situations, win-win, etc.)."
5
5
  authors = ["Evaldas Taroza <evaldas@dialexity.com>"]
6
6
  readme = "README.md"
@@ -35,6 +35,7 @@ classifiers = [
35
35
  "Environment :: Console",
36
36
  "Natural Language :: English"
37
37
  ]
38
+ include = [{ path = "PATENTS", format = ["sdist"] }]
38
39
 
39
40
  [[tool.poetry.packages]]
40
41
  include = "dialectical_framework"
@@ -318,6 +318,14 @@ class AnalysisPipeline(ReasonableConcern[AnalysisResult]):
318
318
  seen.add(h)
319
319
  hashes_to_expand.append(h)
320
320
 
321
+ # Surface the HS-based gate to the agent. _rank_polarities silently
322
+ # drops tensions below HS_THRESHOLD (and beyond the top few); without
323
+ # this the agent only sees a bare perspective count and cannot explain
324
+ # WHY these framings are the strong ones or that weaker tensions were
325
+ # set aside.
326
+ polarity_quality = self._build_polarity_quality(polarity_data, hashes_to_expand)
327
+ set_aside_count = sum(1 for q in polarity_quality if not q["expanded"])
328
+
321
329
  expand_results = await asyncio.gather(
322
330
  *[self._expand_one(h) for h in hashes_to_expand],
323
331
  return_exceptions=True,
@@ -338,14 +346,21 @@ class AnalysisPipeline(ReasonableConcern[AnalysisResult]):
338
346
  reports.append(report)
339
347
 
340
348
  self._report.ok = True
349
+ set_aside_note = (
350
+ f", {set_aside_count} weaker tension(s) set aside"
351
+ if set_aside_count
352
+ else ""
353
+ )
341
354
  self._report.summary = (
342
355
  f"Analysis complete: {len(thesis_hashes)} theses, "
343
356
  f"{len(polarity_hashes)} polarities, "
344
357
  f"{len(perspective_hashes)} perspectives"
358
+ f"{set_aside_note}"
345
359
  )
346
360
  self._report.artifacts["thesis_hashes"] = thesis_hashes
347
361
  self._report.artifacts["polarity_hashes"] = polarity_hashes
348
362
  self._report.artifacts["perspective_hashes"] = perspective_hashes
363
+ self._report.artifacts["polarity_quality"] = polarity_quality
349
364
 
350
365
  return AnalysisResult(
351
366
  ideas_hash=ideas_hash,
@@ -375,6 +390,39 @@ class AnalysisPipeline(ReasonableConcern[AnalysisResult]):
375
390
 
376
391
  return ranked[:MAX_POLARITIES_TO_EXPAND]
377
392
 
393
+ @staticmethod
394
+ def _build_polarity_quality(
395
+ polarity_data: list[dict], hashes_to_expand: list[str]
396
+ ) -> list[dict]:
397
+ """Per-tension HS + gate outcome, HS-descending, for the agent to read.
398
+
399
+ Makes the otherwise-silent HS gate visible: each entry flags whether the
400
+ tension was `expanded` into a full perspective or set aside. HS on the
401
+ antithesis measures how genuine the opposition is (see "Reading Polarity
402
+ Quality" in the system prompt), not the quality of the idea itself.
403
+ """
404
+ expanded_set = set(hashes_to_expand)
405
+ quality: list[dict] = []
406
+ seen: set[str] = set()
407
+ for p in polarity_data:
408
+ h = p.get("polarity_hash")
409
+ if not h or h in seen or p.get("deduped", False):
410
+ continue
411
+ seen.add(h)
412
+ quality.append(
413
+ {
414
+ "polarity_hash": h,
415
+ "thesis": p.get("thesis_text"),
416
+ "antithesis": p.get("antithesis_text"),
417
+ "hs": p.get("heuristic_similarity"),
418
+ "expanded": h in expanded_set,
419
+ }
420
+ )
421
+ quality.sort(
422
+ key=lambda q: q["hs"] if q["hs"] is not None else 0.0, reverse=True
423
+ )
424
+ return quality
425
+
378
426
  async def _expand_one(self, polarity_hash: str) -> tuple[list[str], object]:
379
427
  from dialectical_framework.agents.analyst.skills.expand_polarities import \
380
428
  ExpandPolarity
@@ -39,8 +39,13 @@ from dialectical_framework.agents.execution_report import ExecutionReport
39
39
  from dialectical_framework.enums.di import DI
40
40
  from dialectical_framework.concerns.antithesis_extraction import \
41
41
  AntithesisExtraction
42
+ from dialectical_framework.concerns.antithetical_thesis_detection import \
43
+ AntitheticalThesisDetection
42
44
  from dialectical_framework.concerns.statement_deduplication import (
43
45
  DedupResult, StatementDeduplication)
46
+ from dialectical_framework.graph.estimation_manager import EstimationManager
47
+ from dialectical_framework.graph.nodes.estimation import (ArousalEstimation,
48
+ ModeEstimation)
44
49
  from dialectical_framework.graph.nodes.statement import \
45
50
  Statement
46
51
  from dialectical_framework.graph.nodes.ideas import Ideas
@@ -121,6 +126,15 @@ class FindPolarities(ReasonableConcern[Optional[Ideas]]):
121
126
  results: list[ThesisResult] = []
122
127
  newly_extracted: list[Statement] = []
123
128
 
129
+ # Phase 0: Consolidate theses that are antitheses of each other. Strongly
130
+ # opposed pairs (HS >= 0.7) are merged into a single Polarity here and
131
+ # removed from extraction; weaker pairs are surfaced as suggestions for
132
+ # the agent to confirm (leaving both theses to proceed independently).
133
+ unique_hashes = list(dict.fromkeys(self.thesis_hashes))
134
+ unique_hashes, consolidated_data = await self._consolidate_antithetical(
135
+ unique_hashes, input_text
136
+ )
137
+
124
138
  # Phase 1: For each thesis, collect existing oppositions + extract new ones (parallel)
125
139
  import asyncio
126
140
 
@@ -155,7 +169,6 @@ class FindPolarities(ReasonableConcern[Optional[Ideas]]):
155
169
  result.existing = existing_antitheses
156
170
  return result
157
171
 
158
- unique_hashes = list(dict.fromkeys(self.thesis_hashes))
159
172
  thesis_results = await asyncio.gather(
160
173
  *[_process_thesis(h) for h in unique_hashes]
161
174
  )
@@ -209,18 +222,20 @@ class FindPolarities(ReasonableConcern[Optional[Ideas]]):
209
222
  # Phase 3: Create Polarity nodes for each T-A pair
210
223
  total_antitheses = sum(len(r.antithesis_data) for r in results if not r.error)
211
224
 
212
- if total_antitheses == 0:
225
+ if total_antitheses == 0 and not consolidated_data:
213
226
  self._report.ok = True
214
227
  self._report.summary = "No polarities found"
215
228
  self._report.artifacts["polarity_data"] = []
216
229
  return None
217
230
 
218
- # Phase 4: Create Polarities and Ideas with all T-A pairs
219
- ideas = self._create_ideas(results)
231
+ # Phase 4: Create Polarities and Ideas with all T-A pairs (consolidated
232
+ # pairs already have their Polarities created in Phase 0).
233
+ ideas = self._create_ideas(results, consolidated_data)
220
234
  polarity_map = self._create_polarities(results)
221
235
 
222
- # Build polarity_data for report (includes HS for each T-A pair)
223
- polarity_data = []
236
+ # Build polarity_data for report (includes HS for each T-A pair). Start
237
+ # with the consolidated pairs, then the extracted ones.
238
+ polarity_data = list(consolidated_data)
224
239
  for result in results:
225
240
  if result.error:
226
241
  continue
@@ -258,11 +273,26 @@ class FindPolarities(ReasonableConcern[Optional[Ideas]]):
258
273
  self._report.artifacts["polarity_data"] = polarity_data
259
274
  pol_created = self._report.artifacts.get("created_polarity_count", 0)
260
275
  pol_existing = self._report.artifacts.get("existing_polarity_count", 0)
261
- self._report.summary = (
276
+ consolidated_count = len(consolidated_data)
277
+ suggestion_count = len(
278
+ self._report.artifacts.get("consolidation_suggestions", [])
279
+ )
280
+ summary = (
262
281
  f"Found {existing_count} existing + {new_count} new antithesis(es) "
263
282
  f"for {len(self.thesis_hashes)} thesis(es). "
264
283
  f"Polarities: {pol_created} created, {pol_existing} existing."
265
284
  )
285
+ if consolidated_count:
286
+ summary += (
287
+ f" Consolidated {consolidated_count} antithetical thesis pair(s) "
288
+ f"into single tension(s)."
289
+ )
290
+ if suggestion_count:
291
+ summary += (
292
+ f" {suggestion_count} weaker pair(s) suggested for consolidation "
293
+ f"(acting on one merges 2 theses into 1 tension)."
294
+ )
295
+ self._report.summary = summary
266
296
 
267
297
  return ideas
268
298
 
@@ -424,6 +454,115 @@ class FindPolarities(ReasonableConcern[Optional[Ideas]]):
424
454
  pass
425
455
  return None
426
456
 
457
+ async def _consolidate_antithetical(
458
+ self, unique_hashes: list[str], input_text: str
459
+ ) -> tuple[list[str], list[dict]]:
460
+ """Detect and merge theses that are antitheses of each other.
461
+
462
+ Strongly-opposed pairs (HS >= 0.7) are merged into a single Polarity and
463
+ their two hashes removed from the returned list (so they are NOT sent to
464
+ antithesis extraction). Weaker pairs (0.1 < HS < 0.7) are recorded as
465
+ suggestions but left in the list to proceed as independent theses.
466
+
467
+ Returns:
468
+ (reduced_hashes, consolidated_polarity_data) where each dict has the
469
+ same shape FindPolarities uses in ``polarity_data``.
470
+ """
471
+ if len(unique_hashes) < 2:
472
+ return unique_hashes, []
473
+
474
+ detector = AntitheticalThesisDetection()
475
+ detection = await detector.resolve(
476
+ thesis_hashes=unique_hashes, text=input_text
477
+ )
478
+ self._report = self._report.merge(detector.report)
479
+
480
+ # Surface weak pairs for the agent to confirm (non-destructive).
481
+ self._report.artifacts["consolidation_suggestions"] = [
482
+ p.as_dict() for p in detection.suggest_pairs
483
+ ]
484
+
485
+ if not detection.merge_pairs:
486
+ return unique_hashes, []
487
+
488
+ pol_repo = PolarityRepository()
489
+ est_manager = EstimationManager()
490
+ consolidated_data: list[dict] = []
491
+ merged_hashes: set[str] = set()
492
+ merged_count = 0
493
+
494
+ for pair in detection.merge_pairs:
495
+ thesis = self._resolve_component(pair.thesis_hash)
496
+ antithesis = self._resolve_component(pair.antithesis_hash)
497
+ if thesis is None or antithesis is None:
498
+ continue
499
+
500
+ # Record the dialectical opposition (symmetric, idempotent).
501
+ thesis.oppositions.connect(antithesis)
502
+ self._report.relationship_created(
503
+ thesis.oppositions, thesis, antithesis
504
+ )
505
+
506
+ existing_pols = pol_repo.find_by_tension(thesis, antithesis)
507
+ if existing_pols:
508
+ polarity = existing_pols[0]
509
+ self._report.artifacts.setdefault("existing_polarity_count", 0)
510
+ self._report.artifacts["existing_polarity_count"] += 1
511
+ else:
512
+ polarity = self._build_polarity(
513
+ thesis, antithesis, pair.heuristic_similarity
514
+ )
515
+ merged_count += 1
516
+
517
+ # Persist antithesis Mode/Arousal (Antithesis Persistence Checklist).
518
+ self._persist_mode_arousal(
519
+ est_manager, antithesis, pair.mode_value, pair.arousal_value
520
+ )
521
+
522
+ consolidated_data.append(
523
+ {
524
+ "polarity_hash": polarity.hash,
525
+ "thesis_hash": thesis.hash,
526
+ "thesis_text": thesis.text,
527
+ "antithesis_hash": antithesis.hash,
528
+ "antithesis_text": antithesis.text,
529
+ "heuristic_similarity": pair.heuristic_similarity,
530
+ "existing": False,
531
+ "deduped": False,
532
+ "consolidated": True,
533
+ }
534
+ )
535
+ merged_hashes.add(thesis.hash)
536
+ merged_hashes.add(antithesis.hash)
537
+
538
+ self._report.artifacts["consolidated_pairs"] = len(consolidated_data)
539
+ if merged_count:
540
+ self._report.artifacts["created_polarity_count"] = (
541
+ self._report.artifacts.get("created_polarity_count", 0) + merged_count
542
+ )
543
+
544
+ reduced = [h for h in unique_hashes if h not in merged_hashes]
545
+ return reduced, consolidated_data
546
+
547
+ def _persist_mode_arousal(
548
+ self,
549
+ est_manager: EstimationManager,
550
+ antithesis: Statement,
551
+ mode_value: float,
552
+ arousal_value: float,
553
+ ) -> None:
554
+ """Persist Mode/Arousal estimations on the antithesis (mirrors IntroducePolarity)."""
555
+ mode_est = est_manager.upsert_estimation(
556
+ antithesis, ModeEstimation, mode_value
557
+ )
558
+ arousal_est = est_manager.upsert_estimation(
559
+ antithesis, ArousalEstimation, arousal_value
560
+ )
561
+ if mode_est:
562
+ self._report.node_updated(mode_est, patch={"value": mode_value})
563
+ if arousal_est:
564
+ self._report.node_updated(arousal_est, patch={"value": arousal_value})
565
+
427
566
  def _create_polarities(self, results: list[ThesisResult]) -> dict[tuple[str, str], str]:
428
567
  """Create Polarity nodes (T-A pairs) for each T-A pair.
429
568
 
@@ -461,37 +600,63 @@ class FindPolarities(ReasonableConcern[Optional[Ideas]]):
461
600
  continue
462
601
 
463
602
  # Create new Polarity (atomic creation)
464
- polarity = Polarity()
465
- polarity.set_t(result.thesis, heuristic_similarity=1.0)
466
- polarity.set_a(
467
- antithesis, heuristic_similarity=data["heuristic_similarity"]
603
+ polarity = self._build_polarity(
604
+ result.thesis, antithesis, data["heuristic_similarity"]
468
605
  )
469
- polarity.commit()
470
-
471
606
  polarity_map[(result.thesis.hash, data["hash"])] = polarity.hash
472
607
  created_count += 1
473
- self._report.node_created(
474
- polarity, meta={"hs": data["heuristic_similarity"]}
475
- )
476
- self._report.relationship_created(
477
- polarity.t, result.thesis, polarity,
478
- patch={"heuristic_similarity": 1.0, "alias": "T"},
479
- )
480
- self._report.relationship_created(
481
- polarity.a, antithesis, polarity,
482
- patch={"heuristic_similarity": data["heuristic_similarity"], "alias": "A"},
483
- )
484
608
 
485
- self._report.artifacts["created_polarity_count"] = created_count
609
+ # Accumulate — Phase 0 consolidation may already have created polarities.
610
+ self._report.artifacts["created_polarity_count"] = (
611
+ self._report.artifacts.get("created_polarity_count", 0) + created_count
612
+ )
486
613
  return polarity_map
487
614
 
488
- def _create_ideas(self, results: list[ThesisResult]) -> Optional[Ideas]:
489
- """Create Ideas node with all theses and their antitheses."""
615
+ def _build_polarity(
616
+ self,
617
+ thesis: Statement,
618
+ antithesis: Statement,
619
+ heuristic_similarity: float,
620
+ ) -> Polarity:
621
+ """Create and commit a Polarity from two committed Statements, recording effects.
622
+
623
+ Shared by regular polarity creation and antithetical-thesis consolidation.
624
+ T defines the apex (HS=1.0); the meaningful HS lives on A.
625
+ """
626
+ polarity = Polarity()
627
+ polarity.set_t(thesis, heuristic_similarity=1.0)
628
+ polarity.set_a(antithesis, heuristic_similarity=heuristic_similarity)
629
+ polarity.commit()
630
+
631
+ self._report.node_created(polarity, meta={"hs": heuristic_similarity})
632
+ self._report.relationship_created(
633
+ polarity.t, thesis, polarity,
634
+ patch={"heuristic_similarity": 1.0, "alias": "T"},
635
+ )
636
+ self._report.relationship_created(
637
+ polarity.a, antithesis, polarity,
638
+ patch={"heuristic_similarity": heuristic_similarity, "alias": "A"},
639
+ )
640
+ return polarity
641
+
642
+ def _create_ideas(
643
+ self,
644
+ results: list[ThesisResult],
645
+ consolidated_data: Optional[list[dict]] = None,
646
+ ) -> Optional[Ideas]:
647
+ """Create Ideas node with all theses and their antitheses.
648
+
649
+ Includes both the extracted T-A pairs (from ``results``) and the
650
+ consolidated antithetical pairs (from ``consolidated_data``), whose
651
+ theses were removed from the extraction set in Phase 0.
652
+ """
653
+ consolidated_data = consolidated_data or []
490
654
  valid_results = [r for r in results if not r.error and r.antithesis_data]
491
- if not valid_results:
655
+ if not valid_results and not consolidated_data:
492
656
  return None
493
657
 
494
658
  thesis_statements = [r.thesis.text for r in valid_results]
659
+ thesis_statements += [d["thesis_text"] for d in consolidated_data]
495
660
  intent = f"Tensions for: {', '.join(thesis_statements[:3])}"
496
661
  if len(thesis_statements) > 3:
497
662
  intent += f" (+{len(thesis_statements) - 3} more)"
@@ -508,33 +673,38 @@ class FindPolarities(ReasonableConcern[Optional[Ideas]]):
508
673
 
509
674
  # Connect all theses and antitheses (deduplicated across theses)
510
675
  connected_hashes: set[str] = set()
676
+
677
+ def _connect(hash: str) -> None:
678
+ if hash in connected_hashes:
679
+ return
680
+ comp = self._resolve_component(hash)
681
+ if comp:
682
+ connected_hashes.add(hash)
683
+ ideas.statements.connect(comp)
684
+ self._report.relationship_created(ideas.statements, ideas, comp)
685
+
511
686
  for result in valid_results:
512
- if result.thesis.hash not in connected_hashes:
513
- connected_hashes.add(result.thesis.hash)
514
- ideas.statements.connect(result.thesis)
515
- self._report.relationship_created(
516
- ideas.statements, ideas, result.thesis
517
- )
687
+ _connect(result.thesis.hash)
518
688
  for data in result.antithesis_data:
519
- if data["hash"] in connected_hashes:
520
- continue
521
- comp = self._resolve_component(data["hash"])
522
- if comp:
523
- connected_hashes.add(data["hash"])
524
- ideas.statements.connect(comp)
525
- self._report.relationship_created(
526
- ideas.statements, ideas, comp
527
- )
689
+ _connect(data["hash"])
690
+
691
+ # Consolidated pairs: both sides are theses the user supplied.
692
+ for data in consolidated_data:
693
+ _connect(data["thesis_hash"])
694
+ _connect(data["antithesis_hash"])
528
695
 
529
696
  ideas.commit()
530
697
  self._report.node_committed(ideas)
531
698
 
532
699
  # Add rationale
533
- total_theses = len(valid_results)
534
- total_antitheses = sum(len(r.antithesis_data) for r in valid_results)
700
+ total_theses = len(valid_results) + len(consolidated_data)
701
+ total_antitheses = sum(len(r.antithesis_data) for r in valid_results) + len(
702
+ consolidated_data
703
+ )
535
704
  all_hs = [
536
705
  d["heuristic_similarity"] for r in valid_results for d in r.antithesis_data
537
706
  ]
707
+ all_hs += [d["heuristic_similarity"] for d in consolidated_data]
538
708
  max_hs = max(all_hs) if all_hs else 0.0
539
709
 
540
710
  rationale = Rationale(
@@ -67,6 +67,43 @@ Always check resonance AFTER presenting results — but never before acting.
67
67
  When new tensions emerge from conversation:
68
68
  - Call `analyze` with `thesis_hashes` to develop them without re-processing everything.
69
69
 
70
+ When `find_polarities` merges antithetical theses (a `polarity_data` entry with
71
+ `consolidated: true`): two theses the user supplied were strong direct opposites,
72
+ so they were combined into one tension automatically. Briefly state that you did
73
+ this — e.g. "I treated X and Y as one tension since they're direct opposites; say
74
+ so if you'd rather explore them separately." Don't ask first, but make the merge
75
+ visible so the user can reverse it (`discard` the polarity and re-anchor them
76
+ apart) if the framing was wrong.
77
+
78
+ When `find_polarities` returns `consolidation_suggestions` (theses that may be
79
+ antitheses of each other but the opposition is only moderate): present the
80
+ suggested pair(s) to the user and ask whether the two are really one tension. If
81
+ they confirm, call `introduce_polarity` with that thesis/antithesis pair and
82
+ `discard` the now-redundant separate polarities. If they want the theses kept
83
+ apart, leave them as-is. (Strong opposites are merged automatically, so
84
+ suggestions are only the ambiguous middle ground — always confirm before merging.)
85
+
86
+ ## Reading Polarity Quality (HS)
87
+
88
+ `analyze` and `find_polarities` score every tension with an HS (heuristic
89
+ similarity) on its antithesis — how *genuine* the opposition is, not how good the
90
+ idea is. Use it to decide what to lead with; this is the reasoning that separates
91
+ you from a generic list of pros and cons.
92
+
93
+ - **≥0.7** — a strong, real opposition. Lead with these.
94
+ - **0.5-0.7** — a moderate or partial tension. Worth presenting, but frame it as secondary.
95
+ - **<0.5** — weak or tangential; the two sides barely oppose. Don't present it as a core tension.
96
+
97
+ `analyze` expands only the strongest tensions into full perspectives and sets the
98
+ rest aside — the report's `polarity_quality` artifact lists every tension with its
99
+ `hs` and an `expanded` flag, and the summary notes how many were set aside. When
100
+ tensions were set aside, briefly say stronger framings were prioritized and that
101
+ you can develop a weaker one on request (via `find_polarities`/`expand_polarities`
102
+ on that specific tension) — don't silently drop them.
103
+
104
+ Communicate quality as meaning ("a strong tension", "a weaker, more tangential
105
+ pull"), not raw numbers, unless the app preamble or the user asks for the figures.
106
+
70
107
  ## Exploration Setup (Nexus)
71
108
 
72
109
  When the user wants to explore interactions between perspectives:
@@ -15,7 +15,7 @@ They are injected by the host application at agent construction time.
15
15
 
16
16
  Prompt Revision Methodology
17
17
  ===========================
18
- When fixing LLM output bugs in these prompts, use /df:review-prompts for the
18
+ When fixing LLM output bugs in these prompts, use /df-review-reasoning-layer for the
19
19
  full diagnosis/fix/verify workflow.
20
20
 
21
21
  Quick reference: Diagnose root cause (polysemy | competing signals | missing
@@ -3,8 +3,6 @@ Ac-Re Taxonomy constants for Transformation generation.
3
3
 
4
4
  This module contains the scales, polar pairs, and apex target coordinates
5
5
  for the Action-Reflection dialectical structure.
6
-
7
- See docs/r&d/ac_re-taxonomy.md for full specification.
8
6
  """
9
7
 
10
8
  from __future__ import annotations
@@ -169,7 +169,7 @@ def arousal_label_to_value(label: str) -> float:
169
169
  class ContextualizedTaxonomyDto(BaseModel):
170
170
  """Contextualized universal taxonomy for a thesis.
171
171
 
172
- Structure (from docs/r&d/taxonomy-universal.md):
172
+ Structure:
173
173
  APEX: [T]-lessness
174
174
 
175
175
  ┌──────────────────┴──────────────────┐