Files

11 KiB

tags, create time
tags create time
autonomy
jira
claude-code
生命周期
bug修复
daemon
2026-06-09 22:30

Autonomy Reliability Jira Drafts

概述

基于 /autonomy、proactive ticks、HEARTBEAT managed flows、cron scheduling、command queue consumption 和 daemon process supervision 的调用链审计,整理出 12 个可靠性修复 Tickets。覆盖 autonomy 生命周期状态机、proactive/cron 异步失败可见性、daemon 重启定时器泄漏、持久化锁累积等关键问题。

正文

AUT-001: Preserve autonomy lifecycle when queued commands are consumed mid-turn

  • Type: Bug | Priority: P0 | Status: Draft
  • Patch status: Implemented in fix/autonomy-lifecycle.

Problem: query.ts 可以在 active turn 期间将 queued prompt/task-notification commands 作为 attachments 消费。这种方式消费的 Autonomy prompts 从内存队列中移除,但没有标记持久化的 run 为 running/completed/failed,导致 managed flows 可能卡在 queued 状态无法推进。

Evidence: src/query.ts 通过 getCommandsByMaxPriority() 消费 queued commands 并从队列中移除。生命周期更新仅存在于正常的 queued-submit 路径 src/utils/handlePromptSubmit.ts 和 headless src/cli/print.ts。

Acceptance criteria: Mid-turn consumed autonomy commands 标记 runs 为 running。正常 query completion 完成 consumed runs 并排队下一个 managed-flow steps。Query errors 或 abort terminal reasons 标记 consumed runs 为 failed。Stale/cancelled autonomy commands 从内存队列移除但不发送给模型。


AUT-002: Make autonomy run lifecycle transitions terminal-safe

  • Type: Bug | Priority: P0 | Status: Draft
  • Patch status: Implemented in fix/autonomy-lifecycle.

Problem: Run lifecycle helpers 无条件覆写状态。Stale 的内存命令可能将 cancelled/completed/failed 的 run 重新标记为 running,导致 cancelled flow 执行或 terminal flow 被重写。

Evidence: markAutonomyRunRunning、markAutonomyRunCompleted、markAutonomyRunFailed、markAutonomyRunCancelled 更新记录时未检查当前状态。外部 CLI cancel 无法移除另一个进程中的 queued commands,所以 stale commands 是现实存在的输入。

Acceptance criteria: queued -> running/completed/failed/cancelled 保持允许。running -> completed/failed/cancelled 保持允许。任何 terminal status 拒绝后续 lifecycle 更新。Rejected transitions 不更新 managed-flow step state。


AUT-003: Prevent proactive and scheduled-task async fire failures from becoming invisible

  • Type: Bug | Priority: P1 | Status: Draft
  • Patch status: Implemented in fix/autonomy-lifecycle.

Problem: Proactive tick 和 cron fire callbacks 启动 detached async work。prompt 准备或队列插入的失败可能表现为 unhandled rejections 或从诊断中丢失。在 one-shot cron 路径中,scheduler 已经决定 task 已触发。

Evidence: src/proactive/useProactive.ts 使用了无 catch 的 detached async IIFE。src/cli/print.ts 的 proactive 和 cron 路径也使用 detached async work。src/hooks/useScheduledTasks.ts cron callbacks 使用 detached async work。

Acceptance criteria: Detached proactive/cron fire work 有显式错误日志。REPL proactive tick generation 是 non-reentrant 的。Hook unmount 后 Tick generation 停止排队。


AUT-004: Bound long-running daemon restart timers during shutdown

  • Type: Bug | Priority: P1 | Status: Draft
  • Patch status: Implemented in fix/autonomy-lifecycle.

Problem: daemon supervisor 使用 setTimeout() 调度 worker 重启,但没有存储、清除或 unref() timer。在 backoff 期间 shutdown 可能让 supervisor 保持存活直到 timer 触发,迫使 stop 路径走向 SIGKILL。

Evidence: src/daemon/main.ts 在 worker exit handler 中直接调度 restart timers。Shutdown 仅通知子进程,未清除 restart timers。

Acceptance criteria: Worker restart timers 按 worker 跟踪。Shutdown 清除所有 pending restart timers。Restart 和 force-kill grace timers 不单独保持 supervisor 存活。


AUT-005: Release autonomy persistence lock bookkeeping after each chain

  • Type: Bug | Priority: P1 | Status: Draft
  • Patch status: Implemented in fix/autonomy-lifecycle.

Problem: withAutonomyPersistenceLock 在 map 中存储了 chained promise,但在 cleanup 时将 map 值与 raw current promise 比较。条件永远不匹配,导致 root-level lock bookkeeping 在长期运行的进程中累积。

Evidence: src/utils/autonomyPersistence.ts 存储 previous.then(() => current)。Cleanup 比较 persistenceLocks.get(key) === current。

Acceptance criteria: 存储的 chained promise 是 cleanup 比较使用的值。Same-root calls 的序列化行为不变。测试直接断言 success 和 failure 后 same-root lock bookkeeping 归零。


AUT-006: Add active-record protection before persistence truncation

  • Type: Reliability | Priority: P2 | Status: Draft
  • Patch status: Implemented in fix/autonomy-lifecycle.

Problem: Autonomy runs 和 flows 仅按 latest-created/updated order 截断。高 churn 场景下,active 的 queued 或 running 记录可能在完成前被截断,移除恢复证据并可能中断 managed-flow advancement。

Evidence: src/utils/autonomyRuns.ts 保留最新 200 条 runs(按 createdAt)。src/utils/autonomyFlows.ts 保留最新 100 条 flows(按 updatedAt)。

Acceptance criteria: Active records 在 completed historical records 被 trim 之前保留。测试覆盖超出配置上限且 active records 在尾部附近的 trim 场景。


AUT-007: Treat provider API-error responses as failed autonomy turns

  • Type: Bug | Priority: P0 | Status: Draft
  • Patch status: Implemented in fix/autonomy-lifecycle.

Problem: 第三方 provider adapters 可以将 provider failures 转换为合成的 assistant API-error 消息而非抛出异常。query.ts 将 isApiErrorMessage terminal responses 视为 completed,导致已消费的 autonomy command 被标记为 completed 并推进 managed flow,即使 provider 调用实际失败。

Evidence: src/services/api/openai/index.ts、src/services/api/gemini/index.ts、src/services/api/grok/index.ts 在 adapter errors 时 yield createAssistantAPIErrorMessage()。src/query.ts 跳过 stop hooks 但返回 reason: 'completed'。

Acceptance criteria: Provider API-error assistant messages 以 reason: 'model_error' 终止 query。已消费的 autonomy run 标记为 failed 而非 completed。Provider API errors 后 managed flows 不推进到下一步。


AUT-008: Finalize consumed autonomy runs on async-generator close

  • Type: Bug | Priority: P0 | Status: Draft
  • Patch status: Implemented in fix/autonomy-lifecycle.

Problem: query() 是一个 async generator。当 consumer 调用 .return() 或跳出迭代时,JavaScript 执行 finally 块并跳过 try/finally 之后的代码。之前的 autonomy finalization 在 finally 之后运行,导致已 claimed 为 running 的 queued autonomy commands 在 REPL/SDK consumer 关闭 generator 后永远保持 running 状态。

Evidence: Claimed run IDs 在 queued attachment 注入期间收集。Completion/failure finalization 仅在 yield* queryLoop(...) 正常返回或抛出后执行。

Acceptance criteria: Consumed autonomy runs 从 finally 路径 finalize。Normal completion 标记 consumed runs 为 completed 并入队下一步 managed flow。Generator close 和 user abort terminals 标记 consumed runs 为 cancelled。


AUT-009: Claim queued autonomy runs before attachment injection

  • Type: Bug | Priority: P0 | Status: Draft
  • Patch status: Implemented in fix/autonomy-lifecycle.

Problem: Query loop 在 attachment generation 之前过滤了 stale queued autonomy commands,但直到 attachments 已经 yield 后才将 runs 标记为 running。在这两步之间的并发 cancel 仍然可以将 cancelled prompt 发送到模型上下文中。

Evidence: partitionConsumableQueuedAutonomyCommands() 仅检查持久化状态。markAutonomyRunRunning() 之前在 getAttachmentMessages() 之后运行。

Acceptance criteria: Query 在将 commands 传递给 attachment generation 之前 claim queued autonomy runs。只有成功 claimed 的 commands 被注入为 queued-command attachments。Failed claims 视为 stale 并从内存队列移除。


AUT-010: Cancel proactive and cron runs dropped before enqueue

  • Type: Bug | Priority: P1 | Status: Draft
  • Patch status: Implemented in fix/autonomy-lifecycle.

Problem: /proactive 和 scheduled-task producers 在返回 queue commands 之前持久化 autonomy runs。如果组件在持久化之后、enqueue 之前被 dispose 或 headless input 关闭,queued run 留在磁盘上但没有内存 command 来消费它。

Evidence: createProactiveAutonomyCommands() 在返回 commands 之前提交 runs。commitAutonomyQueuedPrompt() 在 callers enqueue 之前持久化 scheduled-task runs。

Acceptance criteria: Proactive hook cancellation 在 commit 前和 command creation 后都检查。Headless proactive 和 cron 路径在 input close 导致 command 被丢弃时 cancel 已创建的 command。REPL scheduled-task cleanup 在 unmount 时 cancel 已创建的 commands。


AUT-011: Replace query transition any stubs with typed contracts

  • Type: Test/Type Safety | Priority: P2 | Status: Draft
  • Patch status: Implemented in fix/autonomy-lifecycle.

Problem: src/query/transitions.ts 将 Terminal 和 Continue 都定义为 any。这允许新的 terminal reasons(如 model_error)和 continuation reasons(如 collapse_drain_retry)在没有编译器检查的情况下漂移。

Acceptance criteria: Terminal 是 query terminal reasons 的具体 union。Continue 是 continuation reasons 和 payloads 的具体 union。bun run typecheck 验证所有 query return sites。


AUT-012: Avoid provider test settings-module mock pollution

  • Type: Test Reliability | Priority: P2 | Status: Draft
  • Patch status: Implemented in fix/autonomy-lifecycle.

Problem: Provider tests 之前 mock 了 settings.js。Minimal mock 在同一 Bun 进程中破坏了导入额外 settings exports 的其他测试;扩展后的 mock 避免了失败但过度耦合了 provider test 到无关的 settings 内部实现。

Acceptance criteria: Provider tests 不 mock settings.js。modelType precedence 通过注入的 settings snapshot 测试,不触碰全局 bootstrap state。Provider tests 在与 permissions tests 和 provider matrix 一起运行时通过。

关联笔记