dialectical-framework 1.6.0__tar.gz → 1.6.2__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.
- dialectical_framework-1.6.2/PKG-INFO +178 -0
- dialectical_framework-1.6.2/README.md +137 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/pyproject.toml +1 -1
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/advisor/system_prompts.py +14 -5
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/analyst/analyst.py +5 -1
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/analyst/skills/anchor_theses.py +20 -5
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/analyst/skills/find_polarities.py +1 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/analyst/skills/introduce_polarity.py +39 -13
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/analyst/skills/surface_theses.py +1 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/analyst/system_prompts.py +8 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/execution_report.py +14 -2
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/explorer/explorer.py +12 -5
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/explorer/system_prompts.py +54 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/orchestrator/tools/get_schema.py +2 -2
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/orchestrator/tools/inspect_node.py +11 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/orchestrator/tools/query_graph.py +4 -4
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/causality/causality_estimator.py +13 -1
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/causality/causality_estimator_balanced.py +119 -54
- dialectical_framework-1.6.2/src/dialectical_framework/concerns/causality/causality_estimator_criteria.py +35 -0
- dialectical_framework-1.6.2/src/dialectical_framework/concerns/causality/causality_estimator_desirable.py +13 -0
- dialectical_framework-1.6.2/src/dialectical_framework/concerns/causality/causality_estimator_feasible.py +13 -0
- dialectical_framework-1.6.2/src/dialectical_framework/concerns/causality/causality_estimator_realistic.py +13 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/causality_estimation.py +85 -24
- dialectical_framework-1.6.2/src/dialectical_framework/concerns/statement_headline.py +129 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/synthesis_generation.py +6 -2
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/thesis_extraction.py +18 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/transformation_generation.py +1 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/events/graph_event.py +1 -1
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/events/graph_event_bus.py +1 -1
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/repositories/node_repository.py +41 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/utils/dc_replace.py +5 -4
- dialectical_framework-1.6.0/PKG-INFO +0 -167
- dialectical_framework-1.6.0/README.md +0 -126
- dialectical_framework-1.6.0/src/dialectical_framework/concerns/causality/causality_estimator_criteria.py +0 -71
- dialectical_framework-1.6.0/src/dialectical_framework/concerns/causality/causality_estimator_desirable.py +0 -50
- dialectical_framework-1.6.0/src/dialectical_framework/concerns/causality/causality_estimator_feasible.py +0 -50
- dialectical_framework-1.6.0/src/dialectical_framework/concerns/causality/causality_estimator_realistic.py +0 -50
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/LICENSE +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/advisor/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/advisor/advisor.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/advisor/tools/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/advisor/tools/anchor.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/advisor/tools/explore.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/advisor/tools/ingest.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/advisor/tools/sync.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/agent_context.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/analyst/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/analyst/skills/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/analyst/skills/edit_perspective.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/analyst/skills/expand_polarities.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/analyst/tools/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/analyst/tools/create_dx_input.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/analyst/tools/place_statement.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/apps.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/conversation_facilitator.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/explorer/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/explorer/skills/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/explorer/skills/build_wheels.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/explorer/skills/explore_transformations.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/explorer/skills/generate_synthesis.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/explorer/tools/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/explorer/tools/create_nexus.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/explorer/tools/expand_nexus.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/explorer/tools/generate_synthesis.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/explorer/tools/present_exploration.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/orchestrator/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/orchestrator/tools/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/orchestrator/tools/add_input.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/orchestrator/tools/digest_input.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/orchestrator/tools/discard.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/orchestrator/tools/present_analysis.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/orchestrator/tools/read_digest.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/orchestrator/tools/read_input.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/reasonable_concern.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/agents/stream_events.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/ac_re_taxonomy.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/action_extraction.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/add_input.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/ai_dto/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/ai_dto/statement_dto.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/ai_dto/statements_deck_dto.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/antithesis_classification.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/antithesis_extraction.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/aspect_classification.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/aspect_generation.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/causality/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/causality/causality_normalizer.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/causality/estimator_resolver.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/control_statements_check.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/create_dx_input.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/create_nexus.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/diagonal_oppositions_check.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/dialectical_context.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/discard.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/display_text_edit.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/expand_nexus.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/perspective_combination.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/perspective_validation.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/positive_ac_re_apex_derivation.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/scoring_scales.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/source_digest.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/statement_classification.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/statement_deduplication.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/statement_placement.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/concerns/transformation_audit.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/dialectical_reasoning.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/enums/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/enums/causality_preset.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/enums/di.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/events/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/exceptions/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/exceptions/node_errors.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/exceptions/resolver_errors.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/composite_input_resolver.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/dialexity_input_resolver.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/estimation_manager.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/mixins/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/mixins/incremental_build_mixin.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/mixins/intent_mixin.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/mixins/persistable_mixin.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/nodes/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/nodes/assessable_entity.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/nodes/base_node.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/nodes/case.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/nodes/cycle.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/nodes/estimation.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/nodes/ideas.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/nodes/input.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/nodes/nexus.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/nodes/perspective.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/nodes/polarity.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/nodes/rationale.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/nodes/statement.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/nodes/synthesis.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/nodes/transformation.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/nodes/transition.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/nodes/wheel.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationship_manager.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/action_reflection_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/belongs_to_cycle_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/belongs_to_nexus_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/changed_to_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/contradiction_of_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/critiques_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/distilled_to_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/estimates_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/explains_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/has_input_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/has_statement_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/has_wheel_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/immutable_structure.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/is_source_of_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/is_target_of_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/negative_side_of_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/opposite_direction_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/opposite_of_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/polarity_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/positive_side_of_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/provides_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/relationships/synthesis_of_relationship.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/rendering.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/repositories/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/repositories/case_repository.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/repositories/cycle_repository.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/repositories/input_repository.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/repositories/nexus_repository.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/repositories/perspective_repository.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/repositories/polarity_repository.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/repositories/schema_repository.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/repositories/statement_repository.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/repositories/transformation_repository.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/repositories/wheel_repository.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/scope_context.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/verbatim_input_resolver.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/wheel_segment.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/graph/wheel_segment_polar_pair.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/protocols/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/protocols/has_config.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/protocols/input_resolver.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/settings.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/utils/__init__.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/utils/bedrock_provider.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/utils/concurrency.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/utils/decompose_probability_uniformly.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/utils/edge_context.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/utils/effect_logger.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/utils/input_context.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/utils/order_transitions.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/utils/sequence_generation.py +0 -0
- {dialectical_framework-1.6.0 → dialectical_framework-1.6.2}/src/dialectical_framework/utils/use_brain.py +0 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: dialectical-framework
|
|
3
|
+
Version: 1.6.2
|
|
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
|
+
License: MIT
|
|
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
|
|
7
|
+
Author: Evaldas Taroza
|
|
8
|
+
Author-email: evaldas@dialexity.com
|
|
9
|
+
Requires-Python: >=3.11,<4.0
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Framework :: Pydantic
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Education
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Natural Language :: English
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Topic :: Education
|
|
24
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
25
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
26
|
+
Classifier: Topic :: Scientific/Engineering :: Human Machine Interfaces
|
|
27
|
+
Classifier: Topic :: Sociology
|
|
28
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
29
|
+
Classifier: Topic :: Text Processing :: Linguistic
|
|
30
|
+
Requires-Dist: boto3 (>=1.43.4,<2.0.0)
|
|
31
|
+
Requires-Dist: broadcaster (>=0.3.1,<0.4.0)
|
|
32
|
+
Requires-Dist: dependency-injector (>=4.48.2,<5.0.0)
|
|
33
|
+
Requires-Dist: gqlalchemy (>=1.8.0,<2.0.0)
|
|
34
|
+
Requires-Dist: langfuse (>=4.5.1,<5.0.0)
|
|
35
|
+
Requires-Dist: mirascope[anthropic,openai,ops] (>=2.5.0,<3.0.0)
|
|
36
|
+
Requires-Dist: python-dotenv (>=1.2.1,<2.0.0)
|
|
37
|
+
Requires-Dist: tabulate (>=0.9.0,<0.10.0)
|
|
38
|
+
Project-URL: Homepage, https://github.com/dialexity/dialectical-framework
|
|
39
|
+
Project-URL: Repository, https://github.com/dialexity/dialectical-framework
|
|
40
|
+
Description-Content-Type: text/markdown
|
|
41
|
+
|
|
42
|
+
# Dialectical Framework
|
|
43
|
+
|
|
44
|
+
**Make an LLM reason in oppositions, not averages.**
|
|
45
|
+
|
|
46
|
+
Ask a model a hard question and it tends to collapse the tension into one confident answer — or hedge with a bland "on one hand… on the other." This framework does neither. For every thesis it generates a genuine antithesis, maps precisely where each side overreaches (T-, A-) and where it constructively balances the other (T+, A+), and drives the pair toward a **synthesis** — not a compromise, but a new quality that emerges from their circular causality and that neither pole held alone.
|
|
47
|
+
|
|
48
|
+
The reasoning lives in a graph. Every move — surfacing a thesis, finding its opposition, developing its four aspects, arranging them into a **Wheel** — writes semantic, rule-validated nodes and edges into a graph database. The graph **is** the state: a persistent, compounding map of how a domain's tensions resolve, that any application can query, visualize, or build on.
|
|
49
|
+
|
|
50
|
+
And the synthesis is *earned*, not asserted. Where "think step by step" leaves rigor to chance, formal generative rules define what counts as valid: exactly one antithesis per thesis, modality kept in balance, and positive synthesis (S+) only when T-'s excess transforms into A+ and A-'s into T+. The structure enforces a discipline the prompt alone can't.
|
|
51
|
+
|
|
52
|
+
## Learn More
|
|
53
|
+
- [Structured Dialectics](https://dialexity.com/blog/structured-dialectics-consolidated-manuscript/) - the theory
|
|
54
|
+
- [Dialectical Wheels for Systems Optimization](https://dialexity.com/blog/dialectical-wheels-for-systems-optimization/)
|
|
55
|
+
- [Dialectical Ethics](https://dialexity.com/blog/dialectical-ethics/)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
## How It Works
|
|
59
|
+
|
|
60
|
+
1. **Input** — text, URLs, or raw ideas from any domain
|
|
61
|
+
2. **Analysis** — extract the theses, find each one's true antithesis, develop the four aspects (T+, T-, A+, A-) that say where each side helps and where it overreaches
|
|
62
|
+
3. **Graph curation** — commit every insight as content-addressed, rule-validated nodes and edges — nothing is stored until it holds up
|
|
63
|
+
4. **Exploration** — combine perspectives into Cycles, arrange them into Wheels, and trace the Transformations whose circular causality yields synthesis
|
|
64
|
+
|
|
65
|
+
Each pass leaves the graph richer than it found it: new tensions enter an existing web of validated reasoning, so understanding compounds instead of resetting every prompt.
|
|
66
|
+
|
|
67
|
+
## Architecture
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
Host Application (Chainlit, API, CLI)
|
|
71
|
+
│
|
|
72
|
+
▼
|
|
73
|
+
Agent: Analyst · Explorer · Advisor (LLM + tools)
|
|
74
|
+
│
|
|
75
|
+
▼
|
|
76
|
+
Graph Database (Memgraph / Neo4j)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
An **agent** is the entry point — a thin LLM orchestrator that manages a conversation with tools that read and write the graph. There are three (Analyst, Explorer, Advisor); each owns a tool set and a domain-neutral reasoning prompt. The host app controls persona (via the app preamble) and scope identity (`sid`); the framework handles reasoning and graph curation. See [docs/agents.md](docs/agents.md).
|
|
80
|
+
|
|
81
|
+
### Docs
|
|
82
|
+
- [Agents: Analyst, Explorer, Advisor](docs/agents.md) — the building blocks, their tools, and the UX to build around them
|
|
83
|
+
- [Graph Data Model](docs/graph.md)
|
|
84
|
+
- [Scoring & Metrics](docs/scoring.md)
|
|
85
|
+
|
|
86
|
+
## Why a Reasoning Graph
|
|
87
|
+
|
|
88
|
+
Most AI systems treat knowledge as flat context — dump text into the prompt and hope the LLM figures out the structure. The dialectical framework builds a **persistent reasoning graph** where the structure itself encodes how to think about a domain:
|
|
89
|
+
|
|
90
|
+
- **Oppositions are explicit.** The LLM doesn't rediscover the tensions on every call — they persist as typed T/A pairs, so reasoning starts from a mapped conflict instead of a blank page.
|
|
91
|
+
- **Transformations encode causality.** Edges don't just connect — they show how one position's failure becomes another's strength. This is the circular causality that drives synthesis.
|
|
92
|
+
- **Quality is measurable.** Complementarity, modality balance, area metrics tell the LLM which reasoning paths are well-developed and which are thin — no guessing about confidence.
|
|
93
|
+
- **Knowledge compounds.** Each new perspective enters an existing graph of validated reasoning. The LLM builds on prior synthesis rather than re-deriving from scratch.
|
|
94
|
+
|
|
95
|
+
The result: an LLM with this graph in context doesn't just have facts about a topic — it has the intellectual terrain mapped. What opposes what, where balance was achieved, what assumptions remain untested, and where synthesis is possible.
|
|
96
|
+
|
|
97
|
+
This is the [LLM Wiki](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f) pattern realized as a semantic graph rather than a pile of markdown files — knowledge that is structured, rule-validated, and queryable by reasoning topology.
|
|
98
|
+
|
|
99
|
+
| Simple | Detailed |
|
|
100
|
+
|--------|----------|
|
|
101
|
+
|  |  |
|
|
102
|
+
|
|
103
|
+
## Core Graph Structure
|
|
104
|
+
|
|
105
|
+
It's all one graph. **Statements** are the atoms; typed edges carry the dialectical relationships — opposition, complementarity, transformation — and each structure below composes the ones above it into progressively richer reasoning, culminating in the **Dialectical Wheel**.
|
|
106
|
+
|
|
107
|
+
| Structure | Role |
|
|
108
|
+
|-----------|------|
|
|
109
|
+
| **Statement** | Atomic unit of meaning — a thesis, position, or claim |
|
|
110
|
+
| **Polarity** | A single T↔A tension (thesis vs. antithesis); reusable across perspectives |
|
|
111
|
+
| **Perspective** | A full tetrad — a Polarity developed with its four aspects (T+, T-, A+, A-) |
|
|
112
|
+
| **Nexus** | A working set of Perspectives grouped for exploration |
|
|
113
|
+
| **Cycle** | An ordered sequence of Perspectives — which tension drives which |
|
|
114
|
+
| **Wheel** | A concrete circular arrangement of a Cycle, with the edges between components |
|
|
115
|
+
| **Transition** | A directed edge between two components — one step around the Wheel |
|
|
116
|
+
| **Transformation** | The Action-Reflection paths on an edge that turn one pole's excess into the other's strength |
|
|
117
|
+
| **Synthesis** | The emergent S+/S- arising from the whole Wheel's circular causality |
|
|
118
|
+
|
|
119
|
+
Picture the Wheel as a pizza sliced into segments: each **segment** bundles a component with its plus and minus (e.g. T, T+, T-), a **Perspective** joins a thesis segment with the antithesis segment directly across from it, and **Transitions** are the arrows running segment to segment around the rim.
|
|
120
|
+
|
|
121
|
+
## Integration
|
|
122
|
+
|
|
123
|
+
Wherever the answer is a tension rather than a fact, this drops in as the reasoning engine: decision support that weighs both sides, systems thinking, mediation between opposed positions, ethical modeling. You wire it into your app through three conversational agents — the main building blocks:
|
|
124
|
+
|
|
125
|
+
- **Analyst** — turns raw material into structured tensions, up to grouping them into a Nexus (Case-scoped).
|
|
126
|
+
- **Explorer** — takes one Nexus and works out its causal pathways and synthesis (Nexus-scoped).
|
|
127
|
+
- **Advisor** — runs the whole machine silently and returns pure counsel, with no framework vocabulary exposed (Case-scoped).
|
|
128
|
+
|
|
129
|
+
Analyst + Explorer are the structure-forward "graph navigator" experience; the Advisor is a chat-only product over the same graph. See [docs/agents.md](docs/agents.md) for full specs, tool lists, and the UX to build around each.
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from dialectical_framework.dialectical_reasoning import DialecticalReasoning
|
|
133
|
+
from dialectical_framework.settings import Settings
|
|
134
|
+
from dialectical_framework.graph.nodes.case import Case
|
|
135
|
+
from dialectical_framework.graph.scope_context import scope
|
|
136
|
+
from dialectical_framework.agents.advisor.advisor import Advisor
|
|
137
|
+
|
|
138
|
+
# Initialize once
|
|
139
|
+
DialecticalReasoning.setup(Settings.from_env())
|
|
140
|
+
|
|
141
|
+
# A Case owns the scope id (sid); all graph writes are sid-scoped.
|
|
142
|
+
case = Case(); case.commit()
|
|
143
|
+
|
|
144
|
+
with scope(case.sid):
|
|
145
|
+
advisor = Advisor(app_preamble="You are a systems thinking coach...")
|
|
146
|
+
async for event in advisor.chat_stream("Analyze the tension between growth and sustainability"):
|
|
147
|
+
# ThinkingDelta, TextDelta, ToolStart, ToolResult, ResponseComplete
|
|
148
|
+
handle(event)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Setup
|
|
152
|
+
|
|
153
|
+
### Requirements
|
|
154
|
+
|
|
155
|
+
- Python 3.11+
|
|
156
|
+
- Memgraph or Neo4j
|
|
157
|
+
- An LLM provider (OpenAI, Anthropic, or Bedrock via a custom Mirascope provider)
|
|
158
|
+
|
|
159
|
+
### Install
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
poetry install
|
|
163
|
+
cp .env.example .env # then fill in the values (see .env.example for details)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Run Tests
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
poetry run pytest # All tests (LLM mocked)
|
|
170
|
+
poetry run pytest -m llm # Only LLM-path tests (mocked)
|
|
171
|
+
poetry run pytest --real-llm # Hit real LLM provider
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Built With
|
|
175
|
+
|
|
176
|
+
- [Mirascope](https://mirascope.com/) — LLM abstraction
|
|
177
|
+
- [GQLAlchemy](https://memgraph.com/docs/gqlalchemy) — Graph ORM
|
|
178
|
+
- [dependency-injector](https://python-dependency-injector.ets-labs.org/) — DI container
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Dialectical Framework
|
|
2
|
+
|
|
3
|
+
**Make an LLM reason in oppositions, not averages.**
|
|
4
|
+
|
|
5
|
+
Ask a model a hard question and it tends to collapse the tension into one confident answer — or hedge with a bland "on one hand… on the other." This framework does neither. For every thesis it generates a genuine antithesis, maps precisely where each side overreaches (T-, A-) and where it constructively balances the other (T+, A+), and drives the pair toward a **synthesis** — not a compromise, but a new quality that emerges from their circular causality and that neither pole held alone.
|
|
6
|
+
|
|
7
|
+
The reasoning lives in a graph. Every move — surfacing a thesis, finding its opposition, developing its four aspects, arranging them into a **Wheel** — writes semantic, rule-validated nodes and edges into a graph database. The graph **is** the state: a persistent, compounding map of how a domain's tensions resolve, that any application can query, visualize, or build on.
|
|
8
|
+
|
|
9
|
+
And the synthesis is *earned*, not asserted. Where "think step by step" leaves rigor to chance, formal generative rules define what counts as valid: exactly one antithesis per thesis, modality kept in balance, and positive synthesis (S+) only when T-'s excess transforms into A+ and A-'s into T+. The structure enforces a discipline the prompt alone can't.
|
|
10
|
+
|
|
11
|
+
## Learn More
|
|
12
|
+
- [Structured Dialectics](https://dialexity.com/blog/structured-dialectics-consolidated-manuscript/) - the theory
|
|
13
|
+
- [Dialectical Wheels for Systems Optimization](https://dialexity.com/blog/dialectical-wheels-for-systems-optimization/)
|
|
14
|
+
- [Dialectical Ethics](https://dialexity.com/blog/dialectical-ethics/)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## How It Works
|
|
18
|
+
|
|
19
|
+
1. **Input** — text, URLs, or raw ideas from any domain
|
|
20
|
+
2. **Analysis** — extract the theses, find each one's true antithesis, develop the four aspects (T+, T-, A+, A-) that say where each side helps and where it overreaches
|
|
21
|
+
3. **Graph curation** — commit every insight as content-addressed, rule-validated nodes and edges — nothing is stored until it holds up
|
|
22
|
+
4. **Exploration** — combine perspectives into Cycles, arrange them into Wheels, and trace the Transformations whose circular causality yields synthesis
|
|
23
|
+
|
|
24
|
+
Each pass leaves the graph richer than it found it: new tensions enter an existing web of validated reasoning, so understanding compounds instead of resetting every prompt.
|
|
25
|
+
|
|
26
|
+
## Architecture
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
Host Application (Chainlit, API, CLI)
|
|
30
|
+
│
|
|
31
|
+
▼
|
|
32
|
+
Agent: Analyst · Explorer · Advisor (LLM + tools)
|
|
33
|
+
│
|
|
34
|
+
▼
|
|
35
|
+
Graph Database (Memgraph / Neo4j)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
An **agent** is the entry point — a thin LLM orchestrator that manages a conversation with tools that read and write the graph. There are three (Analyst, Explorer, Advisor); each owns a tool set and a domain-neutral reasoning prompt. The host app controls persona (via the app preamble) and scope identity (`sid`); the framework handles reasoning and graph curation. See [docs/agents.md](docs/agents.md).
|
|
39
|
+
|
|
40
|
+
### Docs
|
|
41
|
+
- [Agents: Analyst, Explorer, Advisor](docs/agents.md) — the building blocks, their tools, and the UX to build around them
|
|
42
|
+
- [Graph Data Model](docs/graph.md)
|
|
43
|
+
- [Scoring & Metrics](docs/scoring.md)
|
|
44
|
+
|
|
45
|
+
## Why a Reasoning Graph
|
|
46
|
+
|
|
47
|
+
Most AI systems treat knowledge as flat context — dump text into the prompt and hope the LLM figures out the structure. The dialectical framework builds a **persistent reasoning graph** where the structure itself encodes how to think about a domain:
|
|
48
|
+
|
|
49
|
+
- **Oppositions are explicit.** The LLM doesn't rediscover the tensions on every call — they persist as typed T/A pairs, so reasoning starts from a mapped conflict instead of a blank page.
|
|
50
|
+
- **Transformations encode causality.** Edges don't just connect — they show how one position's failure becomes another's strength. This is the circular causality that drives synthesis.
|
|
51
|
+
- **Quality is measurable.** Complementarity, modality balance, area metrics tell the LLM which reasoning paths are well-developed and which are thin — no guessing about confidence.
|
|
52
|
+
- **Knowledge compounds.** Each new perspective enters an existing graph of validated reasoning. The LLM builds on prior synthesis rather than re-deriving from scratch.
|
|
53
|
+
|
|
54
|
+
The result: an LLM with this graph in context doesn't just have facts about a topic — it has the intellectual terrain mapped. What opposes what, where balance was achieved, what assumptions remain untested, and where synthesis is possible.
|
|
55
|
+
|
|
56
|
+
This is the [LLM Wiki](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f) pattern realized as a semantic graph rather than a pile of markdown files — knowledge that is structured, rule-validated, and queryable by reasoning topology.
|
|
57
|
+
|
|
58
|
+
| Simple | Detailed |
|
|
59
|
+
|--------|----------|
|
|
60
|
+
|  |  |
|
|
61
|
+
|
|
62
|
+
## Core Graph Structure
|
|
63
|
+
|
|
64
|
+
It's all one graph. **Statements** are the atoms; typed edges carry the dialectical relationships — opposition, complementarity, transformation — and each structure below composes the ones above it into progressively richer reasoning, culminating in the **Dialectical Wheel**.
|
|
65
|
+
|
|
66
|
+
| Structure | Role |
|
|
67
|
+
|-----------|------|
|
|
68
|
+
| **Statement** | Atomic unit of meaning — a thesis, position, or claim |
|
|
69
|
+
| **Polarity** | A single T↔A tension (thesis vs. antithesis); reusable across perspectives |
|
|
70
|
+
| **Perspective** | A full tetrad — a Polarity developed with its four aspects (T+, T-, A+, A-) |
|
|
71
|
+
| **Nexus** | A working set of Perspectives grouped for exploration |
|
|
72
|
+
| **Cycle** | An ordered sequence of Perspectives — which tension drives which |
|
|
73
|
+
| **Wheel** | A concrete circular arrangement of a Cycle, with the edges between components |
|
|
74
|
+
| **Transition** | A directed edge between two components — one step around the Wheel |
|
|
75
|
+
| **Transformation** | The Action-Reflection paths on an edge that turn one pole's excess into the other's strength |
|
|
76
|
+
| **Synthesis** | The emergent S+/S- arising from the whole Wheel's circular causality |
|
|
77
|
+
|
|
78
|
+
Picture the Wheel as a pizza sliced into segments: each **segment** bundles a component with its plus and minus (e.g. T, T+, T-), a **Perspective** joins a thesis segment with the antithesis segment directly across from it, and **Transitions** are the arrows running segment to segment around the rim.
|
|
79
|
+
|
|
80
|
+
## Integration
|
|
81
|
+
|
|
82
|
+
Wherever the answer is a tension rather than a fact, this drops in as the reasoning engine: decision support that weighs both sides, systems thinking, mediation between opposed positions, ethical modeling. You wire it into your app through three conversational agents — the main building blocks:
|
|
83
|
+
|
|
84
|
+
- **Analyst** — turns raw material into structured tensions, up to grouping them into a Nexus (Case-scoped).
|
|
85
|
+
- **Explorer** — takes one Nexus and works out its causal pathways and synthesis (Nexus-scoped).
|
|
86
|
+
- **Advisor** — runs the whole machine silently and returns pure counsel, with no framework vocabulary exposed (Case-scoped).
|
|
87
|
+
|
|
88
|
+
Analyst + Explorer are the structure-forward "graph navigator" experience; the Advisor is a chat-only product over the same graph. See [docs/agents.md](docs/agents.md) for full specs, tool lists, and the UX to build around each.
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from dialectical_framework.dialectical_reasoning import DialecticalReasoning
|
|
92
|
+
from dialectical_framework.settings import Settings
|
|
93
|
+
from dialectical_framework.graph.nodes.case import Case
|
|
94
|
+
from dialectical_framework.graph.scope_context import scope
|
|
95
|
+
from dialectical_framework.agents.advisor.advisor import Advisor
|
|
96
|
+
|
|
97
|
+
# Initialize once
|
|
98
|
+
DialecticalReasoning.setup(Settings.from_env())
|
|
99
|
+
|
|
100
|
+
# A Case owns the scope id (sid); all graph writes are sid-scoped.
|
|
101
|
+
case = Case(); case.commit()
|
|
102
|
+
|
|
103
|
+
with scope(case.sid):
|
|
104
|
+
advisor = Advisor(app_preamble="You are a systems thinking coach...")
|
|
105
|
+
async for event in advisor.chat_stream("Analyze the tension between growth and sustainability"):
|
|
106
|
+
# ThinkingDelta, TextDelta, ToolStart, ToolResult, ResponseComplete
|
|
107
|
+
handle(event)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Setup
|
|
111
|
+
|
|
112
|
+
### Requirements
|
|
113
|
+
|
|
114
|
+
- Python 3.11+
|
|
115
|
+
- Memgraph or Neo4j
|
|
116
|
+
- An LLM provider (OpenAI, Anthropic, or Bedrock via a custom Mirascope provider)
|
|
117
|
+
|
|
118
|
+
### Install
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
poetry install
|
|
122
|
+
cp .env.example .env # then fill in the values (see .env.example for details)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Run Tests
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
poetry run pytest # All tests (LLM mocked)
|
|
129
|
+
poetry run pytest -m llm # Only LLM-path tests (mocked)
|
|
130
|
+
poetry run pytest --real-llm # Hit real LLM provider
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Built With
|
|
134
|
+
|
|
135
|
+
- [Mirascope](https://mirascope.com/) — LLM abstraction
|
|
136
|
+
- [GQLAlchemy](https://memgraph.com/docs/gqlalchemy) — Graph ORM
|
|
137
|
+
- [dependency-injector](https://python-dependency-injector.ets-labs.org/) — DI container
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "dialectical-framework"
|
|
3
|
-
version = "1.6.
|
|
3
|
+
version = "1.6.2"
|
|
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"
|
|
@@ -136,11 +136,13 @@ Seven tools. Use silently — never mention them.
|
|
|
136
136
|
|
|
137
137
|
- `ingest` — Processes raw material (text, files, transcripts) through
|
|
138
138
|
dialectical analysis: extracts theses, finds oppositions, builds full
|
|
139
|
-
perspectives with aspects. Use
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
139
|
+
perspectives with aspects. Use for open-ended material where no single
|
|
140
|
+
position is yet articulated and the tensions must be discovered — compose
|
|
141
|
+
the `text` parameter from what they've shared. When the person has already
|
|
142
|
+
named a clear position (or an explicit either/or), prefer `anchor` — it is
|
|
143
|
+
more reliable than extraction. Do NOT ingest greetings or small talk. When
|
|
144
|
+
pre-loaded sources exist (shown in the dump under Sources), call ingest with
|
|
145
|
+
just an `intent` to extract tensions from them without new text.
|
|
144
146
|
|
|
145
147
|
- `anchor` — Plants a specific tension from the conversation. More precise
|
|
146
148
|
than ingest; use when you can see at least the person's position. Two modes:
|
|
@@ -215,6 +217,13 @@ should reflect what resonates — retract what doesn't.
|
|
|
215
217
|
4. `explore` → respond with specific paired pathways
|
|
216
218
|
5. Continue with full depth, offer integration vision when they're ready
|
|
217
219
|
|
|
220
|
+
**When a tool surfaces no tensions:** If `ingest` returns nothing (no
|
|
221
|
+
perspectives in its result), the material resisted automatic extraction — this
|
|
222
|
+
is a signal to `anchor` directly, not to fall back to unstructured discussion.
|
|
223
|
+
Name the position you heard and the force that opposes it, and `anchor` that
|
|
224
|
+
tension before responding. Only proceed on your own judgement if you genuinely
|
|
225
|
+
cannot identify any opposition in what they've shared.
|
|
226
|
+
|
|
218
227
|
## What You Must Never Do
|
|
219
228
|
|
|
220
229
|
- Reveal tools or internal processes
|
|
@@ -261,7 +261,11 @@ class AnalysisPipeline(ReasonableConcern[AnalysisResult]):
|
|
|
261
261
|
|
|
262
262
|
if not thesis_hashes:
|
|
263
263
|
self._report.ok = True
|
|
264
|
-
self._report.summary =
|
|
264
|
+
self._report.summary = (
|
|
265
|
+
"No tensions extracted from this material. Anchor an "
|
|
266
|
+
"explicit position (and its opposition, if visible) "
|
|
267
|
+
"instead of ingesting."
|
|
268
|
+
)
|
|
265
269
|
return AnalysisResult(
|
|
266
270
|
ideas_hash=ideas_hash, errors=errors, reports=reports
|
|
267
271
|
)
|
|
@@ -21,6 +21,7 @@ from pydantic import Field
|
|
|
21
21
|
from dialectical_framework.agents.reasonable_concern import ReasonableConcern
|
|
22
22
|
from dialectical_framework.concerns.statement_classification import (
|
|
23
23
|
ClassificationResult, StatementClassification)
|
|
24
|
+
from dialectical_framework.concerns.statement_headline import StatementHeadline
|
|
24
25
|
from dialectical_framework.enums.di import DI
|
|
25
26
|
from dialectical_framework.graph.nodes.ideas import Ideas
|
|
26
27
|
from dialectical_framework.graph.nodes.rationale import Rationale
|
|
@@ -83,7 +84,11 @@ class AnchorTheses(ReasonableConcern[Optional[Ideas]]):
|
|
|
83
84
|
statements: list[str],
|
|
84
85
|
text: str = "",
|
|
85
86
|
) -> list[Statement]:
|
|
87
|
+
# Condense in parallel with classification. The agent may hand this skill
|
|
88
|
+
# verbose prose (there is no extraction step to clamp length), so the
|
|
89
|
+
# stored text becomes a headline while classification reads the full text.
|
|
86
90
|
classifiers = [StatementClassification() for _ in statements]
|
|
91
|
+
headliners = [StatementHeadline() for _ in statements]
|
|
87
92
|
tasks = [
|
|
88
93
|
classifier.resolve(
|
|
89
94
|
statement=stmt,
|
|
@@ -92,25 +97,35 @@ class AnchorTheses(ReasonableConcern[Optional[Ideas]]):
|
|
|
92
97
|
)
|
|
93
98
|
for classifier, stmt in zip(classifiers, statements)
|
|
94
99
|
]
|
|
100
|
+
headline_tasks = [
|
|
101
|
+
headliner.resolve(statement=stmt, text=text)
|
|
102
|
+
for headliner, stmt in zip(headliners, statements)
|
|
103
|
+
]
|
|
95
104
|
|
|
96
105
|
results: list[ClassificationResult] = await asyncio.gather(*tasks)
|
|
106
|
+
headlines: list[str] = await asyncio.gather(*headline_tasks)
|
|
97
107
|
|
|
98
108
|
components: list[Statement] = []
|
|
99
|
-
for classifier, result in zip(
|
|
100
|
-
|
|
109
|
+
for classifier, headliner, result, headline in zip(
|
|
110
|
+
classifiers, headliners, results, headlines
|
|
111
|
+
):
|
|
112
|
+
component = self._create_component(result, headline)
|
|
101
113
|
components.append(component)
|
|
102
114
|
self._report = self._report.merge(classifier.report)
|
|
115
|
+
self._report = self._report.merge(headliner.report)
|
|
103
116
|
|
|
104
117
|
return components
|
|
105
118
|
|
|
106
|
-
def _create_component(
|
|
107
|
-
|
|
119
|
+
def _create_component(
|
|
120
|
+
self, result: ClassificationResult, headline: str
|
|
121
|
+
) -> Statement:
|
|
122
|
+
component = Statement(text=headline, meaning=result.meaning)
|
|
108
123
|
component.commit()
|
|
109
124
|
|
|
110
125
|
classification_label = "SIMPLE" if result.is_simple else "COMPLEX"
|
|
111
126
|
self._report.node_created(
|
|
112
127
|
component,
|
|
113
|
-
patch={"meaning": result.meaning, "text":
|
|
128
|
+
patch={"meaning": result.meaning, "text": headline},
|
|
114
129
|
meta={"classification": classification_label},
|
|
115
130
|
)
|
|
116
131
|
|
|
@@ -178,6 +178,7 @@ class FindPolarities(ReasonableConcern[Optional[Ideas]]):
|
|
|
178
178
|
vocabulary=dedup_vocab,
|
|
179
179
|
text=input_text,
|
|
180
180
|
)
|
|
181
|
+
self._report = self._report.merge(deduplicator.report)
|
|
181
182
|
|
|
182
183
|
# Reconnect OPPOSITE_OF: thesis -> DB version for replacements
|
|
183
184
|
self._reconnect_oppositions(results, dedup_result)
|
|
@@ -18,6 +18,7 @@ Usage:
|
|
|
18
18
|
|
|
19
19
|
from __future__ import annotations
|
|
20
20
|
|
|
21
|
+
import asyncio
|
|
21
22
|
from dataclasses import dataclass
|
|
22
23
|
from typing import TYPE_CHECKING, Annotated, Optional
|
|
23
24
|
|
|
@@ -26,17 +27,18 @@ from mirascope import llm
|
|
|
26
27
|
from pydantic import Field
|
|
27
28
|
|
|
28
29
|
from dialectical_framework.agents.reasonable_concern import ReasonableConcern
|
|
29
|
-
from dialectical_framework.enums.di import DI
|
|
30
30
|
from dialectical_framework.concerns.antithesis_classification import \
|
|
31
31
|
AntithesisClassification
|
|
32
32
|
from dialectical_framework.concerns.statement_classification import \
|
|
33
33
|
StatementClassification
|
|
34
|
+
from dialectical_framework.concerns.statement_headline import StatementHeadline
|
|
35
|
+
from dialectical_framework.enums.di import DI
|
|
34
36
|
from dialectical_framework.graph.estimation_manager import EstimationManager
|
|
35
|
-
from dialectical_framework.graph.nodes.estimation import (
|
|
36
|
-
|
|
37
|
-
from dialectical_framework.graph.nodes.statement import Statement
|
|
37
|
+
from dialectical_framework.graph.nodes.estimation import (ArousalEstimation,
|
|
38
|
+
ModeEstimation)
|
|
38
39
|
from dialectical_framework.graph.nodes.polarity import Polarity
|
|
39
40
|
from dialectical_framework.graph.nodes.rationale import Rationale
|
|
41
|
+
from dialectical_framework.graph.nodes.statement import Statement
|
|
40
42
|
from dialectical_framework.graph.repositories.input_repository import \
|
|
41
43
|
InputRepository
|
|
42
44
|
from dialectical_framework.graph.repositories.polarity_repository import \
|
|
@@ -117,12 +119,19 @@ class IntroducePolarity(ReasonableConcern[IntroducePolarityResult]):
|
|
|
117
119
|
primary_polarity.commit()
|
|
118
120
|
self._report.node_created(primary_polarity)
|
|
119
121
|
self._report.relationship_created(
|
|
120
|
-
primary_polarity.t,
|
|
122
|
+
primary_polarity.t,
|
|
123
|
+
thesis_stmt,
|
|
124
|
+
primary_polarity,
|
|
121
125
|
patch={"heuristic_similarity": 1.0, "alias": "T"},
|
|
122
126
|
)
|
|
123
127
|
self._report.relationship_created(
|
|
124
|
-
primary_polarity.a,
|
|
125
|
-
|
|
128
|
+
primary_polarity.a,
|
|
129
|
+
antithesis_stmt,
|
|
130
|
+
primary_polarity,
|
|
131
|
+
patch={
|
|
132
|
+
"heuristic_similarity": classification.heuristic_similarity,
|
|
133
|
+
"alias": "A",
|
|
134
|
+
},
|
|
126
135
|
)
|
|
127
136
|
self._report.artifacts["primary_polarity_source"] = "created"
|
|
128
137
|
|
|
@@ -135,9 +144,13 @@ class IntroducePolarity(ReasonableConcern[IntroducePolarityResult]):
|
|
|
135
144
|
antithesis_stmt, ArousalEstimation, classification.arousal_value
|
|
136
145
|
)
|
|
137
146
|
if mode_est:
|
|
138
|
-
self._report.node_updated(
|
|
147
|
+
self._report.node_updated(
|
|
148
|
+
mode_est, patch={"value": classification.mode_value}
|
|
149
|
+
)
|
|
139
150
|
if arousal_est:
|
|
140
|
-
self._report.node_updated(
|
|
151
|
+
self._report.node_updated(
|
|
152
|
+
arousal_est, patch={"value": classification.arousal_value}
|
|
153
|
+
)
|
|
141
154
|
|
|
142
155
|
# Build result
|
|
143
156
|
result = IntroducePolarityResult(
|
|
@@ -166,12 +179,23 @@ class IntroducePolarity(ReasonableConcern[IntroducePolarityResult]):
|
|
|
166
179
|
return result
|
|
167
180
|
|
|
168
181
|
async def _resolve_statement(self, text: str, context: str) -> Statement:
|
|
169
|
-
"""Classify and commit a Statement. Commit is an upsert — same text reuses existing node.
|
|
182
|
+
"""Classify and commit a Statement. Commit is an upsert — same text reuses existing node.
|
|
183
|
+
|
|
184
|
+
The agent may pass verbose prose (the anchor path has no extraction step
|
|
185
|
+
to clamp length), so condense to a headline in parallel with
|
|
186
|
+
classification. Classification reads the full text for richer taxonomy
|
|
187
|
+
anchoring; only the stored ``text`` becomes the headline.
|
|
188
|
+
"""
|
|
170
189
|
classifier = StatementClassification()
|
|
171
|
-
|
|
190
|
+
headliner = StatementHeadline()
|
|
191
|
+
result, headline = await asyncio.gather(
|
|
192
|
+
classifier.resolve(statement=text, text=context),
|
|
193
|
+
headliner.resolve(statement=text, text=context),
|
|
194
|
+
)
|
|
172
195
|
self._report = self._report.merge(classifier.report)
|
|
196
|
+
self._report = self._report.merge(headliner.report)
|
|
173
197
|
|
|
174
|
-
stmt = Statement(text=
|
|
198
|
+
stmt = Statement(text=headline, meaning=result.meaning)
|
|
175
199
|
stmt.commit()
|
|
176
200
|
self._report.node_created(stmt)
|
|
177
201
|
|
|
@@ -207,7 +231,9 @@ class IntroducePolarity(ReasonableConcern[IntroducePolarityResult]):
|
|
|
207
231
|
async def introduce_polarity(
|
|
208
232
|
thesis: Annotated[str, Field(description="The thesis statement text")],
|
|
209
233
|
antithesis: Annotated[str, Field(description="The antithesis statement text")],
|
|
210
|
-
text: Annotated[
|
|
234
|
+
text: Annotated[
|
|
235
|
+
str, Field(description="Additional context for classification")
|
|
236
|
+
] = "",
|
|
211
237
|
) -> str:
|
|
212
238
|
"""Introduce a known thesis-antithesis tension directly as a Polarity. Classifies both statements, creates the Polarity node (T-A pair) with HS score. Use when the tension is already clear from conversation rather than needing extraction from source material."""
|
|
213
239
|
concern = IntroducePolarity(thesis=thesis, antithesis=antithesis, text=text)
|
|
@@ -157,6 +157,7 @@ class SurfaceTheses(ReasonableConcern[Optional[Ideas]]):
|
|
|
157
157
|
vocabulary=vocab,
|
|
158
158
|
text=input_text,
|
|
159
159
|
)
|
|
160
|
+
self._report = self._report.merge(deduplicator.report)
|
|
160
161
|
deleted_count = dedup_result.deleted_count
|
|
161
162
|
deduped = dedup_result.components
|
|
162
163
|
else:
|
|
@@ -77,6 +77,14 @@ When the user wants to explore interactions between perspectives:
|
|
|
77
77
|
Only create separate if user deliberately wants a different scope.
|
|
78
78
|
3. Confirm the exploration direction with the user before creating.
|
|
79
79
|
|
|
80
|
+
**Grouping (which perspectives to combine):**
|
|
81
|
+
- Prefer perspectives from different polarities (different T-A oppositions). Transformations
|
|
82
|
+
between different oppositions are genuine synthesis with opponents — the richest exploration.
|
|
83
|
+
- Same-polarity grouping is still valid when it fits the intent or the user asks for it.
|
|
84
|
+
It produces "angle shifts" (reframing within one opposition) rather than cross-opposition
|
|
85
|
+
synthesis — note that tradeoff so the user knows what they'll get. Never refuse or override
|
|
86
|
+
an explicit same-polarity request.
|
|
87
|
+
|
|
80
88
|
**Intent (internal quality gate — do not surface to user):**
|
|
81
89
|
- Must be specific: what the user wants to understand or navigate.
|
|
82
90
|
- Refine vague requests ("explore this") into purposeful intents internally.
|
|
@@ -37,7 +37,9 @@ if TYPE_CHECKING:
|
|
|
37
37
|
from dialectical_framework.events.graph_event_bus import GraphEventBus
|
|
38
38
|
from dialectical_framework.graph.nodes.base_node import BaseNode
|
|
39
39
|
from dialectical_framework.graph.relationship_manager import (
|
|
40
|
-
BoundRelationshipManager,
|
|
40
|
+
BoundRelationshipManager,
|
|
41
|
+
RelationshipManager,
|
|
42
|
+
)
|
|
41
43
|
from dialectical_framework.utils.effect_logger import EffectLogger
|
|
42
44
|
|
|
43
45
|
# Type alias for relationship type parameter
|
|
@@ -209,11 +211,13 @@ class ExecutionReport(BaseModel):
|
|
|
209
211
|
if self._event_bus is None:
|
|
210
212
|
return
|
|
211
213
|
import asyncio
|
|
214
|
+
|
|
212
215
|
try:
|
|
213
216
|
loop = asyncio.get_running_loop()
|
|
214
217
|
except RuntimeError:
|
|
215
218
|
return
|
|
216
219
|
from dialectical_framework.graph.scope_context import get_current_sid
|
|
220
|
+
|
|
217
221
|
sid = get_current_sid()
|
|
218
222
|
if sid:
|
|
219
223
|
loop.create_task(self._event_bus.publish(sid, effect))
|
|
@@ -224,6 +228,7 @@ class ExecutionReport(BaseModel):
|
|
|
224
228
|
return
|
|
225
229
|
from dialectical_framework.agents.agent_context import get_current_agent
|
|
226
230
|
from dialectical_framework.graph.scope_context import get_current_sid
|
|
231
|
+
|
|
227
232
|
sid = get_current_sid()
|
|
228
233
|
if not sid:
|
|
229
234
|
return
|
|
@@ -239,6 +244,7 @@ class ExecutionReport(BaseModel):
|
|
|
239
244
|
return
|
|
240
245
|
from dialectical_framework.agents.agent_context import get_current_agent
|
|
241
246
|
from dialectical_framework.graph.scope_context import get_current_sid
|
|
247
|
+
|
|
242
248
|
sid = get_current_sid()
|
|
243
249
|
if not sid:
|
|
244
250
|
return
|
|
@@ -431,10 +437,16 @@ class ExecutionReport(BaseModel):
|
|
|
431
437
|
|
|
432
438
|
merged_artifacts = {**self.artifacts, **other.artifacts}
|
|
433
439
|
|
|
434
|
-
|
|
440
|
+
merged = ExecutionReport(
|
|
435
441
|
tool=self.tool,
|
|
436
442
|
ok=self.ok and other.ok,
|
|
437
443
|
summary=f"{self.summary}\n{other.summary}".strip(),
|
|
438
444
|
effects=self.effects,
|
|
439
445
|
artifacts=merged_artifacts,
|
|
440
446
|
)
|
|
447
|
+
# Carry the sequence counter forward so subsequent _next_seq()/merge()
|
|
448
|
+
# calls continue the timeline. Without this the fresh report resets to
|
|
449
|
+
# 0, and chained merges (self._report = self._report.merge(...)) emit
|
|
450
|
+
# duplicate seq values.
|
|
451
|
+
merged._seq_counter = self._seq_counter
|
|
452
|
+
return merged
|