Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ add_library(t81_experimental STATIC
experimental/tiers/cog/tier4/tier4_loop.cpp
experimental/distributed/distributed.cpp
experimental/tiers/cog/tier5/infinite.cpp
experimental/tiers/cog/tier6/distributed_monad.cpp
)
target_link_libraries(t81_experimental PUBLIC t81_core)
target_compile_features(t81_experimental PUBLIC ${T81_CXX_STD_FEATURE})
Expand Down Expand Up @@ -2380,6 +2381,9 @@ add_test(NAME t81lang_surface_gate_test COMMAND t81lang_surface_gate_test)
target_link_libraries(t81_ethics_test PRIVATE t81_core t81_axion)
add_test(NAME t81_ethics_test COMMAND t81_ethics_test)

add_executable(t81_tier6_test tests/cpp/tier6_test.cpp)
target_link_libraries(t81_tier6_test PRIVATE t81_core t81_experimental t81_tracing)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Redundant t81_tracing link dependency

t81_tracing is declared as an OBJECT library (line 195) and its objects are already compiled directly into t81_core via target_sources(t81_core PRIVATE $<TARGET_OBJECTS:t81_tracing>) (line 202). Listing it again here is redundant — the symbols are already present through t81_core. Compare with the analogous t81_tier5_test target which links only t81_core t81_experimental.

Suggested change
target_link_libraries(t81_tier6_test PRIVATE t81_core t81_experimental t81_tracing)
target_link_libraries(t81_tier6_test PRIVATE t81_core t81_experimental)


add_executable(t81_ethics_invariants_test tests/cpp/test_ethics_invariants.cpp)
target_link_libraries(t81_ethics_invariants_test PRIVATE t81_core t81_axion)
add_test(NAME t81_ethics_invariants_test COMMAND t81_ethics_invariants_test)
Expand Down Expand Up @@ -3301,6 +3305,7 @@ target_link_libraries(axion_policy_segment_event_test PRIVATE t81_isa t81_vm)
canonfs_axion_trace_test
t81_tier4_test
t81_tier5_test
t81_tier6_test
t81_infinite_opcodes_test
t81_tier4_vm_test
t81_tier4_distributed_test
Expand Down
96 changes: 96 additions & 0 deletions tests/cpp/tier6_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include <cassert>
#include <iostream>
#include <vector>

#include "t81/experimental/cog/tier6/distributed_monad.hpp"
#include "t81/tracing/canonhash.hpp"

using namespace t81::cog::v6;

void test_empty_mesh() {
MeshReflector reflector;
std::vector<MonadState> monads;

auto result = reflector.mesh_reflect(monads);
assert(result.converged);
assert(result.convergence_hash == "EMPTY_MESH");
assert(result.iterations == 0);
std::cout << "Empty mesh test passed.\n";
}

void test_mesh_reflection_convergence() {
MeshReflector reflector;
std::vector<MonadState> monads;

MonadState m1;
m1.address.node_hash = t81::hash::hash_string("hash1");
m1.label = "node1";

MonadState m2;
m2.address.node_hash = t81::hash::hash_string("hash2");
m2.label = "node2";

m1.peers.push_back(m2.address);
m2.peers.push_back(m1.address);

monads.push_back(m1);
monads.push_back(m2);

auto result = reflector.mesh_reflect(monads);
assert(!result.converged);
assert(result.iterations == 1);
assert(monads[0].label == "node1+node2");
assert(monads[1].label == "node2+node1");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update expected labels for sequential mesh reflection

These assertions assume each monad reflects against a snapshot of pre-round labels, but MeshReflector::mesh_reflect mutates monads in-place as it iterates, so the second monad reads the first monad’s already-updated label in the same round. As written, this assertion (and the later second-round label assertions) will fail whenever assertions are enabled (for example in local debug/assert builds), causing t81_tier6_test to abort even though the implementation behavior is unchanged.

Useful? React with 👍 / 👎.

assert(monads[0].reflection_depth == 1);
Comment on lines +42 to +44
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 In-place mutation causes synchronous-round test to fail

mesh_reflect() in distributed_monad.cpp mutates each monad's label in-place during the single for (auto& m : monads) loop. This means that when monads[1] (m2) is processed, the peer lookup for m1 returns the already-updated value "node1+node2" rather than the original "node1".

Tracing the first call:

Step monad composite built from result label
1 m1 "node1" + peer m2 ("node2") "node1+node2" ✓ written to monads[0]
2 m2 "node2" + peer m1 (now "node1+node2") "node2+node1+node2"

So the assertion on line 43 assert(monads[1].label == "node2+node1") will fail at runtime; the actual value is "node2+node1+node2". All subsequent assertions in this test (lines 50–51) are also invalidated.

The test correctly encodes the intended synchronous (Jacobi) semantics — each monad should see the pre-round labels of its peers. The implementation needs to snapshot all labels before the loop. This is a bug in the existing experimental/tiers/cog/tier6/distributed_monad.cpp that this PR needs to fix before the tests can pass.

assert(monads[1].reflection_depth == 1);

auto result2 = reflector.mesh_reflect(monads);
assert(!result2.converged);
assert(result2.iterations == 1);
assert(monads[0].label == "node1+node2+node2+node1");
assert(monads[1].label == "node2+node1+node1+node2");

std::cout << "Mesh reflection test passed.\n";
}

void test_entropy_containment() {
MeshReflector reflector(2); // Set max depth to 2
std::vector<MonadState> monads;

MonadState m1;
m1.address.node_hash = t81::hash::hash_string("hash1");
m1.label = "node1";

MonadState m2;
m2.address.node_hash = t81::hash::hash_string("hash2");
m2.label = "node2";

m1.peers.push_back(m2.address);
m2.peers.push_back(m1.address);

monads.push_back(m1);
monads.push_back(m2);

auto r1 = reflector.mesh_reflect(monads);
assert(!r1.converged);
assert(monads[0].entropy_contained);

auto r2 = reflector.mesh_reflect(monads);
assert(!r2.converged);
assert(!monads[0].entropy_contained);
assert(!monads[1].entropy_contained);

auto r3 = reflector.mesh_reflect(monads);
assert(!r3.converged);
assert(r3.convergence_hash == "ENTROPY_VIOLATION");

std::cout << "Entropy containment test passed.\n";
}

int main() {
test_empty_mesh();
test_mesh_reflection_convergence();
test_entropy_containment();
std::cout << "All tier 6 tests passed.\n";
return 0;
}
Loading