specter-navigator-gadget

plurigrid's avatarfrom plurigrid

Unified Specter/Navigator/3-MATCH architecture with bidirectional path compilation

⭐1stars🔀2forks📁View on GitHub🕐Updated Jan 9, 2026

When & Why to Use This Skill

The Specter Navigator Gadget is a high-performance developer tool designed for the bidirectional navigation and transformation of complex, nested data structures. By unifying the Specter architecture with 3-MATCH constraint satisfaction, it allows for the creation of compiled path expressions that are both formally verifiable and highly efficient. This skill is essential for developers working with intricate data models, providing a robust framework for selecting, filtering, and modifying data with inline caching and 3-SAT-based satisfiability checking.

Use Cases

  • Complex Data Transformation: Efficiently updating or selecting values deep within nested dictionaries, arrays, or custom data structures using a single, unified path expression.
  • Formal Constraint Verification: Using 3-MATCH logic to verify that data traversal paths are satisfiable and logically consistent before execution, reducing runtime errors in complex systems.
  • AST and S-expression Manipulation: Navigating and refactoring code structures or abstract syntax trees (ASTs) for compiler development or macro-based meta-programming.
  • High-Performance Data Querying: Leveraging compiled Navigators and global inline caching to perform repetitive data selections at near-native speeds in performance-critical applications.
namespecter-navigator-gadget
descriptionUnified Specter/Navigator/3-MATCH architecture with bidirectional path compilation
sourceClojure Specter, SpecterACSet.jl, 3-MATCH constraint composition
licenseMIT
trit0
gf3_triad"möbius-path-filtering (-1) ⊗ specter-navigator-gadget (0) ⊗ color-envelope-preserving (+1)"
statusProduction Ready

Specter Navigator Gadget

Core Concept

Integration of Specter (bidirectional navigation), Navigator (compiled path objects), and 3-MATCH (constraint satisfaction) into a unified system for structure traversal and transformation.

A Navigator is a compiled path expression that can be used for both selecting and transforming values within nested data structures. Each Navigator encodes one or more constraints (Gadgets) from a 3-SAT-like problem space.

Architecture

Key Components

1. Navigator - Compiled path expressions

struct Navigator
    path::Vector{NavigationStep}  # Steps in the traversal
    constraints::Vector{Gadget}   # 3-MATCH constraints
    cache_key::UInt64            # Hash for inline caching
end

2. Gadget - Individual constraint unit

struct Gadget
    name::String
    predicate::Function           # Selection/filtering predicate
    compose_strategy::Symbol      # :all, :any, :sequential
end

3. Navigation Steps (various types)

  • ALL - Navigate to all collection members
  • keypath(key) - Navigate to dictionary key
  • pred(predicate) - Filter by predicate
  • SEXP_HEAD / sexp_nth(n) - S-expression navigation
  • INDEX(i) - Direct indexing

Compilation Pipeline

Path Expression
    ↓
coerce_nav() - converts to Navigator objects
    ↓
Constraint checking - verifies 3-MATCH satisfiability
    ↓
Inline caching via @late_nav / @compiled_select
    ↓
nav_select() / nav_transform() - execution

API

Macros

@late_nav(path_expr) Compiles and caches a navigation path, returning a reusable Navigator:

nav = @late_nav([ALL, pred(iseven)])
results = nav_select(nav, [1,2,3,4,5], x -> [x])
# => [2, 4]

@compiled_select(path, structure) Combines compilation, caching, and selection in one call:

results = @compiled_select([ALL, pred(iseven)], [1,2,3,4,5])
# => [2, 4]

Core Functions

coerce_nav(path_expr) :: Navigator Converts a path expression to a compiled Navigator object.

nav_select(nav::Navigator, structure, result_fn) :: Vector Selects all values matching the path, applies result_fn to each.

nav_transform(nav::Navigator, structure, transform_fn) :: Structure Transforms all values matching the path in-place.

compose_navigators(nav1, nav2) :: Navigator Composes two Navigators into one. Verifies 3-MATCH constraint satisfiability.

Performance Characteristics

Operation Time Notes
First @late_nav call O( path
Subsequent @late_nav O(1) Cache lookup
nav_select O(n⋅ path
Constraint checking O(m) m = number of gadgets, linear in constraint count

Integration with 3-MATCH

Each path expression can encode constraints that are verifiable via 3-SAT:

# Constraint 1: values must be even
# Constraint 2: values must be > 2
# Constraint 3: XOR of above (either even or >2, but not both)
nav = @late_nav([ALL, pred(x -> (iseven(x) && x ≤ 2) || (!iseven(x) && x > 2))])

The 3-MATCH system can:

  • Verify path compositions are satisfiable before execution
  • Detect infeasible path combinations early
  • Optimize constraint ordering for faster filtering

Bidirectionality

The same Navigator works for both selection and transformation:

# Select even numbers
selected = nav_select(nav, [1,2,3,4,5], x -> [x])

# Transform even numbers (multiply by 10)
transformed = nav_transform(nav, [1,2,3,4,5], x -> x * 10)
# => [1, 20, 3, 40, 5]

Caching Strategy

Global Cache: Dict{UInt64, Navigator}()

  • Key: hash(path_expr) - computed at compile time
  • Value: compiled Navigator object
  • Per-callsite - different code locations maintain separate entries

Cache Invalidation: Never (by design)

  • Paths are immutable after compilation
  • Cache entries are safe indefinitely
  • Memory is the only constraint

Composition with Möbius Filtering

See möbius-path-filtering skill for how non-orientable filtering eliminates invalid paths before Navigator compilation.

Composition with Color Envelopes

See color-envelope-preserving skill for how GF(3) color conservation is enforced across Navigator compositions.

Usage Patterns

Nested Dictionary Navigation

data = Dict(
  "users" => [
    Dict("name" => "Alice", "age" => 30, "active" => true),
    Dict("name" => "Bob", "age" => 25, "active" => false)
  ]
)

# Select all active users' names
nav = @late_nav([keypath("users"), ALL, pred(u -> u["active"]), keypath("name")])
active_names = nav_select(nav, data, x -> [x])
# => ["Alice"]

S-expression Navigation

sexp = :(define (square x) (* x x))

# Navigate to function definition head
nav = @late_nav([sexp_nth(1), SEXP_HEAD])
func_name = nav_select(nav, sexp, x -> [x])
# => :square

Constraint-based Filtering

# Find numbers that are odd AND greater than 5
nav = @late_nav([
  ALL,
  pred(x -> isodd(x) && x > 5)
])
results = nav_select(nav, [1,3,5,7,9,11], x -> [x])
# => [7, 9, 11]

Error Handling

InvalidPathError - Path expression doesn't compile UnsatisfiableConstraintError - 3-MATCH constraints are contradictory TypeMismatchError - Structure doesn't match expected shape for path

  • möbius-path-filtering - Eliminates topologically invalid paths
  • color-envelope-preserving - Maintains GF(3) color invariants
  • three-match - Core 3-SAT constraint satisfaction engine

References