syntax = "proto3";

package mnemara.v1;

enum RecallScorerKind {
  RECALL_SCORER_KIND_UNSPECIFIED = 0;
  RECALL_SCORER_KIND_PROFILE = 1;
  RECALL_SCORER_KIND_CURATED = 2;
}

enum RecallScoringProfile {
  RECALL_SCORING_PROFILE_UNSPECIFIED = 0;
  RECALL_SCORING_PROFILE_BALANCED = 1;
  RECALL_SCORING_PROFILE_LEXICAL_FIRST = 2;
  RECALL_SCORING_PROFILE_IMPORTANCE_FIRST = 3;
}

enum RecallPolicyProfile {
  RECALL_POLICY_PROFILE_UNSPECIFIED = 0;
  RECALL_POLICY_PROFILE_GENERAL = 1;
  RECALL_POLICY_PROFILE_SUPPORT = 2;
  RECALL_POLICY_PROFILE_RESEARCH = 3;
  RECALL_POLICY_PROFILE_ASSISTANT = 4;
  RECALL_POLICY_PROFILE_AUTONOMOUS_AGENT = 5;
}

enum EmbeddingProviderKind {
  EMBEDDING_PROVIDER_KIND_UNSPECIFIED = 0;
  EMBEDDING_PROVIDER_KIND_DISABLED = 1;
  EMBEDDING_PROVIDER_KIND_DETERMINISTIC_LOCAL = 2;
}

message MemoryScope {
  string tenant_id = 1;
  string namespace = 2;
  string actor_id = 3;
  optional string conversation_id = 4;
  optional string session_id = 5;
  string source = 6;
  repeated string labels = 7;
  string trust_level = 8;
}

message ArtifactPointer {
  string uri = 1;
  optional string media_type = 2;
  optional string checksum = 3;
}

message EpisodeSalience {
  uint32 reuse_count = 1;
  float novelty_score = 2;
  float goal_relevance = 3;
  float unresolved_weight = 4;
}

message AffectiveAnnotation {
  optional string tone = 1;
  optional string sentiment = 2;
  float urgency = 3;
  float confidence = 4;
  float tension = 5;
  string provenance = 6;
}

message EpisodeContext {
  uint32 schema_version = 17;
  string episode_id = 1;
  optional string summary = 2;
  string continuity_state = 3;
  repeated string actor_ids = 4;
  optional string goal = 5;
  optional string outcome = 6;
  optional uint64 started_at_unix_ms = 7;
  optional uint64 ended_at_unix_ms = 8;
  optional uint64 last_active_unix_ms = 9;
  optional string recurrence_key = 18;
  optional uint64 recurrence_interval_ms = 19;
  optional string boundary_label = 20;
  optional string previous_record_id = 10;
  optional string next_record_id = 11;
  repeated string causal_record_ids = 12;
  repeated string related_record_ids = 13;
  repeated string linked_artifact_uris = 14;
  EpisodeSalience salience = 15;
  optional AffectiveAnnotation affective = 16;
}

message LineageLink {
  string record_id = 1;
  string relation = 2;
  float confidence = 3;
}

message ConflictAnnotation {
  string state = 1;
  repeated string conflicting_record_ids = 2;
  float drift_score = 3;
  string resolution = 4;
  optional string resolved_by = 5;
  optional uint64 resolved_at_unix_ms = 6;
  optional string note = 7;
}

message MemoryRecord {
  string id = 1;
  MemoryScope scope = 2;
  string kind = 3;
  string content = 4;
  optional string summary = 5;
  map<string, string> metadata = 6;
  string quality_state = 7;
  uint64 created_at_unix_ms = 8;
  uint64 updated_at_unix_ms = 9;
  optional uint64 expires_at_unix_ms = 10;
  float importance_score = 11;
  optional string source_id = 12;
  optional ArtifactPointer artifact = 13;
  optional EpisodeContext episode = 14;
  optional string historical_state = 15;
  repeated LineageLink lineage = 16;
  optional ConflictAnnotation conflict = 17;
}

message UpsertMemoryRecordRequest {
  MemoryRecord record = 1;
  optional string idempotency_key = 2;
}

message UpsertMemoryRecordReply {
  string record_id = 1;
  bool deduplicated = 2;
  bool summary_refreshed = 3;
}

message BatchUpsertMemoryRecordsRequest {
  repeated UpsertMemoryRecordRequest requests = 1;
}

message BatchUpsertMemoryRecordsReply {
  repeated UpsertMemoryRecordReply receipts = 1;
}

message RecallFilters {
  repeated string kinds = 1;
  repeated string required_labels = 2;
  optional string source = 3;
  optional uint64 from_unix_ms = 4;
  optional uint64 to_unix_ms = 5;
  optional float min_importance_score = 6;
  repeated string trust_levels = 7;
  repeated string states = 8;
  bool include_archived = 9;
  optional string episode_id = 10;
  repeated string continuity_states = 11;
  bool unresolved_only = 12;
  optional string temporal_order = 13;
  optional string historical_mode = 14;
  optional string lineage_record_id = 15;
  optional string before_record_id = 16;
  optional string after_record_id = 17;
  repeated string boundary_labels = 18;
  optional string recurrence_key = 19;
  repeated string conflict_states = 20;
  repeated string resolution_kinds = 21;
  bool unresolved_conflicts_only = 22;
}

message RecallRequest {
  MemoryScope scope = 1;
  string query_text = 2;
  uint32 max_items = 3;
  optional uint32 token_budget = 4;
  bool include_explanation = 5;
  optional RecallFilters filters = 6;
}

message RecallScoreBreakdown {
  float lexical = 1;
  float semantic = 2;
  float graph = 3;
  float temporal = 4;
  float policy = 5;
  float total = 6;
  float metadata = 7;
  float curation = 8;
  float episodic = 9;
  float salience = 10;
}

message RecallExplanation {
  repeated string selected_channels = 1;
  repeated string policy_notes = 2;
  optional string trace_id = 3;
  optional RecallPlanningTrace planning_trace = 4;
  RecallScorerKind scorer_kind = 5;
  RecallScoringProfile scoring_profile = 6;
  optional string planning_profile = 7;
  RecallPolicyProfile policy_profile = 8;
}

message RecallTraceCandidate {
  string record_id = 1;
  string kind = 2;
  bool selected = 3;
  repeated string matched_terms = 4;
  string decision_reason = 5;
  RecallScoreBreakdown breakdown = 6;
  optional uint32 selection_rank = 7;
  repeated string selected_channels = 8;
  repeated string filter_reasons = 9;
  repeated string candidate_sources = 10;
  optional string planner_stage = 11;
  repeated string relation_reasons = 12;
}

message RecallPlanningTrace {
  string trace_id = 1;
  bool token_budget_applied = 2;
  repeated RecallTraceCandidate candidates = 3;
}

message RecallHit {
  MemoryRecord record = 1;
  RecallScoreBreakdown breakdown = 2;
  repeated string selected_channels = 3;
  repeated string policy_notes = 4;
  optional RecallExplanation explanation = 5;
}

message RecallReply {
  repeated RecallHit hits = 1;
  uint32 total_candidates_examined = 2;
  optional RecallExplanation explanation = 3;
}

message CompactRequest {
  string tenant_id = 1;
  optional string namespace = 2;
  bool dry_run = 3;
  string reason = 4;
}

message CompactReply {
  uint64 deduplicated_records = 1;
  uint64 archived_records = 2;
  uint64 summarized_clusters = 3;
  uint64 pruned_graph_edges = 4;
  bool dry_run = 5;
  uint64 superseded_records = 6;
  uint64 lineage_links_created = 7;
}

message SnapshotRequest {}

message SnapshotReply {
  string snapshot_id = 1;
  uint64 created_at_unix_ms = 2;
  repeated string namespaces = 3;
  uint64 record_count = 4;
  uint64 storage_bytes = 5;
  EngineTuningInfo engine = 6;
}

message DeleteRequest {
  string tenant_id = 1;
  string namespace = 2;
  string record_id = 3;
  bool hard_delete = 4;
  string audit_reason = 5;
}

message DeleteReply {
  string record_id = 1;
  bool tombstoned = 2;
  bool hard_deleted = 3;
}

message ArchiveRequest {
  string tenant_id = 1;
  string namespace = 2;
  string record_id = 3;
  bool dry_run = 4;
  string audit_reason = 5;
}

message ArchiveReply {
  string record_id = 1;
  string previous_quality_state = 2;
  string previous_historical_state = 3;
  string quality_state = 4;
  string historical_state = 5;
  bool changed = 6;
  bool dry_run = 7;
}

message SuppressRequest {
  string tenant_id = 1;
  string namespace = 2;
  string record_id = 3;
  bool dry_run = 4;
  string audit_reason = 5;
}

message SuppressReply {
  string record_id = 1;
  string previous_quality_state = 2;
  string previous_historical_state = 3;
  string quality_state = 4;
  string historical_state = 5;
  bool changed = 6;
  bool dry_run = 7;
}

message RecoverRequest {
  string tenant_id = 1;
  string namespace = 2;
  string record_id = 3;
  bool dry_run = 4;
  string audit_reason = 5;
  string quality_state = 6;
  optional string historical_state = 7;
}

message RecoverReply {
  string record_id = 1;
  string previous_quality_state = 2;
  string previous_historical_state = 3;
  string quality_state = 4;
  string historical_state = 5;
  bool changed = 6;
  bool dry_run = 7;
}

message StoreStatsRequest {
  optional string tenant_id = 1;
  optional string namespace = 2;
}

message NamespaceStats {
  string tenant_id = 1;
  string namespace = 2;
  uint64 active_records = 3;
  uint64 archived_records = 4;
  uint64 deleted_records = 5;
  uint64 suppressed_records = 6;
  uint64 pinned_records = 7;
}

message MaintenanceStats {
  uint64 duplicate_candidate_groups = 1;
  uint64 duplicate_candidate_records = 2;
  uint64 tombstoned_records = 3;
  uint64 expired_records = 4;
  uint64 stale_idempotency_keys = 5;
  uint64 historical_records = 6;
  uint64 superseded_records = 7;
  uint64 lineage_links = 8;
}

message EngineTuningInfo {
  RecallScorerKind recall_scorer_kind = 1;
  RecallScoringProfile recall_scoring_profile = 2;
  EmbeddingProviderKind embedding_provider_kind = 3;
  uint64 embedding_dimensions = 4;
  uint64 compaction_summarize_after_record_count = 5;
  uint32 compaction_cold_archive_after_days = 6;
  uint32 compaction_cold_archive_importance_threshold_per_mille = 7;
  optional string recall_planning_profile = 8;
  uint32 graph_expansion_max_hops = 9;
  RecallPolicyProfile recall_policy_profile = 10;
}

message StoreStatsReply {
  uint64 generated_at_unix_ms = 1;
  uint64 total_records = 2;
  uint64 storage_bytes = 3;
  repeated NamespaceStats namespaces = 4;
  MaintenanceStats maintenance = 5;
  EngineTuningInfo engine = 6;
}

message GraphInspectionRequest {
  optional string tenant_id = 1;
  optional string namespace = 2;
  optional string actor_id = 3;
  optional string conversation_id = 4;
  optional string session_id = 5;
  bool include_archived = 6;
  bool include_suppressed = 7;
  bool include_deleted = 8;
  optional uint32 max_nodes = 9;
}

message GraphInspectionNode {
  string record_id = 1;
  string tenant_id = 2;
  string namespace = 3;
  string actor_id = 4;
  string kind = 5;
  optional string summary = 6;
  string quality_state = 7;
  string historical_state = 8;
  optional string episode_id = 9;
  optional string continuity_state = 10;
  optional string conflict_state = 11;
  uint32 importance_per_mille = 12;
  uint64 updated_at_unix_ms = 13;
}

message GraphInspectionEdge {
  string source_id = 1;
  string target_id = 2;
  string kind = 3;
  repeated string details = 4;
}

message GraphInspectionReply {
  uint64 generated_at_unix_ms = 1;
  uint64 total_records_scanned = 2;
  repeated GraphInspectionNode nodes = 3;
  repeated GraphInspectionEdge edges = 4;
  bool truncated = 5;
}

message IntegrityCheckRequest {
  optional string tenant_id = 1;
  optional string namespace = 2;
}

message IntegrityCheckReply {
  uint64 generated_at_unix_ms = 1;
  bool healthy = 2;
  uint64 scanned_records = 3;
  uint64 scanned_idempotency_keys = 4;
  uint64 stale_idempotency_keys = 5;
  uint64 missing_idempotency_keys = 6;
  uint64 duplicate_active_records = 7;
}

message RepairRequest {
  optional string tenant_id = 1;
  optional string namespace = 2;
  bool dry_run = 3;
  string reason = 4;
  bool remove_stale_idempotency_keys = 5;
  bool rebuild_missing_idempotency_keys = 6;
}

message RepairReply {
  bool dry_run = 1;
  uint64 scanned_records = 2;
  uint64 scanned_idempotency_keys = 3;
  uint64 removed_stale_idempotency_keys = 4;
  uint64 rebuilt_missing_idempotency_keys = 5;
  bool healthy_after = 6;
}

message MaintenanceRunRequest {
  optional string tenant_id = 1;
  optional string namespace = 2;
  bool dry_run = 3;
  string reason = 4;
  bool run_integrity_check = 5;
  bool run_repair = 6;
  bool run_compaction = 7;
  bool remove_stale_idempotency_keys = 8;
  bool rebuild_missing_idempotency_keys = 9;
}

message MaintenanceRunReply {
  bool dry_run = 1;
  optional IntegrityCheckReply integrity_before = 2;
  optional RepairReply repair = 3;
  optional CompactReply compaction = 4;
  optional IntegrityCheckReply integrity_after = 5;
}

enum TraceOperationKind {
  TRACE_OPERATION_KIND_UNSPECIFIED = 0;
  TRACE_OPERATION_KIND_UPSERT = 1;
  TRACE_OPERATION_KIND_BATCH_UPSERT = 2;
  TRACE_OPERATION_KIND_RECALL = 3;
  TRACE_OPERATION_KIND_SNAPSHOT = 4;
  TRACE_OPERATION_KIND_STATS = 5;
  TRACE_OPERATION_KIND_INTEGRITY_CHECK = 6;
  TRACE_OPERATION_KIND_REPAIR = 7;
  TRACE_OPERATION_KIND_COMPACT = 8;
  TRACE_OPERATION_KIND_DELETE = 9;
  TRACE_OPERATION_KIND_ARCHIVE = 10;
  TRACE_OPERATION_KIND_SUPPRESS = 11;
  TRACE_OPERATION_KIND_RECOVER = 12;
  TRACE_OPERATION_KIND_EXPORT = 13;
  TRACE_OPERATION_KIND_IMPORT = 14;
  TRACE_OPERATION_KIND_MAINTENANCE_RUN = 15;
  TRACE_OPERATION_KIND_SNAPSHOT_SHIP = 16;
}

enum TraceStatus {
  TRACE_STATUS_UNSPECIFIED = 0;
  TRACE_STATUS_OK = 1;
  TRACE_STATUS_REJECTED = 2;
  TRACE_STATUS_ERROR = 3;
}

enum ImportMode {
  IMPORT_MODE_UNSPECIFIED = 0;
  IMPORT_MODE_MERGE = 1;
  IMPORT_MODE_REPLACE = 2;
  IMPORT_MODE_VALIDATE = 3;
}

message OperationTraceSummary {
  optional string record_id = 1;
  optional uint32 request_count = 2;
  optional string query_text = 3;
  optional uint32 max_items = 4;
  optional uint32 token_budget = 5;
  optional bool dry_run = 6;
}

message OperationTrace {
  string trace_id = 1;
  string correlation_id = 2;
  TraceOperationKind operation = 3;
  string transport = 4;
  optional string backend = 15;
  optional string admission_class = 16;
  optional string tenant_id = 5;
  optional string namespace = 6;
  optional string principal = 7;
  optional string store_span_id = 17;
  optional string planning_trace_id = 18;
  uint64 started_at_unix_ms = 8;
  uint64 completed_at_unix_ms = 9;
  uint64 latency_ms = 10;
  TraceStatus status = 11;
  optional string status_message = 12;
  optional OperationTraceSummary summary = 13;
  optional RecallExplanation recall_explanation = 14;
}

message ListTracesRequest {
  optional string tenant_id = 1;
  optional string namespace = 2;
  optional uint32 limit = 3;
  TraceOperationKind operation = 4;
  TraceStatus status = 5;
  optional uint64 before_started_at_unix_ms = 6;
}

message ListTracesReply {
  repeated OperationTrace traces = 1;
}

message GetTraceRequest {
  string trace_id = 1;
}

message PortableRecord {
  MemoryRecord record = 1;
  optional string idempotency_key = 2;
}

message ExportRequest {
  optional string tenant_id = 1;
  optional string namespace = 2;
  bool include_archived = 3;
}

message ExportReply {
  uint32 package_version = 1;
  uint64 exported_at_unix_ms = 2;
  SnapshotReply manifest = 3;
  repeated PortableRecord records = 4;
}

message ImportRequest {
  ExportReply package = 1;
  ImportMode mode = 2;
  bool dry_run = 3;
}

message ImportFailure {
  optional string record_id = 1;
  string reason = 2;
}

message ImportReply {
  ImportMode mode = 1;
  bool dry_run = 2;
  bool applied = 3;
  bool compatible_package = 4;
  string snapshot_id = 5;
  uint32 package_version = 6;
  uint64 validated_records = 7;
  uint64 imported_records = 8;
  uint64 skipped_records = 9;
  bool replaced_existing = 10;
  repeated ImportFailure failed_records = 11;
}

message SnapshotShipRequest {
  string target_url = 1;
  optional string bearer_token = 2;
  optional string tenant_id = 3;
  optional string namespace = 4;
  bool include_archived = 5;
  ImportMode mode = 6;
  bool dry_run = 7;
}

message SnapshotShipReply {
  string target_url = 1;
  uint64 exported_records = 2;
  uint64 imported_records = 3;
  uint64 skipped_records = 4;
  bool dry_run = 5;
  bool compatible_package = 6;
  uint32 remote_status = 7;
  optional string remote_snapshot_id = 8;
}

service MemoryService {
  rpc UpsertMemoryRecord(UpsertMemoryRecordRequest) returns (UpsertMemoryRecordReply);
  rpc BatchUpsertMemoryRecords(BatchUpsertMemoryRecordsRequest) returns (BatchUpsertMemoryRecordsReply);
  rpc Recall(RecallRequest) returns (RecallReply);
  rpc Compact(CompactRequest) returns (CompactReply);
  rpc Snapshot(SnapshotRequest) returns (SnapshotReply);
  rpc Delete(DeleteRequest) returns (DeleteReply);
  rpc Archive(ArchiveRequest) returns (ArchiveReply);
  rpc Suppress(SuppressRequest) returns (SuppressReply);
  rpc Recover(RecoverRequest) returns (RecoverReply);
  rpc Stats(StoreStatsRequest) returns (StoreStatsReply);
  rpc InspectGraph(GraphInspectionRequest) returns (GraphInspectionReply);
  rpc IntegrityCheck(IntegrityCheckRequest) returns (IntegrityCheckReply);
  rpc Repair(RepairRequest) returns (RepairReply);
  rpc RunMaintenance(MaintenanceRunRequest) returns (MaintenanceRunReply);
  rpc ListTraces(ListTracesRequest) returns (ListTracesReply);
  rpc GetTrace(GetTraceRequest) returns (OperationTrace);
  rpc Export(ExportRequest) returns (ExportReply);
  rpc Import(ImportRequest) returns (ImportReply);
  rpc ShipSnapshot(SnapshotShipRequest) returns (SnapshotShipReply);
}
