dialectical-framework 1.6.2__tar.gz → 1.6.3__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 → dialectical_framework-1.6.3}/PKG-INFO +1 -1
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/pyproject.toml +1 -1
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/analyst/analyst.py +48 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/analyst/skills/find_polarities.py +215 -45
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/analyst/system_prompts.py +37 -0
- dialectical_framework-1.6.3/src/dialectical_framework/concerns/antithetical_thesis_detection.py +338 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/LICENSE +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/README.md +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/advisor/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/advisor/advisor.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/advisor/system_prompts.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/advisor/tools/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/advisor/tools/anchor.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/advisor/tools/explore.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/advisor/tools/ingest.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/advisor/tools/sync.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/agent_context.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/analyst/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/analyst/skills/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/analyst/skills/anchor_theses.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/analyst/skills/edit_perspective.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/analyst/skills/expand_polarities.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/analyst/skills/introduce_polarity.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/analyst/skills/surface_theses.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/analyst/tools/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/analyst/tools/create_dx_input.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/analyst/tools/place_statement.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/apps.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/conversation_facilitator.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/execution_report.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/explorer/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/explorer/explorer.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/explorer/skills/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/explorer/skills/build_wheels.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/explorer/skills/explore_transformations.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/explorer/skills/generate_synthesis.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/explorer/system_prompts.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/explorer/tools/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/explorer/tools/create_nexus.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/explorer/tools/expand_nexus.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/explorer/tools/generate_synthesis.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/explorer/tools/present_exploration.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/orchestrator/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/orchestrator/tools/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/orchestrator/tools/add_input.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/orchestrator/tools/digest_input.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/orchestrator/tools/discard.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/orchestrator/tools/get_schema.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/orchestrator/tools/inspect_node.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/orchestrator/tools/present_analysis.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/orchestrator/tools/query_graph.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/orchestrator/tools/read_digest.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/orchestrator/tools/read_input.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/reasonable_concern.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/agents/stream_events.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/ac_re_taxonomy.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/action_extraction.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/add_input.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/ai_dto/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/ai_dto/statement_dto.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/ai_dto/statements_deck_dto.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/antithesis_classification.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/antithesis_extraction.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/aspect_classification.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/aspect_generation.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/causality/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/causality/causality_estimator.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/causality/causality_estimator_balanced.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/causality/causality_estimator_criteria.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/causality/causality_estimator_desirable.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/causality/causality_estimator_feasible.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/causality/causality_estimator_realistic.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/causality/causality_normalizer.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/causality/estimator_resolver.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/causality_estimation.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/control_statements_check.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/create_dx_input.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/create_nexus.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/diagonal_oppositions_check.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/dialectical_context.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/discard.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/display_text_edit.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/expand_nexus.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/perspective_combination.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/perspective_validation.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/positive_ac_re_apex_derivation.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/scoring_scales.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/source_digest.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/statement_classification.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/statement_deduplication.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/statement_headline.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/statement_placement.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/synthesis_generation.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/thesis_extraction.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/transformation_audit.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/concerns/transformation_generation.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/dialectical_reasoning.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/enums/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/enums/causality_preset.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/enums/di.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/events/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/events/graph_event.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/events/graph_event_bus.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/exceptions/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/exceptions/node_errors.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/exceptions/resolver_errors.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/composite_input_resolver.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/dialexity_input_resolver.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/estimation_manager.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/mixins/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/mixins/incremental_build_mixin.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/mixins/intent_mixin.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/mixins/persistable_mixin.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/nodes/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/nodes/assessable_entity.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/nodes/base_node.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/nodes/case.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/nodes/cycle.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/nodes/estimation.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/nodes/ideas.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/nodes/input.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/nodes/nexus.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/nodes/perspective.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/nodes/polarity.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/nodes/rationale.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/nodes/statement.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/nodes/synthesis.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/nodes/transformation.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/nodes/transition.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/nodes/wheel.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationship_manager.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/action_reflection_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/belongs_to_cycle_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/belongs_to_nexus_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/changed_to_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/contradiction_of_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/critiques_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/distilled_to_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/estimates_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/explains_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/has_input_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/has_statement_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/has_wheel_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/immutable_structure.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/is_source_of_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/is_target_of_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/negative_side_of_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/opposite_direction_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/opposite_of_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/polarity_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/positive_side_of_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/provides_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/relationships/synthesis_of_relationship.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/rendering.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/repositories/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/repositories/case_repository.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/repositories/cycle_repository.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/repositories/input_repository.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/repositories/nexus_repository.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/repositories/node_repository.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/repositories/perspective_repository.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/repositories/polarity_repository.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/repositories/schema_repository.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/repositories/statement_repository.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/repositories/transformation_repository.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/repositories/wheel_repository.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/scope_context.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/verbatim_input_resolver.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/wheel_segment.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/graph/wheel_segment_polar_pair.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/protocols/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/protocols/has_config.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/protocols/input_resolver.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/settings.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/utils/__init__.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/utils/bedrock_provider.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/utils/concurrency.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/utils/dc_replace.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/utils/decompose_probability_uniformly.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/utils/edge_context.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/utils/effect_logger.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/utils/input_context.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/utils/order_transitions.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/utils/sequence_generation.py +0 -0
- {dialectical_framework-1.6.2 → dialectical_framework-1.6.3}/src/dialectical_framework/utils/use_brain.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: dialectical-framework
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.3
|
|
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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "dialectical-framework"
|
|
3
|
-
version = "1.6.
|
|
3
|
+
version = "1.6.3"
|
|
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"
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
465
|
-
|
|
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
|
-
|
|
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
|
|
489
|
-
|
|
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
|
-
|
|
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
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
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:
|