Files
IdeA/crates/domain/src/error.rs
Blomios 98a8b7292a feat(memory): système de mémoire projet model-agnostic (L14, LOT A+B+C)
Base de connaissance persistante par projet, indépendante de tout modèle/CLU
et de git. Cadrage archi en §14.5 (ARCHITECTURE.md), cycle Archi→Dev→Test.

LOT A — étage 1 (.md, source de vérité)
  - domaine: entité Memory (+ MemorySlug, MemoryType, MemoryFrontmatter,
    MemoryLink, MemoryIndexEntry), liens [[slug]], index MEMORY.md dérivé
  - port MemoryStore + MemoryError, adapter FsMemoryStore (.ideai/memory/)
  - application: 7 use cases (Create/Update/List/Get/Delete/ReadIndex/
    ResolveLinks), From<MemoryError> for AppError
  - app-tauri: commandes + DTO, events MemorySaved/MemoryDeleted
  - suppression de la variante morte DomainError::MalformedFrontmatter

LOT B — rappel adaptatif (étage 1)
  - port MemoryRecall + MemoryQuery, adapter NaiveMemoryRecall (troncature
    au budget de tokens, court-circuit budget-0), use case RecallMemory

LOT C — étage 2 vectoriel (structure complète, zéro dépendance lourde)
  - port Embedder + EmbedderError, profils déclaratifs EmbedderProfile/
    EmbedderStrategy (embedder.json)
  - VectorMemoryRecall (cosinus, cache .ideai/memory/.index/ gitignoré)
  - AdaptiveMemoryRecall (bascule pure should_use_vector), défaut none
  - HashEmbedder (déterministe, tests), StubEmbedder (onnx/server/api)

Tests: 57 binaires verts, build + clippy --workspace sans warning.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 08:47:23 +02:00

79 lines
2.4 KiB
Rust

//! Domain-level validation errors.
//!
//! These errors are raised by validating constructors (`new`/`try_new`) when an
//! invariant documented in `ARCHITECTURE.md` §3.2 is violated. They are pure
//! data — no I/O, no platform coupling.
use thiserror::Error;
/// Error raised when an entity or value object invariant is violated at
/// construction time.
#[derive(Debug, Clone, PartialEq, Eq, Error)]
pub enum DomainError {
/// A required string field was empty.
#[error("field `{field}` must not be empty")]
EmptyField {
/// Name of the offending field.
field: &'static str,
},
/// A path that must be absolute was relative.
#[error("path `{path}` must be absolute")]
PathNotAbsolute {
/// The offending path.
path: String,
},
/// A path that must be relative was absolute, or escaped its root via `..`.
#[error("path `{path}` must be relative and must not contain `..`")]
PathNotRelativeSafe {
/// The offending path.
path: String,
},
/// An environment variable name was not a valid identifier.
#[error("`{value}` is not a valid environment variable identifier")]
InvalidEnvVar {
/// The offending value.
value: String,
},
/// An SSH port was outside the valid `1..=65535` range.
#[error("ssh port must be in 1..=65535, got {port}")]
InvalidPort {
/// The offending port.
port: u32,
},
/// A PTY dimension was zero.
#[error("pty size must have rows>0 and cols>0, got rows={rows} cols={cols}")]
InvalidPtySize {
/// Requested rows.
rows: u16,
/// Requested cols.
cols: u16,
},
/// `synchronized == true` requires an agent originating from a template.
#[error("a synchronized agent must originate from a template")]
SyncRequiresTemplate,
/// A manifest entry was inconsistent (e.g. synchronized without template metadata).
#[error("manifest entry inconsistent: {reason}")]
InconsistentManifest {
/// Human-readable reason.
reason: String,
},
/// A memory slug was not valid kebab-case (`[a-z0-9-]`, non-empty).
#[error("`{value}` is not a valid kebab-case slug")]
InvalidSlug {
/// The offending value.
value: String,
},
/// A generic invariant violation with an explanatory message.
#[error("invariant violated: {0}")]
Invariant(String),
}