Aster文档
搜索 Aster 文档
ESC
产品
版本

输入关键词开始搜索。

    文档目录

    ASTER CODE / 内核原理

    会话恢复与外部操作核实

    事实日志、检查点、消息摘要、工作区身份、未决效果与失联切片。

    重放恢复控制状态

    恢复会话时,Core 从原始事实重建运行投影。 已经有完整结果的调用支持沿记录继续判断。 结果缺失的外部操作仍保留不确定性。 重放日志本身不会撤销或重新执行外部效果。

    架构图恢复会话时先证明来源重放事实恢复控制状态。结果不明的外部操作仍需核实。
    恢复会话时先证明来源重放事实恢复控制状态。结果不明的外部操作仍需核实。1234读取身份与缓存核对原始事实恢复控制投影报告未决副作用宿主检查点事实日志恢复的会话宿主检查点事实日志恢复的会话
    1. 01检查点用于接续上下文

      缓存记录消息和运行关联。缓存不能覆盖原始事实。

      checkpoints.rs L5 ↗
    2. 02事实日志提供原始依据

      恢复流程验证会话与工作区关联。

      resume.rs L37 ↗
    3. 03保留无法证明的缺口

      缺失回执时,宿主核实真实对象后再决定后续动作。

    下载 SVG ↗

    例如,外部服务已接受写入。 本地进程随后在保存结果前退出。 恢复后的日志缺少结果,外部写入却可能已经生效。 直接重试可能造成第二次写入。

    四种材料分别承担什么职责

    材料用途权威边界
    事实日志重建控制与原始效果关联不被摘要中的声明覆盖
    检查点保存已提交状态的缓存投影恢复时核对身份与来源
    对话摘要帮助模型接续推理不能授予权限或接受步骤
    当前工作区核对真实文件与当前对象不能仅凭历史缓存推断现状

    缓存加快接续,事实提供依据。 两者矛盾时,恢复流程需要报告具体缺口。 宿主不应把缓存存在当成原始效果已证明。

    源码漫游

    恢复源码漫游

    恢复流程先核对来源,再恢复控制投影。

    检查点从原日志事实构造消息与关联。

    缓存是投影,原始事实仍是依据。

    checkpoints.rs L5-L28 ↗
    RS
    crates/code/core/src/fact_control/checkpoints.rs
    L5-L28 ↗
    pub(super) async fn save_committed(
    surface: &SessionSurface,
    checkpoint: &CheckpointState,
    attempted_seq: &AtomicU64,
    ) -> Result<(), ActorError> {
    let facts = surface_fact_log(surface)?.read(&thread_for_session(&surface.session_id))?;
    replay_unsettled_mutations_from_facts(surface, &facts);
    let debt = receipts::fold_debt(&facts);
    let expected_binding = checkpoint
    .capability_binding
    .as_ref()
    .map(|binding| {
    crate::content_digest::digest_json("a3s.code.tool-admission-binding.v1", binding)
    .map_err(|error| ActorError::Schema(error.to_string()))
    })
    .transpose()?;
    let thread = thread_for_session(&surface.session_id);
    // A recovery may read receipts from its source Run. Export only when
    // this exact admitted Run has added a terminal; the original checkpoint
    // and log remain the authority for its older work.
    let latest = facts.iter().rev().find(|fact| {
    if fact.kind != "tool.result" {
    return false;
    }

    recovery.unproved 记录缺失证据的来源身份。

    这个标记不会批准重试,也不会清除执行欠项。

    recovery_unproved.rs L16-L34 ↗
    RS
    crates/code/core/src/fact_control/recovery_unproved.rs
    L16-L34 ↗
    pub(super) const RECOVERY_UNPROVED_FACT_KIND: &str = "recovery.unproved";
    const RECOVERY_UNPROVED_SCHEMA: &str = "a3s.code.recovery-unproved.v1";
    const RECOVERY_UNPROVED_IDENTITY_DOMAIN: &str = "a3s.code.recovery-unproved.identity.v1";
    const SOURCE_BINDING_DIGEST_DOMAIN: &str = "a3s.code.tool-admission-binding.v1";
    #[derive(Debug, Clone, PartialEq, Eq, Error)]
    pub(super) enum RecoveryUnprovedError {
    #[error("tool_effect_recovery_unproved_invalid: {0}")]
    Invalid(String),
    #[error("tool_effect_recovery_unproved_schema_unsupported: {0}")]
    SchemaUnsupported(String),
    }
    impl RecoveryUnprovedError {
    pub(super) const fn code(&self) -> &'static str {
    match self {
    Self::Invalid(_) => "tool_effect_recovery_unproved_invalid",
    Self::SchemaUnsupported(_) => "tool_effect_recovery_unproved_schema_unsupported",
    }

    reconcile_goal_slices 核对旧切片,保留原始效果结算要求。

    核对失联切片与重放外部操作是不同动作。

    goal_facade.rs L421-L449 ↗
    RS
    crates/code/core/src/agent_api/goal_facade.rs
    L421-L449 ↗
    pub fn reconcile_goal_slices(&self) -> Result<usize> {
    self.close_handle.mutate_immediate(|| {
    let lease = self.run_admission.try_acquire(&self.session_id)?;
    let log = lease.nonexecuting_fact_log(&self.run_admission, &self.session_id)?;
    let _writer = log.try_writer_fence().map_err(goal_log_error)?;
    let thread = crate::fact_control::thread_for_session(&self.session_id);
    let facts = log.read(&thread).map_err(goal_log_error)?;
    self.verify_saved_source(&facts)?;
    let digest = self.policy_digest_from(&facts)?;
    let workspace = self.tool_context.workspace_services.workspace_ref();
    let pending = crate::goal_control::reconcile_slices(
    &facts,
    &self.session_id,
    workspace,
    digest.as_deref(),
    )
    .map_err(goal_error)?;
    if !pending.is_empty() {
    log.append(&thread, &pending, None)
    .map_err(goal_log_error)?;
    }
    let facts = log.read(&thread).map_err(goal_log_error)?;
    let completed = crate::goal_control::prepare_completion(
    &facts,
    &self.session_id,
    workspace,
    digest.as_deref(),
    )
    .map_err(goal_error)?;

    源码与本文版本一致,保留原始行号。

    ACP 恢复为什么检查工作区

    会话 ID 必须指向对应工作区的原会话。 ACP 对启动工作区与请求目录做规范化核对。 随后查找原始会话来源。 缺少来源时返回资源不存在。 快照存在时,还会检查快照中的会话与工作区。

    这样能避免把另一个项目的缓存接入当前任务。 实现:恢复准入 L37 ↗。

    发现未决效果后怎样调查

    警告:结果不明时,重试外部写入可能产生重复效果。

    1. 读取原运行的工具身份。
    2. 核对原始调用参数。
    3. 查找原效果回执。
    4. 检查真实目标对象的状态。
    5. 记录缺失或新增的观察依据。
    6. 按原接口核对结清状态。

    若来源仍无法证明,运行保留未决状态。 模型的推测不会清除该状态。 宿主需要继续取得可核对的证据。

    recovery.unproved 说明什么

    recovery.unproved 记录无法证明的恢复来源。 记录携带内容绑定的身份与原因。 该记录本身不证明外部效果成功。 该记录也不授权重新执行效果。

    这是一项负面来源记录。 它把“证据缺失”与“已经失败”区分开。 宿主应保留这一区别,避免显示虚假的成功状态。

    长期目标的失联切片怎样处理

    目标切片的执行者退出后,切片可能尚未结清。 下一次 tick 会要求先核对原运行。 reconcile_goal_slices 处理已经失去执行者的切片。 核对过程不会直接重放原始工具操作。 未结清的实际效果仍使用原有检查路径。

    “进程消失”“切片结清”“效果已知”是三个事实。 宿主需要分别核对。

    恢复验收应该覆盖哪些反例

    反例预期结果
    快照的会话 ID 与请求不同拒绝恢复
    请求目录属于另一个工作区拒绝接入原会话
    旧切片没有结清下一轮先进入 Reconcile
    外部效果缺少结果保留未决效果
    摘要宣称目标已完成继续核对原始步骤与完成事实
    同一控制命令重复提交按原身份处理幂等或冲突

    相关机制见完成判定。