feat(spatial): bind derived spatial state to explicit derivation lineage

Open
#511 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
35/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Active
Tech stack
rust
Domain
ai

Research direction

Start by reviewing the prerequisite contracts in #498, #528, and #520, then compare their boundaries with the proposed SpatialStateLineageV1 and SpatialDerivationRef shapes. Define the typed input and parent roles, separate state and lineage digests, and validate the listed replay invariants and qualification regressions, including missing parents, self-parenting, cycles, and unsupported schemas.

Written by the indexing model from the issue text.

Description

Purpose

Define one replayable, content-addressed provenance contract for derived spatial state.

This is intentionally broader than SpatialBelief<T>. The first deterministic mapper (#530) should produce a derived geometric evidence field, while a later separately qualified inference step may derive an actual physical occupancy belief from that evidence.

The lineage substrate should work for both without pretending they have the same epistemic meaning.

Core theorem

input evidence/state
      +
exact derivation recipe
      ↓
derived spatial state

must retain enough identity to reconstruct what inputs were used, what procedure transformed them, and what exact output state resulted.

But:

derivation provenance
      !=
truth
      !=
confidence
      !=
currentness
      !=
belief authority
      !=
action authority

Persistence of lineage is non-authorizing.

Why evidence references alone are insufficient

The same input evidence can yield different outputs under different algorithms, model revisions, transforms, calibration, parameters, or fusion rules:

same evidence
 + recipe A
 -> state A

same evidence
 + recipe B
 -> state B

Conversely, different valid histories can sometimes produce byte-identical state. State identity and history identity must therefore remain separate.

Proposed V1 shape

Conceptually:

SpatialStateLineageV1
├── state_kind
├── state_schema_version
├── derivation_ref
├── direct_input_refs[]
├── parent_state_refs[]
├── output_state_digest
└── lineage_digest

A small content-addressed derivation identity may be:

SpatialDerivationRef
├── namespace / producer identity
├── local derivation id
├── generation
└── derivation_digest

derivation_digest binds the canonical replay recipe/configuration. Depending on state kind, that record may include algorithm identity/version, implementation revision, grid specification, camera model, transform/calibration lineage, conflict rule, resource budget, uncertainty model, observation-likelihood model, or other replay-critical semantics.

Preserve input roles

Do not flatten all inputs into one untyped digest vector.

Direct inputs should preserve semantic role, conceptually:

DirectSpatialInputV1
├── SpatialStatement(ref)
├── Calibration(ref)
├── Transform(ref)
├── ClockScale(ref)          // only if later introduced
└── OtherQualifiedInput(...)

Parent derived states belong in parent_state_refs[], not in the direct-observation list.

This prevents a prior map/belief digest from masquerading as fresh sensor evidence.

Recursive incremental updates

A realistic streaming update is:

State_t
 + newly admitted direct inputs
 + exact derivation recipe
 -> State_t+1

so provenance is a DAG, not a repeatedly flattened evidence list.

Important invariants:

  1. prior states are not silently reclassified as fresh evidence;
  2. direct evidence remains separately addressable through graph depth;
  3. repeated evidence entering through an ancestor and again as a new direct input can be detected by the owning fusion/replay logic;
  4. missing/unresolved parents fail replay rather than being ignored;
  5. no state may directly name itself as a parent;
  6. replay resolution detects cycles rather than recursing indefinitely.

A small reference object alone does not prove global DAG validity; full graph validation belongs to the replay resolver/verifier.

Separate state and lineage identity

Use different identities for output bytes and derivation history:

output_state_digest = hash(canonical state bytes only)

lineage_digest = hash(
    state kind/schema
  + derivation recipe identity
  + typed direct inputs
  + parent state refs
  + output_state_digest
)

This permits:

same output_state_digest
+ different valid history
-> different lineage_digest

which is expected for commutative streaming accumulators reached through different ingestion orders.

Likewise, identical recipe/input lineage with different stored output bytes is detectable because output_state_digest differs.

State-kind boundary

state_kind is descriptive/type identity, not authority.

Examples:

geometric_evidence_field
physical_occupancy_belief
object_relational_state
photometric_surface_field

A geometric evidence field must not become a belief merely by changing a string. The owning Rust type/constructor and qualified derivation transition establish the semantic boundary.

Intended sequence:

SpatialObservation
      ↓
SparseGeometricEvidenceFieldV1       (#530)
      ↓
qualified/calibrated belief extraction
      ↓
SpatialBelief<PhysicalOccupancyState>
      ↓
object / dynamic / semantic state
      ↓
photometric renderer

Every arrow may have lineage; the arrows do not grant one another authority automatically.

Replay / persistence

Persisted lineage cannot recreate runtime evidence admission, runtime belief authority, or currentness.

Reconstitution requires either:

  1. rerunning the exact qualified derivation from appropriately admitted/resolved inputs and comparing output identity; or
  2. a separately qualified replay/verifier boundary that establishes equivalent output and authority conditions.

A persisted derivation_ref + output_state_digest is evidence of recorded provenance, not a runtime capability.

Relationship to #530

#530 should use this lineage for SparseGeometricEvidenceFieldV1 without requiring BeliefSupport just to aggregate observations.

A later evidence-field -> occupancy-belief transition should produce a new state kind and new lineage and consume whatever bounded belief-support / calibrated inference authority is appropriate.

Qualification requirements

Require regressions proving at least:

  • same direct evidence + different derivation recipe -> distinguishable lineage;
  • changed recipe/config bytes -> changed derivation identity;
  • same state bytes reached through different valid parent chains -> same state digest, different lineage digest;
  • changed output bytes -> changed output state digest;
  • parent state and direct observation roles cannot be substituted;
  • repeated evidence through parent + direct input is detectable where the owning derivation forbids reuse;
  • persisted lineage retains exact parents/inputs/recipe/output identity but grants no runtime authority;
  • missing parent fails replay;
  • direct self-parenting is rejected;
  • cyclic lineage resolution fails closed;
  • unknown/unsupported state/derivation schema fails closed;
  • replay-critical transform/calibration/model/config revisions cannot be omitted by the owning derivation adapter.

Ordering

#495 protected spatial HDC
      ↓
#498 metric/frame/time/evidence foundation
      ↓
#528 generic observation admission
      ↓
#520 exact spatial statement binding
      ↓
#511 derived-state lineage
      ↓
#530 deterministic geometric evidence field
      ↓
qualified belief extraction
      ↓
objects / dynamics / Gaussian-surface renderer

This issue should remain a prerequisite for promoting the first persistent derived spatial state beyond a throwaway fixture, but should not expand #498 while #498 intentionally contains no fusion implementation.

Dominant language
Rust
Stars
9
Forks
1
Avg merge
15m
Merged PRs (30d)
8

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Luminous-Dynamics/symthaea

All issues in Luminous-Dynamics/symthaea

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.