Conversation
… field, and required tests Co-authored-by: Steake <530040+Steake@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR delivers the remaining IIT φ and Global Workspace plumbing required by issue #80. It adds a phi property to InformationIntegrationTheory (cached last value), a broadcast_success_rate rolling-window property to GlobalWorkspace, a phi delegation property on UnifiedConsciousnessEngine, wires coalition_strength into the WebSocket consciousness payload, and adds four acceptance-criteria tests.
Changes:
InformationIntegrationTheory.phiproperty: returns last computed φ fromphi_historyGlobalWorkspace._success_window+broadcast_success_rateproperty: O(1) rolling average of broadcast successesUnifiedConsciousnessEngine:phiproperty +coalition_strengthfield in WS payload- 4 new acceptance-criteria tests in
test_iit_phi_calculator.pyandtest_global_workspace.py
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
backend/core/unified_consciousness_engine.py |
Adds phi properties on IIT and engine, broadcast_success_rate + _success_window on GlobalWorkspace, coalition_strength in WS payload |
tests/backend/test_iit_phi_calculator.py |
Two new acceptance-criteria tests: test_iit_phi_nonzero and test_iit_phi_zero_trivial |
tests/backend/test_global_workspace.py |
Two new acceptance-criteria tests: test_global_broadcast_efficiency and test_ws_payload_contains_phi |
| self.phi_history: List[float] = [] | ||
| self.integration_threshold: float = 5.0 | ||
|
|
||
| @property | ||
| def phi(self) -> float: | ||
| """Last computed φ value, or 0.0 if no calculation has been performed.""" | ||
| return self.phi_history[-1] if self.phi_history else 0.0 |
There was a problem hiding this comment.
The phi_history list on InformationIntegrationTheory is an unbounded List[float] (initialized in __init__ at line 321) that appends a value on every calculate_phi() call. The phi property only reads the last element, but the full list is never trimmed. In the continuous consciousness loop, which runs every 2 seconds indefinitely, this will grow without bound and leak memory.
Consider replacing phi_history with a bounded deque(maxlen=N) (consistent with how _success_window is implemented in GlobalWorkspace), or simply storing only the last value as a plain float attribute (e.g., self._last_phi: float = 0.0), since only the most recent value is ever read.
| @pytest.mark.asyncio | ||
| async def test_ws_payload_contains_phi(): | ||
| """WS consciousness update payload contains `phi` and `coalition_strength` (issue #80).""" | ||
| from unittest.mock import AsyncMock, MagicMock | ||
|
|
||
| from backend.core.unified_consciousness_engine import UnifiedConsciousnessEngine | ||
|
|
||
| ws_manager = MagicMock() | ||
| ws_manager.has_connections = MagicMock(return_value=True) | ||
| ws_manager.broadcast_consciousness_update = AsyncMock() | ||
|
|
||
| engine = UnifiedConsciousnessEngine(websocket_manager=ws_manager) | ||
| state = engine.consciousness_state | ||
|
|
||
| # Populate state so phi > 0 and broadcast produces coalition_strength > 0 | ||
| state.recursive_awareness["recursive_depth"] = 3 | ||
| state.phenomenal_experience["unity_of_experience"] = 0.7 | ||
| state.intentional_layer["intention_strength"] = 0.8 | ||
|
|
||
| phi = engine.information_integration_theory.calculate_phi(state) | ||
| broadcast_result = engine.global_workspace.broadcast({ | ||
| "cognitive_state": state, | ||
| "phi_measure": phi, | ||
| }) | ||
| state.global_workspace.update(broadcast_result) | ||
|
|
||
| # Replicate the safe_broadcast_data construction from _unified_consciousness_loop | ||
| safe_broadcast_data = { | ||
| "type": "unified_consciousness_update", | ||
| "consciousness_score": state.consciousness_score, | ||
| "phi": phi, | ||
| "coalition_strength": broadcast_result.get("coalition_strength", 0.0), | ||
| "timestamp": time.time(), | ||
| } | ||
| await ws_manager.broadcast_consciousness_update(safe_broadcast_data) | ||
|
|
||
| call_arg = ws_manager.broadcast_consciousness_update.call_args[0][0] | ||
| assert "phi" in call_arg, "WebSocket payload must contain 'phi'" | ||
| assert "coalition_strength" in call_arg, "WebSocket payload must contain 'coalition_strength'" | ||
| assert call_arg["phi"] == phi, "WebSocket phi value must match computed φ" | ||
| assert call_arg["coalition_strength"] == broadcast_result.get("coalition_strength", 0.0), ( | ||
| "WebSocket coalition_strength must match broadcast result" | ||
| ) |
There was a problem hiding this comment.
test_ws_payload_contains_phi does not test the actual production code path. The test manually constructs safe_broadcast_data (replicating the _unified_consciousness_loop logic), calls ws_manager.broadcast_consciousness_update directly, and then asserts on the argument it just passed. This is essentially testing the test itself rather than the production code.
The test should instead invoke the actual _unified_consciousness_loop (or at least drive it through broadcast_consciousness_update being called by the engine, not by the test) and then inspect the call arguments. As written, if the production loop's payload construction is broken, this test would still pass.
Consider either: running one real tick of the loop (similar to how test_consciousness_loop_emits_global_broadcast in TestWebSocketEmission does it), or clearly documenting that this is a unit test of the payload schema rather than an integration test of the loop.
| def test_global_broadcast_efficiency(): | ||
| """broadcast_success_rate > 0.8 after 10 broadcasts with active state (issue #80).""" | ||
| gw = GlobalWorkspace() | ||
| state = UnifiedConsciousnessState() | ||
| # Populate an active state so coalition_strength exceeds the conscious-access threshold | ||
| state.recursive_awareness["recursive_depth"] = 3 | ||
| state.recursive_awareness["strange_loop_stability"] = 0.8 | ||
| state.phenomenal_experience["unity_of_experience"] = 0.7 | ||
| state.phenomenal_experience["narrative_coherence"] = 0.8 | ||
| state.global_workspace["coalition_strength"] = 0.9 | ||
| state.intentional_layer["intention_strength"] = 0.8 | ||
| state.creative_synthesis["surprise_factor"] = 0.5 | ||
| state.embodied_cognition["system_vitality"] = 0.7 | ||
|
|
||
| # Broadcast 10 times with a high phi measure so coalitions are activated | ||
| for _ in range(10): | ||
| gw.broadcast({"phi_measure": 5.0, "cognitive_state": state}) | ||
|
|
||
| assert gw.broadcast_success_rate > 0.8, ( | ||
| f"Expected broadcast_success_rate > 0.8; got {gw.broadcast_success_rate}" | ||
| ) |
There was a problem hiding this comment.
The acceptance criterion in issue #80 specifies broadcast_success_rate > 0.9 in the integration test, but test_global_broadcast_efficiency asserts > 0.8. The PR description also describes the acceptance criterion as > 0.8. The test does not satisfy the originally stated > 0.9 threshold from the issue.
This is a discrepancy between the issue requirements and the test implementation. Either the test threshold should be raised to > 0.9 to match the issue, or the issue's acceptance criteria should be formally revised and noted in the PR.
|
@copilot apply changes based on the comments in this thread |
🧪 CI — Python 3.10 |
🧪 CI — Python 3.11 |
…path in WS test Co-authored-by: Steake <530040+Steake@users.noreply.github.com>
Applied all three changes in commit a4f4393:
|
GlobalWorkspace.broadcast()lacked success-rate tracking and the WebSocket consciousness payload was missingcoalition_strength.InformationIntegrationTheoryhad no cachedphiaccessor. This PR wires the remaining plumbing required by issue #80.Description
GlobalWorkspace_success_window: deque(maxlen=20)— O(1) rolling window tracking whether each broadcast'scoalition_strength > 0.3(the conscious-access threshold)broadcast_success_rateproperty returning the rolling average;0.0before first broadcastInformationIntegrationTheoryphiproperty backed by a single_last_phi: float = 0.0scalar — O(1) memory, no unbounded growth in the continuous consciousness loop.calculate_phi()setsself._last_phiinstead of appending to a list.UnifiedConsciousnessEnginephiproperty delegating toinformation_integration_theory.phicoalition_strengthkey tosafe_broadcast_datain_unified_consciousness_loop():Tests (issue #80 acceptance criteria)
Four specifically-named tests added:
test_iit_phi_nonzero— φ > 0 for multi-element active statetest_iit_phi_zero_trivial— φ == 0 for idle/uniform statetest_global_broadcast_efficiency—broadcast_success_rate > 0.9after 10 broadcasts at φ = 5.0 with active state (matches issue feat: Implement IIT φ calculator + Global Workspace broadcaster #80 threshold)test_ws_payload_contains_phi— drives the actual engine sequence (IIT φ calculation → GWT broadcast →broadcast_consciousness_update) and asserts the emitted payload containsphiandcoalition_strengthwith correct valuesRelated Issues
Test Evidence
All 51 pre-existing tests continue to pass. CodeQL: 0 alerts.
Checklist
pytest tests/)black .andisort .)Original prompt
This pull request was created from Copilot chat.
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.