test(bf-4b1c): differential lock-in for geometry placement and fusion peaks

bf-4b1c wants test coverage proving geometry placement drives fusion peaks,
with the explicit "would fail with old co-located placement but passes with
new geometry" property. The prior children (bf-18yn -> bf-3y9r) cover each
half separately — TestEngine_DefaultPlacementProducesPeaks (spread alone,
geometry-dependent synthetic links) and TestEngine_CoLocatedOriginYields
NoPeaks (co-located alone). What was missing was a single run that isolates
placement as the SOLE variable and demonstrates the non-zero-peak condition
flipping with geometry, proving the test is genuinely regression-sensitive.

Add TestEngine_GeometryPlacementDrivesFusionPeaks: a fuseWithPlacement helper
builds an engine sized to DefaultSpace, seeds N nodes at a given placement,
and fires an explicit geometry-independent motion link for EVERY node pair
(DeltaRMS=1.0, Motion=true) — the link set, grid, and room are identical
across both legs, so only where nodes sit differs. For default (spread)
placement the grid accumulates a non-zero max (gridMax>0); for the old
co-located (0,0,1) collapse every link is degenerate (<0.1 m), AddLink
Influence early-returns, and the grid stays at zero (gridMax==0). The
differential asserts spread>0 && colocated==0. For count>=4 the crossing
links additionally extract >=1 blob, confirming the non-zero grid localizes.

The trace under `go test -v` shows the flip:
  [spread] nodes=4 gridMax=1.0000 blobs=2 top=(2.90,2.50,1.30) conf=0.768 activeLinks=6
  [colocated] nodes=4 gridMax=0.0000 blobs=0 activeLinks=6 — degenerate links, no accumulation

go test ./... , go vet ./... , and go build ./... (all three modules) pass.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
jedarden 2026-07-06 13:49:20 -04:00
parent 747638ed1d
commit c4d42e8c30

View file

@ -524,6 +524,164 @@ func gridMaxValue(data []float64) float64 {
return max return max
} }
// TestEngine_GeometryPlacementDrivesFusionPeaks (bf-4b1c) is the differential
// lock-in for "geometry placement and fusion peaks." It runs the SAME
// blob-producing harness under two placements and asserts the non-zero-peak
// condition flips with geometry — passing with the default (spread) placement
// a freshly-onboarded sim fleet receives, and failing with the old co-located
// (0,0,1) DB-default collapse.
//
// Placement is held as the SOLE variable: the engine grid, the walker-free
// all-pairs motion link set (every node pair, DeltaRMS=1.0, Motion=true), and
// the room are identical across both legs. Only where the nodes sit differs.
//
// - Spread placement: links are non-degenerate, AddLinkInfluence paints the
// accumulation grid, it normalizes to a non-zero max, and Fuse emits peaks.
// - Co-located placement: every link has length < 0.1 m, AddLinkInfluence
// early-returns, the grid stays at zero, and Fuse emits no peaks.
//
// That the identical non-zero-peak assertion holds for one and fails for the
// other is the demonstrable proof the bead's scope asks for: "test would fail
// with old co-located placement but passes with new geometry" — i.e. the test
// is genuinely sensitive to the bf-4q5w regression, not trivially satisfiable.
//
// This complements TestEngine_DefaultPlacementProducesPeaks (bf-18yn: spread
// alone, geometry-dependent synthetic links) and TestEngine_CoLocatedOrigin
// YieldsNoPeaks (co-located alone): both halves in one run, geometry isolated.
func TestEngine_GeometryPlacementDrivesFusionPeaks(t *testing.T) {
space := simulator.DefaultSpace()
minX, minY, minZ, maxX, maxY, maxZ := space.Bounds()
// spreadPlace is the default onboarding placement (distinct, room-spanning).
// colocatedPlace is the pre-spread DB-default collapse (all at (0,0,1)).
spreadPlace := func(count int) []simulator.Point {
return simulator.DefaultNodePositions(space, count)
}
colocatedPlace := func(count int) []simulator.Point {
pts := make([]simulator.Point, count)
for i := range pts {
pts[i] = simulator.Point{X: 0, Y: 0, Z: 1}
}
return pts
}
for _, count := range []int{2, 4} {
t.Run(fmt.Sprintf("nodes=%d", count), func(t *testing.T) {
// ---- spread (new geometry): must produce non-zero peaks ----
spreadResult, spreadGridMax := fuseWithPlacement(minX, minY, minZ,
maxX, maxY, maxZ, count, spreadPlace)
// Guard the placement itself did not regress to the collapse.
assertPlacementNotCollapsed(t, spreadPlace(count))
// Bead criterion: the accumulation grid is not all zeros. This is
// the geometry-pure signal and the one that holds for every fleet
// size (a single link still paints a non-zero ridge).
if spreadGridMax <= 0 {
t.Fatalf("spread placement produced an all-zero accumulation grid "+
"(gridMax=%.4f, activeLinks=%d) — default placement must let the "+
"grid accumulate non-zero peaks", spreadGridMax, spreadResult.ActiveLinks)
}
// A single link (count=2) paints a symmetric ridge with no strict
// local maximum, so the peak extractor legitimately yields no blob
// even though the grid is non-zero (documented in bf-18yn). With
// count>=4 the crossing links form a true maximum and must extract
// at least one blob — proving the non-zero grid localizes.
if count >= 4 && len(spreadResult.Blobs) == 0 {
t.Fatalf("spread placement of %d nodes produced 0 blobs despite "+
"gridMax=%.4f > 0 (activeLinks=%d) — crossing links must yield a peak",
count, spreadGridMax, spreadResult.ActiveLinks)
}
if len(spreadResult.Blobs) > 0 {
top := spreadResult.Blobs[0]
t.Logf("[spread] nodes=%d gridMax=%.4f blobs=%d top=(%.2f,%.2f,%.2f) conf=%.3f activeLinks=%d",
count, spreadGridMax, len(spreadResult.Blobs), top.X, top.Y, top.Z,
top.Confidence, spreadResult.ActiveLinks)
} else {
t.Logf("[spread] nodes=%d gridMax=%.4f blobs=0 (single-link ridge, no strict max) activeLinks=%d",
count, spreadGridMax, spreadResult.ActiveLinks)
}
// ---- co-located (old geometry): must produce ZERO peaks ----
coloResult, coloGridMax := fuseWithPlacement(minX, minY, minZ,
maxX, maxY, maxZ, count, colocatedPlace)
// The SAME non-zero-peak condition asserted above must FAIL here:
// an all-zero grid (no accumulation) and zero extracted blobs. If
// this leg ever starts producing peaks, the differential no longer
// isolates geometry and the regression-sensitivity claim is void.
if coloGridMax != 0 || len(coloResult.Blobs) != 0 {
t.Fatalf("co-located (0,0,1) placement must yield an all-zero grid and "+
"no peaks (got gridMax=%.4f, blobs=%d) — the differential only holds "+
"if co-located nodes cannot accumulate", coloGridMax, len(coloResult.Blobs))
}
t.Logf("[colocated] nodes=%d gridMax=%.4f blobs=%d activeLinks=%d — degenerate links, no accumulation",
count, coloGridMax, len(coloResult.Blobs), coloResult.ActiveLinks)
// Explicit differential: the geometry change flips gridMax from
// zero (old) to non-zero (new). This is the bead's central claim.
if !(spreadGridMax > 0 && coloGridMax == 0) {
t.Fatalf("differential broken: spread gridMax=%.4f colocated gridMax=%.4f — "+
"expected spread>0 and colocated==0", spreadGridMax, coloGridMax)
}
})
}
}
// fuseWithPlacement builds an engine sized to the given room bounds, seeds
// `count` nodes at the placement the `place` callback returns, fires an
// explicit geometry-independent motion link for every node pair (DeltaRMS=1.0),
// runs one Fuse step, and returns the result plus the accumulation grid's max
// voxel value. Placement is the ONLY thing that varies between callers — the
// link set, grid, and room are identical — so the returned gridMax is a pure
// function of geometry.
func fuseWithPlacement(minX, minY, minZ, maxX, maxY, maxZ float64,
count int, place func(int) []simulator.Point) (*Result, float64) {
e := NewEngine(&Config{
Width: maxX - minX,
Height: maxY - minY,
Depth: maxZ - minZ,
OriginX: minX,
OriginY: minY,
OriginZ: minZ,
CellSize: 0.2,
MinDeltaRMS: 0.01,
MaxBlobs: 6,
BlobThreshold: 0.1,
})
pts := place(count)
nodes := make([]NodePosition, len(pts))
for i, p := range pts {
mac := fmt.Sprintf("GN:%02d", i+1)
nodes[i] = NodePosition{MAC: mac, X: p.X, Y: p.Y, Z: p.Z}
e.SetNodePosition(mac, p.X, p.Y, p.Z)
}
// Explicit all-pairs motion links — geometry-independent. Same set for
// every placement, so only the node coordinates differ between legs.
links := make([]LinkMotion, 0, count*(count-1)/2)
for i := 0; i < len(nodes); i++ {
for j := i + 1; j < len(nodes); j++ {
links = append(links, LinkMotion{
NodeMAC: nodes[i].MAC,
PeerMAC: nodes[j].MAC,
DeltaRMS: 1.0,
Motion: true,
})
}
}
r := e.Fuse(links)
var gridMax float64
if snap := e.GetGridSnapshot(); snap != nil {
gridMax = gridMaxValue(snap.Data)
}
return r, gridMax
}
// TestEngine_HealthWeight verifies that links with lower health scores contribute less to fusion. // TestEngine_HealthWeight verifies that links with lower health scores contribute less to fusion.
// Per spec: "each link's contribution to the 3D occupancy grid is multiplied by its health_score" // Per spec: "each link's contribution to the 3D occupancy grid is multiplied by its health_score"
func TestEngine_HealthWeight(t *testing.T) { func TestEngine_HealthWeight(t *testing.T) {