Authoritative contracts between UI, ingestion, persistence, event processing, and local inference layers.
This document defines the explicit contracts that allow Aevum teams to build, test, and evolve the system without breaking ingestion, persistence, provenance, companion behavior, or release truth. These are internal product contracts first. They are more important than any hypothetical public REST API at the current stage.
The document captures what the system must accept, what it must emit, what state transitions are allowed, and what must remain invariant across surfaces.
| Contract Layer | Purpose | Current Relevance |
|---|---|---|
| UI-to-Ingestion | Defines how any first-party input becomes a visible root entry. | Critical |
| Ingestion-to-Persistence | Defines how canonical root entries are written and how provenance is preserved. | Critical |
| Ingestion-to-Pipeline | Defines deferred enrichment events and post-save processing. | Critical |
| Behavior-to-Inference | Defines grounded companion invocation using persona/session/context. | Critical |
| App-to-Localhost API | Defines optional local inference gateway behavior. | Secondary |
| External-service contracts | Defines model delivery and any approved external dependencies. | Critical for disclosure |
The authoritative interface for first-party input is the canonical ingestion service, currently represented by UnifiedIngestionService.
| Operation | Purpose | Contract Rule |
|---|---|---|
captureImmediate(...) | Used for direct user-authored foreground inputs. | Must create exactly one visible root entry immediately. |
ingestImportedItem(...) | Used for a single imported artifact or extracted content block. | Must create a visible root entry immediately, not queue-only. |
ingestImportedBatch(...) | Used for multi-unit imports such as chunked docs or OCR batches. | Must create visible root entries for approved units immediately. |
appendDeferredEnrichment(...) | Schedules post-save enrichment against an existing root item. | Must never create a second root for the same input. |
captureImmediate(text: String, source: InputSource, context: ModelContext, confidence: Double = 1.0) -> MemoryEntry ingestImportedItem(text: String, source: InputSource, context: ModelContext) -> MemoryEntry ingestImportedBatch(nodes: [ImportedNode], source: InputSource, context: ModelContext) -> [MemoryEntry] appendDeferredEnrichment(rootEntryID: UUID, enrichmentType: String, sourceContext: String) async throws
| Surface | Ingress Operation | Required Provenance | Immediate Visibility |
|---|---|---|---|
| Dashboard typed input | captureImmediate | .text | Required |
| Dashboard voice input | captureImmediate | .voice | Required |
| CaptureSheet manual text | captureImmediate | .text | Required |
| CaptureSheet dictation | captureImmediate | .voice | Required |
| CaptureSheet camera OCR | ingestImportedItem or batch equivalent | .cameraOcr or approved equivalent | Required |
| CaptureSheet gallery OCR | ingestImportedItem or batch equivalent | .galleryOcr or approved equivalent | Required |
| Document import | ingestImportedBatch | .document | Required |
| Audio transcription import | ingestImportedItem | .voice or explicit import/audio source | Required |
| Habit action | captureImmediate or approved action-specific ingress | Approved system/habit source | Required |
| Legacy initialization | captureImmediate or approved initialization ingress | Approved system/legacy source | Required |
| Onboarding first reply | captureImmediate | User-authored source, not generic system by default | Required |
InputSource identifies where the raw inbound event came from. It preserves entry truth at the boundary between UI/import systems and the ingestion layer.
MemorySource defines how a persisted root entry is classified at storage level. A mapping layer between InputSource and MemorySource is expected and must be explicit.
InputSource --(explicit mapping)--> MemorySource
The mapping must not be implicit or scattered across views. It must live in one canonical place and be testable.
| Inbound | Persistence Intent | Contract Rule |
|---|---|---|
.text | User-authored text memory | Must remain user-authored, not reclassified as system inference. |
.voice | User-authored voice-derived memory | Voice provenance must survive capture and persistence. |
.system | System-originated or system-triggered action | If mapped to systemInference, that mapping must be documented and tested consistently. |
.deferredEnrichment | Non-root enrichment reference event | May never be treated as a fresh user capture. |
Deferred enrichment exists to append relationship, compression, merge, classification, or model-derived context after the root entry has already been persisted.
{
"rootEntryID": "UUID",
"enrichmentType": "semantic | merge | relation | other approved type",
"sourceContext": "dashboard | capture | import | habit | legacy | onboarding"
}
| Rule | Meaning |
|---|---|
| Single root write | Each user-triggered input event yields one primary root persistence event. |
| Visible immediacy | The user must see the result in logs/timeline immediately after accepted capture/import. |
| Deterministic provenance | Root write must retain truthful source classification. |
| No hidden mutation path | UI must not mutate root state through untracked shortcuts outside the canonical boundary. |
| ModelContext authority | Writes occur through approved SwiftData model contexts only. |
The live companion path must be grounded. It must not use placeholder persona/session objects or generic ungrounded synthesis when real local state exists.
| Step | Contract Requirement |
|---|---|
| Persona fetch | Fetch persisted active persona state or use a documented deterministic fallback. |
| Session fetch | Fetch active session state or use a documented deterministic fallback. |
| Memory retrieval | Retrieve bounded relevant local context before model invocation. |
| Prompt assembly | Build a bounded prompt package containing persona, session, context, and current input. |
| Inference call | Use the grounded invocation path, not a bare input-only shortcut. |
| Response composition | Answer the user’s actual question first; hooks are secondary. |
The local API is not the canonical CRUD layer for Aevum data. It is a narrow local inference gateway / execution hook and must not be treated as the primary source of truth for user memory state.
The native app persists through SwiftData and approved ingestion/pipeline flows. Any local HTTP endpoint must not bypass the canonical persistence and provenance rules.
| External Boundary | Contract | Release Truth Requirement |
|---|---|---|
| Cloudflare R2 model delivery | Used to download model artifacts. | Must be disclosed accurately in privacy/security/release materials. |
| Apple frameworks and permissions | Camera, microphone, speech, photos, calendar, Face ID and any others actually used. | Usage descriptions must match implementation exactly. |
| Widgets / App Intents / Siri surfaces | Must respect same persistence and provenance rules as app UI surfaces. | No shadow behavior or alternate truth. |
| Contract Area | Required Test Shape |
|---|---|
| Single root write | At least one orchestration-path test per major surface proving one input yields one root item. |
| Provenance | Tests must assert correct persisted source semantics. |
| Deferred enrichment | Tests must prove deferred enrichment is reachable and non-duplicative. |
| Import route | Tests must prove the UI route reaches the actual importer. |
| Companion grounding | Tests must prove persona/session/context retrieval are used by the live path. |
| Criterion | Success Condition |
|---|---|
| Interface clarity | All teams can identify which layer owns each operation without ambiguity. |
| Ingestion discipline | Every first-party input surface maps to a documented contract path. |
| Persistence integrity | Root writes, provenance, and enrichment behavior are testable and deterministic. |
| Release truth | Active interface docs describe the system as it really behaves today. |