//! Input Augmentation 层 — Mention Resolver trait + 注册表 + 注入段构建
//!
//! 核心设计2(plan mighty-wibbling-papert.md):
//! - [`MentionResolver`] async trait:把 [`MentionRef`] 投影成 [`Augmentation`],
//!   按 provider locality 决定 path 脱敏粒度(Local 全路径 / Remote basename)。
//! - [`ResolverRegistry`]:HashMap<kind, Arc<dyn MentionResolver>> + `resolve_all`
//!   按 MentionRef::kind_str 分发,单条失败收集 [`ResolveError`] 不阻断整批注入。
//! - 四 impl(ProjectResolver/TaskResolver/IdeaResolver/SkillResolver)在 [`resolvers`] 模块。
//!
//! 新增 mention 类型 = 加一个 impl + 注册一行,主干零改(破解"改 4-5 处"僵化)。

pub mod inject;
pub mod registry;
pub mod resolvers;
pub mod sanitize;

pub use inject::build_augmentation_segment;
pub use registry::ResolverRegistry;
pub use resolvers::build_resolver_registry;

use async_trait::async_trait;
use df_types::augmentation::{Augmentation, MentionRef, ResolveError};

use crate::commands::ai::augmentation::sanitize::ProviderLocality;

/// Mention → Augmentation 的投影 trait。
///
/// 每个 Resolver 处理一种 kind(`project`/`task`/`idea`/`skill`),`kind()` 返回的标签
/// 须与 [`MentionRef::kind_str`] / serde tag 一致。`resolve()` 接收 locality 用于决定
/// path 脱敏粒度(仅 ProjectResolver 用到,其余忽略即可)。
///
/// 单条 resolve 失败应返 [`ResolveError::NotFound`] / [`ResolveError::Skip`],
/// 由 [`ResolverRegistry::resolve_all`] 收集进 errors 列表不中断其他 mention。
#[async_trait]
pub trait MentionResolver: Send + Sync {
    /// 返回 Resolver 处理的 kind 标签(与 serde tag 一致):`project`/`task`/`idea`/`skill`。
    fn kind(&self) -> &'static str;

    /// 把单个 [`MentionRef`] 投影成 [`Augmentation`]。
    ///
    /// `loc` 为当前 provider 的 locality,ProjectResolver 据此决定 path 是否脱敏。
    /// kind 不匹配返 [`ResolveError::KindMismatch`](防注册表分发错配)。
    async fn resolve(
        &self,
        rf: &MentionRef,
        loc: ProviderLocality,
    ) -> Result<Augmentation, ResolveError>;
}
