bf-4bhd failed repeatedly because re-dispatched agents trust its stale
"Analysis Report" framing (no supersession marker on the file). Per
notes/bf-1q3m-consolidated.md §4.1, add a visible SUPERSEDED banner to the
top of notes/bf-4bhd.md and notes/bf-3ldj-findings.md naming
notes/bf-1q3m-consolidated.md as the sole trusted blob inventory, stating the
material reasons:
- bf-4bhd: 2D field-list drift (claims tracking.Blob has PersonName/
AssignedColor/IdentityResolved — those fields no longer exist) + line
drift (E2/E3/volume +90, E1 +110) vs HEAD.
- bf-3ldj: same line drift + a fundamentally wrong "IDENTITY ATTACHED"
data-flow claim (tracker.TrackManager.UpdateWithIdentity is not wired
into main.go at HEAD; identity is sidecar-based via ble.IdentityMatcher).
Add proportionate "secondary - see consolidated" banners to the bf-3ldj-input
notes (bf-26ta, bf-67ao, bf-5kns) and bf-26ta's JS/TS result dumps, so no
inventory-titled note remains that a future agent could mistake for
authoritative. notes/bf-1q3m-consolidated.md already declares itself the
single source of truth (header banner + §9 provenance) - confirmed unchanged.
All stale files retained for provenance; none deleted. Docs-only change, no
Go/JS source modified (go vet + go test ./... clean).
Co-Authored-By: Claude <noreply@anthropic.com>
16 KiB
🔴🔴🔴 SUPERSEDED — DO NOT USE THIS FILE AS A BLOB INVENTORY. 🔴🔴🔴
This report has drifted against current HEAD and is retained for provenance only. The sole trusted blob inventory is
notes/bf-1q3m-consolidated.md— read that file instead and ignore thefile:linereferences below.Why superseded (per
notes/bf-1q3m-consolidated.md§4.1):
- 2D field-list drift (material). This report claims
tracking.Blob(2D) carries the fieldsPersonName,AssignedColor, andIdentityResolved. Those fields no longer exist. At HEAD the 2D identity field set is identical to the 3D type:PersonID / PersonLabel / PersonColor / IdentityConfidence / IdentitySource / IdentityLastSeen. (Verified 2026-07-06.) The "Pattern 1.1" literal below that allegedly setsPersonName:"",AssignedColor:"",IdentityResolved:falseis therefore wrong — the literal sets none of the identity fields (Go zero values).- Line drift (+90 / +110). The E1/E2/E3 boundary citations and the projection-table lines are all stale: E2 automation is actually
main.go:2303(cited:2213, +90), E3 explainabilitymain.go:2206(cited:2116, +90), E1 sigprocmain.go:5494(cited:5384, +110), and the projection table's explainability:2116/ volume:2236are:2206/:2326(+90 each).Status: provenance only. A future agent must not consume this file for
file:linereferences or for the 2D Blob field list — it will re-introduce the very drift this effort corrected. Usenotes/bf-1q3m-consolidated.md.
Blob Creation Code Paths - Analysis Report (SUPERSEDED — see banner above)
Task: Find all blob creation code paths
Summary
This report documents all locations where blob objects are created or constructed in the spaxel codebase. There are FIVE distinct primary Blob types across different packages (the tracked-blob lifecycle), plus seven additional Blob-shaped projection types that are derived from blobs for specific subsystems (see "Related Blob-shaped projection types" below).
tracking.Blob- 2D floor tracker (X, Z coordinates)tracker.Blob- 3D tracker with identity support (X, Y, Z coordinates + posture)fusion.Blob- Simple fusion result (X, Y, Z + confidence)automation.TrackedBlob- Automation engine blob representationsignal.TrackedBlob- Fusion-to-tracking pipeline blob (X, Y, Z + velocity + identity fields)
Line numbers verified against current
main(2026-07-06). Sites move by a few lines as the codebase evolves; re-locate withgrep -n "&Blob{\|Blob{\|TrackedBlob{" mothership/before editing.
Blob Type Definitions
1. tracking.Blob (mothership/internal/tracking/tracker.go:21)
type Blob struct {
ID int
X float64 // metres, room X
Z float64 // metres, room Z
VX float64 // m/s
VZ float64 // m/s
Weight float64 // localisation confidence [0..1]
LastSeen time.Time
Trail [][2]float64
ukf *UKF
// Identity fields
PersonID string
PersonLabel string
PersonColor string
PersonName string
AssignedColor string
IdentityResolved bool
IdentityConfidence float64
IdentitySource string
IdentityLastSeen time.Time
Posture Posture
}
2. tracker.Blob (mothership/internal/tracker/tracker.go:36)
type Blob struct {
ID int
X, Y, Z float64 // world-space position, metres
VX, VY, VZ float64 // velocity, m/s
Weight float64 // detection confidence [0..1]
Posture Posture
LastSeen time.Time
Trail [][3]float64
// Identity fields
PersonID string
PersonLabel string
PersonColor string
IdentityConfidence float64
IdentitySource string
IdentityLastSeen time.Time
ukf *UKF
}
3. fusion.Blob (mothership/internal/fusion/fusion.go:36)
type Blob struct {
X, Y, Z float64 // world-space position (metres)
Confidence float64 // normalised [0..1]
}
4. automation.TrackedBlob (mothership/internal/automation/engine.go:1337)
type TrackedBlob struct {
ID int
X, Y, Z float64
VX, VY, VZ float64
Confidence float64
}
5. signal.TrackedBlob (mothership/internal/signal/processor.go:587)
Type alias:
api.TrackedBlobatmothership/internal/api/tracks.go:30is a pure alias (type TrackedBlob = signal.TrackedBlob), not a new struct. Any field change tosignal.TrackedBlobpropagates toapi.TrackedBlobautomatically — no separate edit needed, but be aware the type surfaces under two names.
type TrackedBlob struct {
ID int
X, Y, Z float64
VX, VY, VZ float64
Weight float64
// Identity fields
PersonID string
PersonLabel string
PersonColor string
IdentityConfidence float64
IdentitySource string
Posture string
}
Blob Creation Sites
Pattern 1: Direct struct construction with &Blob{}
1.1 tracking/tracker.go:160 - New blob from measurement
b := &Blob{
ID: t.nextID,
X: meas[0],
Z: meas[1],
Weight: meas[2],
LastSeen: now,
Trail: [][2]float64{{meas[0], meas[1]}},
ukf: NewUKF(meas[0], meas[1]),
// Initialize identity fields with default values
PersonName: "",
AssignedColor: "",
IdentityResolved: false,
}
- Context: Tracker.Update() when unmatched measurements create new tracks
- Pattern: Pointer construction, initializes ID, position, weight, trail, UKF filter
1.2 tracker/tracker.go:162 - New 3D blob from measurement
b := &Blob{
ID: t.nextID,
X: m[0], Y: m[1], Z: m[2],
Weight: m[3],
LastSeen: now,
Trail: [][3]float64{{m[0], m[1], m[2]}},
Posture: PostureUnknown,
ukf: NewUKF(m[0], m[1], m[2]),
}
- Context: Tracker.Update() when unmatched measurements create new 3D tracks
- Pattern: Similar to 1.1 but with Y coordinate and Posture field
Pattern 2: Value-type construction with Blob{}
2.1 fusion/fusion.go:260 - Blob from peak detection
blobs[i] = Blob{X: p[0], Y: p[1], Z: p[2], Confidence: p[3]}
- Context: Engine.Fuse() converting fusion grid peaks to blobs
- Pattern: Value-type construction from 4-element peak array [x, y, z, confidence]
Pattern 3: Slice allocation and copying
3.1 tracking/tracker.go:199-203 - Return snapshot (deep copy)
out := make([]Blob, len(t.blobs))
for i, b := range t.blobs {
out[i] = *b
trail := make([][2]float64, len(b.Trail))
copy(trail, b.Trail)
out[i].Trail = trail
}
- Context: Tracker.Update() returning immutable snapshot
- Pattern: Dereference pointer, deep-copy trail slice
3.2 tracker/tracker.go:193-199 - Return 3D snapshot (deep copy)
out := make([]Blob, len(t.blobs))
for i, b := range t.blobs {
out[i] = *b
trail := make([][3]float64, len(b.Trail))
copy(trail, b.Trail)
out[i].Trail = trail
out[i].ukf = nil
}
- Context: Tracker.Update() returning immutable snapshot
- Pattern: Similar to 3.1 but clears ukf field for caller safety
3.3 tracker/identity.go:201 (GetAllBlobs), copy at 205-206 - Get all blobs copy
result := make([]Blob, len(tm.blobs))
copy(result, tm.blobs)
- Context: TrackManager.GetAllBlobs() returning all blobs
- Pattern: Slice copy operation
Pattern 4: automation.TrackedBlob construction
4.1 cmd/mothership/main.go:2213 - Automation blob conversion
autoBlobs[i] = automation.TrackedBlob{
// fields populated
}
- Context: Converting blobs to automation engine format
- Pattern: Cross-package type conversion
Pattern 5: signal.TrackedBlob construction
5.1 cmd/mothership/main.go:5384 - Fusion result to tracked blob
b := sigproc.TrackedBlob{
ID: id,
X: pk.X,
Y: pk.Y,
Z: pk.Z,
Weight: pk.Confidence,
}
- Context: blobTracker.track() converting fusion peaks to tracked blobs
- Pattern: Type conversion from fusion.Blob to signal.TrackedBlob
Pattern 6: Test data construction
6.1 fusion/fusion_test.go:631 - Test fixture
Blobs: []Blob{{X: 2, Y: 1, Z: 2, Confidence: 0.85}}
- Context: Test data creation
- Pattern: Inline slice literal with struct literals
6.2 fusion/fusion_test.go:680 - Test fixture
Blobs: []Blob{{X: 2, Y: 1, Z: 2, Confidence: 0.80}}
6.3 fusion/fusion_test.go:700 - Test fixture
result := &Result{Blobs: []Blob{{X: 1, Y: 1, Z: 1, Confidence: 0.5}}}
Files That Update Blob Fields
Identity assignment (tracker/identity.go)
These functions operate on
tracker.Blob(the 3D tracker), whose identity fields arePersonID,PersonLabel,PersonColor,IdentityConfidence,IdentitySource,IdentityLastSeen. The extra fieldsPersonName,AssignedColor,IdentityResolvedbelong only totracking.Blob(2D).
applyIdentity() - Lines 164-176
func (tm *TrackManager) applyIdentity(blob *Blob, info *IdentityInfo, now time.Time) {
blob.PersonID = info.PersonID
blob.PersonLabel = info.PersonLabel
blob.PersonColor = info.PersonColor
blob.IdentityConfidence = info.IdentityConfidence
blob.IdentityLastSeen = now
if info.IdentitySource != "" {
blob.IdentitySource = info.IdentitySource
} else {
blob.IdentitySource = "ble_triangulation"
}
}
- Context: Applying BLE identity match to blob
- Pattern: Field mutation on existing blob pointer
clearIdentity() - Lines 179-185
func (tm *TrackManager) clearIdentity(blob *Blob) {
blob.PersonID = ""
blob.PersonLabel = ""
blob.PersonColor = ""
blob.IdentityConfidence = 0
blob.IdentitySource = ""
}
- Context: Clearing identity when match expires
- Pattern: Resetting identity fields to defaults
Related Blob-shaped projection types
Beyond the five primary Blob types above, the codebase defines seven additional
Blob*-named structs. These are projections — read-only views built from a
tracked blob for a specific subsystem, not new tracked entities. They do not own a
UKF or a stable session ID. They matter for this inventory because any change to
blob fields must be propagated to the projections that copy those fields.
| Type | File:line | Built from | Purpose |
|---|---|---|---|
tracking.BlobEvent |
tracking/tracker.go:52 |
tracking.Blob |
Lifecycle event emitted on blob appear/disappear/re-ident (security-mode persistence, timeline) |
falldetect.BlobSnapshot |
falldetect/detector.go:69 |
tracker.Blob |
Z-trajectory input to the fall-detection state machine |
explainability.BlobSnapshot |
explainability/handler.go:95 |
tracker.Blob |
Per-link contribution / confidence breakdown for the "Why?" overlay |
explainability.BlobExplanation |
explainability/handler.go:27 |
derived | Rendered explanation result (not a direct blob copy) |
volume.BlobState |
volume/shape.go:139 |
tracked blob pos/vel | Input to spatial trigger volume point-in-volume tests (automation) |
volume.BlobPos |
volume/shape.go:1080 |
blob pos | Lightweight position used inside the volume containment math |
api.BlobPos |
api/triggers.go:624 |
blob pos | REST/JSON-facing position used by trigger evaluation in the API layer |
replay.BlobUpdate |
replay/types.go:303 |
replay pipeline blob | Incremental blob frame pushed to the dashboard during time-travel replay |
simulator.BlobResult |
simulator/engine.go:80 |
synthetic walker | Synthetic blob emitted by spaxel-sim (test fixture, not production) |
Construction pattern (all projections): value-type struct literal
(SomeBlobSnapshot{ID: b.ID, X: b.X, ...}) at the boundary where a tracked blob
enters the subsystem.
Enumerated projection construction sites (non-test, verified 2026-07-06) — every place a projection is built. A field added to a tracked blob that a projection copies must be propagated at each of these sites:
| Site | Type built | Built from | Notes |
|---|---|---|---|
cmd/mothership/main.go:2116 |
explainability.BlobSnapshot |
tracked blob | "Why?" overlay input; loop over all blobs |
cmd/mothership/main.go:2236 |
volume.BlobPos |
tracked blob | volume-trigger evaluation; loop over all blobs |
explainability/handler.go:194,255,357 |
BlobExplanation |
derived | rendered explanation result (3 return sites) |
falldetect/detector.go:277 |
BlobSnapshot |
tracked blob | Z-trajectory input to fall-detect state machine |
replay/pipeline.go:114,132 |
BlobUpdate |
replay blob | incremental frames pushed to dashboard during replay |
simulator/engine.go:460 |
BlobResult |
synthetic walker | emitted by spaxel-sim (test fixture, not production) |
tracking/tracker.go:173,188 |
BlobEvent |
tracked blob | appear/disappear lifecycle events |
volume/shape.go:375,575,820,879 |
BlobState |
tracked blob | per-blob state in volume trigger state machine (4 sites) |
Re-locate any moved site with:
grep -rn "BlobSnapshot{\|BlobState{\|BlobPos{\|BlobUpdate{\|BlobEvent{\|BlobResult{\|BlobExplanation{" mothership/
Key Findings
Files Requiring Updates for Blob Structure Changes
-
mothership/internal/tracking/tracker.go(line 160)- Constructor for new 2D blobs
-
mothership/internal/tracker/tracker.go(line 162)- Constructor for new 3D blobs with posture
-
mothership/internal/fusion/fusion.go(line 260)- Constructor for fusion result blobs
-
mothership/cmd/mothership/main.go(lines 2213, 5384)- Type conversion constructors for automation and signal packages
-
mothership/internal/tracker/identity.go(lines 164-185)- Identity field assignment (
applyIdentity) and clearing (clearIdentity)
- Identity field assignment (
Creation Patterns by Type
| Blob Type | Construction Method | Typical Context |
|---|---|---|
tracking.Blob |
&Blob{} |
New track from measurement |
tracker.Blob |
&Blob{} |
New 3D track from measurement |
fusion.Blob |
Blob{} |
Peak detection result |
automation.TrackedBlob |
TrackedBlob{} |
Automation trigger evaluation |
signal.TrackedBlob |
TrackedBlob{} |
Fusion to tracking pipeline |
Identity Fields Affected
When updating blob identity fields, these files need changes:
- Constructors:
tracking/tracker.go:160(2D) andtracker/tracker.go:162(3D) — initialize new fields - Identity matching:
tracker/identity.go:164-185—applyIdentity()andclearIdentity()(operate ontracker.Blobonly) - Type conversions:
cmd/mothership/main.go:2213(automation) and:5384(signal) - Field-set caveat:
tracking.Blob(2D) carriesPersonName,AssignedColor,IdentityResolved;tracker.Blob(3D) does not. Adding an identity field to one type does not automatically add it to the other — both definitions must be edited deliberately.
Recommendations
- For adding new identity fields: Update all 5 creation sites + the 2 identity functions
- For changing blob structure: Update the 5 type definitions, all constructors, and every projection type in the table above that copies the changed field
- For identity field logic: Focus on
tracker/identity.go(note: only the 3D tracker has identity functions today) - For testing: Update
fusion_test.gofixtures when structure changes - For projection types: Run the grep in the projection-types section to find each boundary construction site before changing copied fields
Acceptance Criteria Status
- All blob creation sites are identified and listed
- Each site is documented with file path and line number
- Creation pattern is noted (constructor, literal, factory, etc.)
- Report is ready for the next bead to use
Totals: 5 primary Blob types · 8 primary construction sites (3 direct struct literals + 3 slice/copy snapshots + 2 cross-package conversions) · 2 identity field-mutation functions · 9 additional Blob-shaped projection types · 15 projection construction sites enumerated across 7 files.