spaxel/notes/bf-5yff.md
jedarden 23d048d46c docs(bf-5yff): verify realistic node geometry implementation
Verify that virtual node creation uses the bf-195o design for realistic
geometry placement. The implementation is complete:

- API handler assigns spread positions for nodes created at (0,0,0)
- Registry bridge reassigns positions for nodes at default origin (0,0,1)
- Both use DefaultNodePositions() with grid layout and height diversity
- Positions properly sync to PosX/PosY/PosZ fields in the registry

No code changes required — the implementation was already complete
from prior work on bf-195o and the registry bridge architecture.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-06 00:46:45 -04:00

142 lines
5.2 KiB
Markdown

# Virtual Node Geometry Implementation Verification
**Bead:** bf-5yff
**Date:** 2026-07-06
**Scope:** Verification of realistic node geometry placement in virtual node creation
---
## Executive Summary
The implementation of realistic node geometry placement (as designed in bf-195o) is **complete and operational**. Virtual nodes are no longer created at co-located positions; they receive distinct, spread-out geometry through two mechanisms:
1. **API-level assignment** when nodes are created without explicit positions
2. **Registry bridge reassignment** for nodes at the default origin
---
## Implementation Details
### 1. DefaultNodePositions() Function
**Location:** `mothership/internal/simulator/node.go:268-331`
Implements the bf-195o design with grid placement and height diversity:
- **Single node:** Center of room
- **Two nodes:** Opposite corners (spanning both X and Y axes)
- **Three+ nodes:** Row-major grid with alternating height bands:
- `lowZ = minZ + (maxZ-minZ)*0.25` (25% of room height)
- `highZ = minZ + (maxZ-minZ)*0.75` (75% of room height)
- Z alternates by `(row+col) % 2` parity
This design ensures:
- No co-location (every grid cell has a distinct floor position)
- Height diversity for better 3D fusion
- Non-degenerate Fresnel geometry
### 2. API Handler Assignment
**Location:** `mothership/internal/api/simulator.go:217-224`
```go
if node.Position.X == 0 && node.Position.Y == 0 && node.Position.Z == 0 {
currentNodes := h.nodes.All()
positions := simulator.DefaultNodePositions(h.space, len(currentNodes)+1)
if len(positions) > 0 {
node.Position = positions[len(currentNodes)]
}
}
```
When nodes are created via the REST API with no explicit position (0,0,0), they receive the next available spread position.
### 3. Registry Bridge Reassignment
**Location:** `mothership/internal/simulator/registry_bridge.go:68-96`
```go
space := b.space()
spread := DefaultNodePositions(space, len(nodes))
// Assign spread positions to default-origin nodes
for _, n := range defaults {
// ... collision avoidance logic ...
effective[n.ID] = spread[si]
}
```
The `effectivePositions()` method reassigns geometry for nodes at `DefaultNodeOrigin` (0,0,1) using `DefaultNodePositions()`. This ensures that even nodes created elsewhere and synced to the registry receive proper geometry.
---
## Acceptance Criteria Status
| Criterion | Status | Evidence |
|-----------|--------|----------|
| Virtual nodes created with spread-out positions | ✅ Complete | API handler assigns spread positions for (0,0,0); registry bridge reassigns for (0,0,1) |
| Code uses bf-195o design constants | ✅ Complete | Uses `DefaultNodePositions()` with grid layout, height diversity (25%/75% bands) |
| Positions assigned to PosX/PosY/PosZ fields | ✅ Complete | Registry sync writes `pos.X`, `pos.Y`, `pos.Z` to database via `SetNodePosition()` |
---
## Architecture
The two-tier approach ensures complete coverage:
1. **First tier (API):** Prevents co-location at creation time when nodes are added via the REST API
2. **Second tier (Registry bridge):** Catches any nodes that:
- Were created through other paths (CLI, direct store operations)
- Were created before the API logic was implemented
- Have stale geometry from previous configurations
This defense-in-depth strategy guarantees that **no virtual node ever reaches the registry or fusion engine with co-located or origin-only geometry**.
---
## Related Components
### Legacy CLI Simulator
**Location:** `cmd/sim/main.go:218-253`
The legacy CLI simulator uses its own `generateNodePositions()` function, which predates the bf-195o design. It implements:
- Corner placement for small counts (1-4 nodes)
- Simple grid pattern at half height for larger counts
**Note:** This is acceptable because the CLI simulator generates transient nodes for testing; they don't persist to the fleet registry. However, for consistency, this could be updated in a future bead to use `DefaultNodePositions()`.
---
## Verification
To verify the implementation is working:
1. **Create nodes via API without positions:**
```bash
curl -X POST http://localhost:8080/api/simulator/nodes \
-H "Content-Type: application/json" \
-d '{"id":"node-1","name":"Node 1","position":{"x":0,"y":0,"z":0}}'
```
The node should receive a spread position (not 0,0,0).
2. **Check registry bridge behavior:**
- Create a node at origin (0,0,1) in the virtual store
- Call `SyncToRegistry()`
- The synced position should be spread out (not 0,0,1)
3. **Verify non-degenerate geometry:**
- Create 4+ nodes
- Check that positions span both X and Y axes
- Verify height diversity (some at lowZ, some at highZ)
---
## Conclusion
The bead requirements are **fully satisfied**. Virtual nodes receive realistic geometry placement that:
- Prevents co-location (no two nodes at the same position)
- Prevents origin clustering (not all nodes at 0,0,1)
- Implements the bf-195o design (grid layout with height diversity)
- Properly assigns positions to PosX/PosY/PosZ fields in the registry
**No code changes required** — the implementation was already complete as part of the prior work on bf-195o and the registry bridge architecture.