ADR-0045: Spector Memory Import & Export Pipeline¶
| Field | Value |
|---|---|
| Status | Accepted (Implemented) |
| Date | 2026-08-13 |
| Authors | Spector Maintainers & Architecture Working Group |
| Deciders | Spector Technical Steering Committee (TSC) |
| Supersedes | None |
| Superseded By | None |
| Last Verified | 2026-09-24 (implemented & verified via SpectorMemoryPortabilityGoldenTest) |
0. Status History & Implementation Resolution¶
0.1 Resolution — 2026-09-24 (issue #981, memory-portability Groups 1–4)¶
This ADR returned to Accepted (Implemented) upon successful implementation and verification of Groups 1–4 of the memory-portability specification:
- Container & Format Reconciliation: Standard ZIP archive with per-entry DEFLATE;
manifest.jsonat root;nodes/chunk-NNNNN.jsonlstreaming chunks;vectors/chunk-NNNNN.binordinal-aligned IEEE 754 float vectors;graph/edges.jsonl,graph/hyperedges.jsonl, andgraph/facts.jsonl. - Export Engine:
SpectorMemoryExporterreads live memory viaSpectorMemoryResolvercursor-stable enumeration, streaming chunks, Hebbian graph edges, typed hyperedges (HyperEntityGraphMemory), and temporal facts. - Import Engine:
SpectorMemoryImporterdecodes multi-chunks, resolves graph IDs to new slot indices, reconstructs Hebbian associations, typed hyperedges (TYPE_CONTRADICTS), temporal facts, reconciles derived indexes per ADR-0082, and executes within an atomic staging namespace lifecycle. - Golden Gate Verification: Passed
SpectorMemoryPortabilityGoldenTest(export → wipe → import with 100% ID, text, tags, and vector bit-identity parity, Hebbian edge parity, typed hyperedge parity, temporal facts parity, double-import idempotency, and explicit demonstration of failure against legacy fixture scaffolding).
0.2 Status correction — 2026-09-23 (issue #981)¶
This ADR was marked Accepted (Implemented) and "Verified against main" on 2026-09-16. It is not implemented. A review against main @ 09f1f2d7 found that SpectorExportJobConfig holds no reference to a memory engine — no SpectorMemory field, constructor parameter, or import — and is therefore structurally incapable of reading a namespace. Every .smb member was a hardcoded literal:
| Member | What was actually written |
|---|---|
manifest.json | hardcoded schemaVersion "2.0.0"; no embed model, no dims, no namespace id |
nodes/chunk-00001.jsonl | two sample rows ("Spector cognitive memory initialized", "Spring Batch pipeline configured") |
vectors/vectors-dim1536.bin | four literal bytes {0x00,0x01,0x02,0x03} |
graph/edges.jsonl | one invented DEPENDS_ON edge |
subsystems/state.json | literal invented subsystem values |
security/keys.json | a literal AES-256-GCM claim — no encryption code exists anywhere in the product |
validateExportStep then rewrote the manifest, adding counts of those fixtures and "verified": true. On the import side the node, graph and vector-index steps were log.info no-ops: nothing was parsed, nothing was written, and no memory id was ever read. E2EMigrationParityTest was annotated "verify 100% parity" but only SHA-256'd a hand-built directory through a zip round trip — and returned early, passing unconditionally, whenever its source directory was absent, which it always is in CI.
The practical consequence: an operator following this ADR to migrate a namespace or take a portable backup would have received a bundle containing none of their data, with "verified": true in its manifest, and imported it to a log line reporting success. Silent total data loss presented as success.
All affected steps now throw UnsupportedOperationException. Producing or consuming an .smb bundle is disabled. The design in this ADR is sound and is retained as the target; implementation is owned by spectrayan/.kiro/specs/memory-portability, which depends on embedder identity being persisted first (memory-durability-contract R3) and on the cursor-stable listing path (namespace-scale-and-observability R4). This ADR returns to Accepted (Implemented) only when that spec's golden test passes — export → wipe → import, with memory id, vector and graph-edge parity — and is demonstrated to fail against a fixture-based implementation.
0.1 Format divergences between this ADR and the code — Resolved¶
Resolved under memory-portability (Task 1.1, R3, R6):
| Feature | Code & ADR Reconciliation | Resolution |
|---|---|---|
| Container format | .smb is a standard ZIP archive with per-entry DEFLATE (java.util.zip) | Amended to ZIP (R6.1): Manifest-first refusal (R3.3, V6) requires random-access to manifest.json before unpacking gigabytes; tar.zst is a solid stream requiring decompressing preceding bytes. |
| Member compression | Individual members use standard entry deflate | Amended (R6.2): graph/edges.jsonl and nodes/chunk-NNNNN.jsonl are uncompressed-named; compression is handled per-entry by ZIP. |
| Vector naming & dims | Manifest records embedding.dimensions; vector files are vectors/chunk-NNNNN.bin | Amended (R6.3, R6.4): Dims are no longer encoded into filenames (vectors-dim1536.bin). Codec test and real output use vectors/chunk-NNNNN.bin. |
| Checksums & javadoc | Per-member SHA-256 recorded in manifest; javadoc corrected | Amended (R3.2): Codec javadoc and manifest record SHA-256 hashes per member rather than fictitious CRC32 claims. |
Also note: the codec archives regular files only, so an empty member directory does not survive the round trip (SpectorBundleArchiveFidelityTest#emptyDirectoriesAreNotPreserved). Any implementation validating members by directory presence must account for that.
1. Context¶
Spector Memory stores rich cognitive state across multiple heterogeneous tiers:
- Memory text contents, tags, key-value attributes, salience scores, decay values, and importance estimates
- High-dimensional vector embeddings (HNSW indices and raw float arrays)
- Cognitive hypergraphs (entities, hyperedges, and Hebbian synaptic coactivation weights)
- Biological subsystem states (Hippocampus, Amygdala, Insula, Dopamine levels)
- Partition encryption headers, keys, and transactional write-ahead logs (WAL)
As Spector Memory evolves, schemas, index layouts, vector dimensions, and biological model configurations undergo major upgrades across releases. To enable zero-downtime migrations, disaster recovery, cloud backups, and offline data transfer, Spector requires a robust, high-throughput, chunk-oriented import and export pipeline.
2. Problem Statement¶
Migrating or backing up multi-gigabyte cognitive memory states introduces critical architectural challenges:
- Memory Pressure & OOM Hazards: Ingesting or dumping millions of high-dimensional vectors and graph nodes into monolithic heap objects inevitably triggers Garbage Collection pauses or JVM
OutOfMemoryErrorfailures. - Dual Operational Contexts: Administrators require both online live backups via Synapse REST/gRPC endpoints and offline maintenance operations via the CLI (
spectorctl) for air-gapped or disaster-recovery environments. - CLI Latency vs Heavy Runtimes: Standard CLI invocations (
spectorctl status,spectorctl version) must start in under 100 milliseconds and cannot tolerate a 2–3 second Spring Boot bootstrap delay. - Data Completeness: An export cannot simply be a raw database dump; it must capture full semantics, vector indices, hypergraph topologies, and affective biological parameters in a portable format.
3. Decision Drivers¶
- Chunked Streaming & Bounded Heap: All import and export operations must execute in configurable streaming chunks (e.g., 1,000 items/chunk) to keep heap consumption strictly constant regardless of total corpus size.
- Resumability & Checkpointing: Long-running migration jobs must maintain persistent state to support pause, cancel, and checkpointed resume operations upon network or host failures.
- Dual-Mode Ergonomics: Provide instant sub-100ms CLI execution in online mode by delegating to Synapse, while supporting a standalone embedded execution mode for offline air-gapped clusters.
- Comprehensive Encapsulated Format: The backup archive must be self-contained, compressed, checksummed, and versioned.
4. Considered Options¶
Option 1: Custom Ad-Hoc Streaming Scripts¶
- Implement bespoke file-streaming threads and socket serializers within
spector-synapse. - Verdict: Rejected. Fragile, difficult to maintain, lacks standardized job tracking, metrics, retry semantics, and checkpointing.
Option 2: Apache Camel Route-Based Data Flow¶
- Leverage Camel enterprise integration routes to marshal and unmarshal components.
- Verdict: Rejected for batch migrations. Camel excels at real-time message exchange and streaming endpoints, but lacks native chunk-step-job transaction coordination and job-repository semantics.
Option 3: Spring Batch in synapse/spector-batch with Dual-Mode CLI (Selected)¶
- Locate the core batch migration engine within
synapse/spector-batchusing Spring Batch's battle-testedItemReader,ItemProcessor, andItemWriterabstractions. - Adopt a dual-mode CLI where
spectorctldelegates to Synapse REST APIs by default, but provides an embedded--offlinemode for standalone maintenance. - Bundle exports into a standardized
.smb(ZIP container with per-entry DEFLATE compression). - Verdict: Accepted. Delivers industrial-grade chunk processing, progress tracking, and low-latency CLI interactions.
5. Decision Outcome¶
5.1 Spring Batch Engine Location & Scoping¶
The batch processing engine is isolated in synapse/spector-batch:
- Chunk Processing Pipeline:
ItemReader,ItemProcessor, andItemWriterabstractions stream nodes, memory texts, tags, vectors, and graph edges in configurable chunk sizes (default 1,000 items/chunk). - Execution Persistence:
JobRepositorybacked by H2 (in-memory or file-based for CLI) or Spring JDBC tracks step progress, execution parameters, and failure checkpoints. - Auto-Configuration: Packaged as
SpectorBatchAutoConfigurationwith explicit export (SpectorExportJobConfig) and import (SpectorImportJobConfig) pipelines.
5.2 Dual-Mode CLI Architecture¶
We adopt a split execution model:
-
Online Mode (Default):
spectorctl memory exportconnects tospector-synapseREST API (/api/v1/migration/export).- Synapse executes the Spring Batch job asynchronously.
spectorctlstreams progress via Server-Sent Events (SSE) or polls job execution status. Startup time remains <100ms.
-
Offline / Standalone Mode (
--offline):spectorctl memory export --offlinelaunches an embedded Spring Batch context directly inside the CLI usingpicocli-spring-boot-starter.- Used for air-gapped environments or emergency disaster recovery when Synapse is down.
5.3 Spector Memory Bundle (.smb) Container Format¶
Exports are archived into a compressed .smb (standard ZIP container with per-entry DEFLATE compression) containing structured partitions:
manifest.json: Schema version 3.0.0, embedding descriptor (model,dimensions,quantizer),namespaceId,counts(records, edges, hyperedges, facts), per-member SHA-256 checksums, andsourceBuildVersion.nodes/chunk-NNNNN.jsonl: Full memory items (node IDs, text, tags, key-values, salience, importance, decay).vectors/chunk-NNNNN.bin: Raw float arrays, ordinal-aligned to nodes and described by manifest.graph/edges.jsonl: Cognitive hypergraph connections, relation attributes, and Hebbian weights with endpoint IDs.graph/hyperedges.jsonl: Typed hyperedges and roles (HyperEntityGraphMemory).graph/facts.jsonl: Temporal facts and validity intervals.subsystems/state.json: Real biological subsystem parameters (or omitted).security/keys.json: Omitted until Phase 6 DEK exists.
flowchart LR
subgraph Clients
CLI_Online["spectorctl memory export"]
CLI_Offline["spectorctl memory export --offline"]
WebUI["Cortex Admin UI"]
end
subgraph Synapse ["Spector Synapse Server"]
REST_API["Migration REST Controller"]
JobLauncher_Server["Spring Batch JobLauncher"]
end
subgraph CoreBatch ["synapse/spector-batch Module"]
ExportJob["Export Job Pipeline"]
ImportJob["Import Job Pipeline"]
SMB_Codec["Spector Memory Bundle (.smb) Codec"]
end
CLI_Online -->|REST / SSE| REST_API
WebUI -->|REST| REST_API
REST_API --> JobLauncher_Server
CLI_Offline -->|Embedded Spring Context| ExportJob
JobLauncher_Server --> ExportJob
JobLauncher_Server --> ImportJob
ExportJob --> SMB_Codec
ImportJob --> SMB_Codec 6. Pros and Cons of the Options¶
Positive¶
- Bounded Memory Footprint: Chunked streaming guarantees that heap consumption remains flat even when processing multimillion-node memory bundles.
- Comprehensive Preservation: Full fidelity preservation of vectors, graphs, and affective biological states without data degradation.
- Fast CLI Interaction: Online mode keeps the CLI startup latency under 100ms by avoiding JVM Spring context initialization.
- Resilient Recovery: In-flight job states are committed incrementally to
JobRepository, enabling automated resume after network hiccups or JVM restarts.
Negative / Trade-offs¶
- Packaging Footprint: Including embedded batch dependencies in
spector-cliincreases the binary JAR distribution size. - Archive Extraction Bounds: While ZIP per-entry DEFLATE provides fast random-access inspection of
manifest.jsonprior to disk writes, chunk extraction must be bounded and monitored to avoid I/O bottlenecks on low-throughput disk volumes.
7. Implementation Plan¶
-
Batch Core Implementation (
synapse/spector-batch):- Implement
SpectorBundleCodecsupporting.smbarchive packaging with ZIP per-entry DEFLATE and SHA-256 member verification. - Implement
SpectorExportJobConfigandSpectorImportJobConfigdefining readers, processors, and writers. - Implement
ReflectConsolidationJobConfigandSpringBatchReflectSweepExecutorfor background consolidation sweeps.
- Implement
-
REST Integration (
synapse/spector-synapse):- Expose asynchronous endpoints
/api/v1/migration/exportand/api/v1/migration/import. - Expose Server-Sent Events (SSE) stream for real-time progress monitoring.
- Expose asynchronous endpoints
-
CLI Integration (
synapse/spector-cli):- Wire Picocli command tree for
spectorctl memory exportandspectorctl memory import. - Support
--offlineflag to trigger embedded batch executor when running out-of-band.
- Wire Picocli command tree for
8. Code Reference & Verification¶
All batch components and pipelines are implemented and verified in the repository:
- Batch Core & Auto-Configuration:
synapse/spector-batch/src/main/java/com/spectrayan/spector/batch/SpectorBatchAutoConfiguration.java - Bundle Codec & Archive Formatting:
synapse/spector-batch/src/main/java/com/spectrayan/spector/batch/SpectorBundleCodec.java - Batch Service & Lifecycle:
synapse/spector-batch/src/main/java/com/spectrayan/spector/batch/SpectorBatchService.java - Import & Export Job Configurations:
synapse/spector-batch/src/main/java/com/spectrayan/spector/batch/SpectorExportJobConfig.javasynapse/spector-batch/src/main/java/com/spectrayan/spector/batch/SpectorImportJobConfig.java
- Reflective Consolidation Pipeline:
synapse/spector-batch/src/main/java/com/spectrayan/spector/batch/ReflectConsolidationJobConfig.javasynapse/spector-batch/src/main/java/com/spectrayan/spector/batch/SpringBatchReflectSweepExecutor.java