vault backup: 2026-06-09 23:15:17
This commit is contained in:
@@ -1,314 +1,168 @@
|
||||
---
|
||||
tags: [autonomy, jira, claude-code, 生命周期, bug修复, daemon]
|
||||
create time: 2026-06-09 22:30
|
||||
---
|
||||
|
||||
# Autonomy Reliability Jira Drafts
|
||||
|
||||
These tickets are based on the call-chain audit of `/autonomy`, proactive
|
||||
ticks, HEARTBEAT managed flows, cron scheduling, command queue consumption,
|
||||
and daemon process supervision.
|
||||
## 概述
|
||||
|
||||
## AUT-001: Preserve autonomy lifecycle when queued commands are consumed mid-turn
|
||||
基于 `/autonomy`、proactive ticks、HEARTBEAT managed flows、cron scheduling、command queue consumption 和 daemon process supervision 的调用链审计,整理出 12 个可靠性修复 Tickets。覆盖 autonomy 生命周期状态机、proactive/cron 异步失败可见性、daemon 重启定时器泄漏、持久化锁累积等关键问题。
|
||||
|
||||
Type: Bug
|
||||
Priority: P0
|
||||
Status: Draft
|
||||
Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
## 正文
|
||||
|
||||
Problem:
|
||||
`query.ts` can drain queued prompt/task-notification commands as attachments
|
||||
during an active turn. Autonomy prompts consumed this way were removed from the
|
||||
in-memory queue without marking the persisted run as running/completed/failed,
|
||||
so managed flows could stay stuck in `queued` and never advance.
|
||||
### AUT-001: Preserve autonomy lifecycle when queued commands are consumed mid-turn
|
||||
|
||||
Evidence:
|
||||
- `src/query.ts` drains queued commands via `getCommandsByMaxPriority()`.
|
||||
- `src/query.ts` removes consumed commands from the queue.
|
||||
- Lifecycle updates existed only in the normal queued-submit path
|
||||
`src/utils/handlePromptSubmit.ts` and headless `src/cli/print.ts`.
|
||||
- Type: Bug | Priority: P0 | Status: Draft
|
||||
- Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
|
||||
Acceptance criteria:
|
||||
- Mid-turn consumed autonomy commands mark runs `running`.
|
||||
- Normal query completion finalizes consumed runs and queues next managed-flow
|
||||
steps.
|
||||
- Query errors or abort terminal reasons mark consumed runs failed.
|
||||
- Stale/cancelled autonomy commands are removed from the in-memory queue
|
||||
without being sent to the model.
|
||||
- Regression tests cover stale command filtering and managed-flow advancement.
|
||||
**Problem**: `query.ts` 可以在 active turn 期间将 queued prompt/task-notification commands 作为 attachments 消费。这种方式消费的 Autonomy prompts 从内存队列中移除,但没有标记持久化的 run 为 running/completed/failed,导致 managed flows 可能卡在 `queued` 状态无法推进。
|
||||
|
||||
## AUT-002: Make autonomy run lifecycle transitions terminal-safe
|
||||
**Evidence**: `src/query.ts` 通过 `getCommandsByMaxPriority()` 消费 queued commands 并从队列中移除。生命周期更新仅存在于正常的 queued-submit 路径 `src/utils/handlePromptSubmit.ts` 和 headless `src/cli/print.ts`。
|
||||
|
||||
Type: Bug
|
||||
Priority: P0
|
||||
Status: Draft
|
||||
Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
**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 从内存队列移除但不发送给模型。
|
||||
|
||||
Problem:
|
||||
Run lifecycle helpers rewrote status unconditionally. A stale in-memory command
|
||||
could mark a cancelled/completed/failed run back to `running`, causing a
|
||||
cancelled flow to execute or a terminal flow to be rewritten.
|
||||
---
|
||||
|
||||
Evidence:
|
||||
- `markAutonomyRunRunning`, `markAutonomyRunCompleted`,
|
||||
`markAutonomyRunFailed`, and `markAutonomyRunCancelled` updated records
|
||||
without checking current status.
|
||||
- External CLI cancel cannot remove queued commands living inside another
|
||||
process, so stale commands are a realistic input.
|
||||
### AUT-002: Make autonomy run lifecycle transitions terminal-safe
|
||||
|
||||
Acceptance criteria:
|
||||
- `queued -> running/completed/failed/cancelled` remains allowed.
|
||||
- `running -> completed/failed/cancelled` remains allowed.
|
||||
- Any terminal status rejects later lifecycle updates.
|
||||
- Rejected transitions do not update managed-flow step state.
|
||||
- Regression tests cover stale lifecycle calls after cancellation.
|
||||
- Type: Bug | Priority: P0 | Status: Draft
|
||||
- Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
|
||||
## AUT-003: Prevent proactive and scheduled-task async fire failures from becoming invisible
|
||||
**Problem**: Run lifecycle helpers 无条件覆写状态。Stale 的内存命令可能将 cancelled/completed/failed 的 run 重新标记为 `running`,导致 cancelled flow 执行或 terminal flow 被重写。
|
||||
|
||||
Type: Bug
|
||||
Priority: P1
|
||||
Status: Draft
|
||||
Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
**Evidence**: `markAutonomyRunRunning`、`markAutonomyRunCompleted`、`markAutonomyRunFailed`、`markAutonomyRunCancelled` 更新记录时未检查当前状态。外部 CLI cancel 无法移除另一个进程中的 queued commands,所以 stale commands 是现实存在的输入。
|
||||
|
||||
Problem:
|
||||
Proactive tick and cron fire callbacks launch detached async work. Failures in
|
||||
prompt preparation or queue insertion could surface as unhandled rejections or
|
||||
be lost from diagnostics. In one-shot cron paths, the scheduler has already
|
||||
decided the task fired.
|
||||
**Acceptance criteria**: `queued -> running/completed/failed/cancelled` 保持允许。`running -> completed/failed/cancelled` 保持允许。任何 terminal status 拒绝后续 lifecycle 更新。Rejected transitions 不更新 managed-flow step state。
|
||||
|
||||
Evidence:
|
||||
- `src/proactive/useProactive.ts` used a detached async IIFE without catch.
|
||||
- `src/cli/print.ts` proactive and cron paths also detached async work.
|
||||
- `src/hooks/useScheduledTasks.ts` cron callbacks detached async work.
|
||||
---
|
||||
|
||||
Acceptance criteria:
|
||||
- Detached proactive/cron fire work has explicit error logging.
|
||||
- REPL proactive tick generation is non-reentrant.
|
||||
- Tick generation stops queueing after hook unmount.
|
||||
### AUT-003: Prevent proactive and scheduled-task async fire failures from becoming invisible
|
||||
|
||||
## AUT-004: Bound long-running daemon restart timers during shutdown
|
||||
- Type: Bug | Priority: P1 | Status: Draft
|
||||
- Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
|
||||
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 已触发。
|
||||
|
||||
Problem:
|
||||
The daemon supervisor scheduled worker restarts with `setTimeout()` but did
|
||||
not store, clear, or `unref()` the timer. Shutdown during backoff could keep
|
||||
the supervisor alive until the timer fired, forcing the stop path toward
|
||||
SIGKILL.
|
||||
**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。
|
||||
|
||||
Evidence:
|
||||
- `src/daemon/main.ts` scheduled restart timers directly in the worker exit
|
||||
handler.
|
||||
- Shutdown only signaled child processes and did not clear restart timers.
|
||||
**Acceptance criteria**: Detached proactive/cron fire work 有显式错误日志。REPL proactive tick generation 是 non-reentrant 的。Hook unmount 后 Tick generation 停止排队。
|
||||
|
||||
Acceptance criteria:
|
||||
- Worker restart timers are tracked per worker.
|
||||
- Shutdown clears any pending restart timers.
|
||||
- Restart and force-kill grace timers do not keep the supervisor alive alone.
|
||||
---
|
||||
|
||||
## AUT-005: Release autonomy persistence lock bookkeeping after each chain
|
||||
### AUT-004: Bound long-running daemon restart timers during shutdown
|
||||
|
||||
Type: Bug
|
||||
Priority: P1
|
||||
Status: Draft
|
||||
Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
- Type: Bug | Priority: P1 | Status: Draft
|
||||
- Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
|
||||
Problem:
|
||||
`withAutonomyPersistenceLock` stored a chained promise in its map but compared
|
||||
the map value against the raw current promise during cleanup. That condition
|
||||
never matched, so root-level lock bookkeeping could accumulate in long-lived
|
||||
processes that touch many workspaces.
|
||||
**Problem**: daemon supervisor 使用 `setTimeout()` 调度 worker 重启,但没有存储、清除或 `unref()` timer。在 backoff 期间 shutdown 可能让 supervisor 保持存活直到 timer 触发,迫使 stop 路径走向 SIGKILL。
|
||||
|
||||
Evidence:
|
||||
- `src/utils/autonomyPersistence.ts` stored `previous.then(() => current)`.
|
||||
- Cleanup compared `persistenceLocks.get(key) === current`.
|
||||
**Evidence**: `src/daemon/main.ts` 在 worker exit handler 中直接调度 restart timers。Shutdown 仅通知子进程,未清除 restart timers。
|
||||
|
||||
Acceptance criteria:
|
||||
- The stored chained promise is the value used for cleanup comparison.
|
||||
- Existing serialization behavior for same-root calls remains unchanged.
|
||||
- Tests directly assert same-root lock bookkeeping returns to zero after both
|
||||
success and failure.
|
||||
**Acceptance criteria**: Worker restart timers 按 worker 跟踪。Shutdown 清除所有 pending restart timers。Restart 和 force-kill grace timers 不单独保持 supervisor 存活。
|
||||
|
||||
## AUT-006: Add active-record protection before persistence truncation
|
||||
---
|
||||
|
||||
Type: Reliability
|
||||
Priority: P2
|
||||
Status: Draft
|
||||
Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
### AUT-005: Release autonomy persistence lock bookkeeping after each chain
|
||||
|
||||
Problem:
|
||||
Autonomy runs and flows are capped by latest-created/updated order only.
|
||||
Under high churn, active `queued` or `running` records can be truncated before
|
||||
completion, which removes recovery evidence and can break managed-flow
|
||||
advancement.
|
||||
- Type: Bug | Priority: P1 | Status: Draft
|
||||
- Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
|
||||
Evidence:
|
||||
- `src/utils/autonomyRuns.ts` keeps the latest 200 runs by `createdAt`.
|
||||
- `src/utils/autonomyFlows.ts` keeps the latest 100 flows by `updatedAt`.
|
||||
**Problem**: `withAutonomyPersistenceLock` 在 map 中存储了 chained promise,但在 cleanup 时将 map 值与 raw current promise 比较。条件永远不匹配,导致 root-level lock bookkeeping 在长期运行的进程中累积。
|
||||
|
||||
Acceptance criteria:
|
||||
- Active records are retained before completed historical records are trimmed.
|
||||
- Tests cover trimming with more than the configured cap and active records
|
||||
near the tail.
|
||||
**Evidence**: `src/utils/autonomyPersistence.ts` 存储 `previous.then(() => current)`。Cleanup 比较 `persistenceLocks.get(key) === current`。
|
||||
|
||||
## AUT-007: Treat provider API-error responses as failed autonomy turns
|
||||
**Acceptance criteria**: 存储的 chained promise 是 cleanup 比较使用的值。Same-root calls 的序列化行为不变。测试直接断言 success 和 failure 后 same-root lock bookkeeping 归零。
|
||||
|
||||
Type: Bug
|
||||
Priority: P0
|
||||
Status: Draft
|
||||
Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
---
|
||||
|
||||
Problem:
|
||||
Third-party provider adapters can convert provider failures into synthetic
|
||||
assistant API-error messages instead of throwing. `query.ts` treated
|
||||
`isApiErrorMessage` terminal responses as `completed`, so an autonomy command
|
||||
that had already been consumed as a queued attachment could be marked
|
||||
completed and advance its managed flow even though the provider call failed.
|
||||
### AUT-006: Add active-record protection before persistence truncation
|
||||
|
||||
Evidence:
|
||||
- `src/services/api/openai/index.ts`, `src/services/api/gemini/index.ts`, and
|
||||
`src/services/api/grok/index.ts` yield `createAssistantAPIErrorMessage()` on
|
||||
adapter errors.
|
||||
- `src/query.ts` skipped stop hooks for API-error assistant messages but
|
||||
returned `reason: 'completed'`.
|
||||
- Top-level autonomy finalization used terminal completion to decide whether
|
||||
to mark consumed runs completed or failed.
|
||||
- Type: Reliability | Priority: P2 | Status: Draft
|
||||
- Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
|
||||
Acceptance criteria:
|
||||
- Provider API-error assistant messages terminate the query with
|
||||
`reason: 'model_error'`.
|
||||
- Any consumed autonomy run is marked failed rather than completed.
|
||||
- Managed flows do not advance to the next step after provider API errors.
|
||||
- A regression test simulates provider error after a queued autonomy attachment
|
||||
has been consumed.
|
||||
**Problem**: Autonomy runs 和 flows 仅按 latest-created/updated order 截断。高 churn 场景下,active 的 `queued` 或 `running` 记录可能在完成前被截断,移除恢复证据并可能中断 managed-flow advancement。
|
||||
|
||||
## AUT-008: Finalize consumed autonomy runs on async-generator close
|
||||
**Evidence**: `src/utils/autonomyRuns.ts` 保留最新 200 条 runs(按 `createdAt`)。`src/utils/autonomyFlows.ts` 保留最新 100 条 flows(按 `updatedAt`)。
|
||||
|
||||
Type: Bug
|
||||
Priority: P0
|
||||
Status: Draft
|
||||
Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
**Acceptance criteria**: Active records 在 completed historical records 被 trim 之前保留。测试覆盖超出配置上限且 active records 在尾部附近的 trim 场景。
|
||||
|
||||
Problem:
|
||||
`query()` is an async generator. When its consumer calls `.return()` or breaks
|
||||
out of iteration, JavaScript executes `finally` blocks and skips code after the
|
||||
`try/finally`. The previous autonomy finalization ran after the `finally`, so
|
||||
queued autonomy commands that had already been claimed as `running` could stay
|
||||
persisted as `running` forever if the REPL/SDK consumer closed the generator.
|
||||
---
|
||||
|
||||
Evidence:
|
||||
- Claimed run IDs were collected during queued attachment injection.
|
||||
- Completion/failure finalization happened only after `yield* queryLoop(...)`
|
||||
returned normally or threw.
|
||||
- Claude cross-validation flagged this as a durable run/flow leak.
|
||||
### AUT-007: Treat provider API-error responses as failed autonomy turns
|
||||
|
||||
Acceptance criteria:
|
||||
- Consumed autonomy runs are finalized from a `finally` path.
|
||||
- Normal completion marks consumed runs completed and enqueues next managed
|
||||
flow steps.
|
||||
- Provider/model errors mark consumed runs failed.
|
||||
- Generator close and user abort terminals mark consumed runs cancelled.
|
||||
- A regression test closes the generator after a queued autonomy attachment and
|
||||
verifies the run/flow are cancelled, not left running.
|
||||
- Type: Bug | Priority: P0 | Status: Draft
|
||||
- Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
|
||||
## AUT-009: Claim queued autonomy runs before attachment injection
|
||||
**Problem**: 第三方 provider adapters 可以将 provider failures 转换为合成的 assistant API-error 消息而非抛出异常。`query.ts` 将 `isApiErrorMessage` terminal responses 视为 `completed`,导致已消费的 autonomy command 被标记为 completed 并推进 managed flow,即使 provider 调用实际失败。
|
||||
|
||||
Type: Bug
|
||||
Priority: P0
|
||||
Status: Draft
|
||||
Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
**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'`。
|
||||
|
||||
Problem:
|
||||
The query loop filtered stale queued autonomy commands before attachment
|
||||
generation, but it did not claim runs as `running` until after attachments were
|
||||
already yielded. A concurrent cancellation between those steps could still send
|
||||
a cancelled prompt into the model context.
|
||||
**Acceptance criteria**: Provider API-error assistant messages 以 `reason: 'model_error'` 终止 query。已消费的 autonomy run 标记为 failed 而非 completed。Provider API errors 后 managed flows 不推进到下一步。
|
||||
|
||||
Evidence:
|
||||
- `partitionConsumableQueuedAutonomyCommands()` only checked persisted status.
|
||||
- `markAutonomyRunRunning()` previously ran after `getAttachmentMessages()`.
|
||||
- Reviewer cross-validation identified the check-then-act race.
|
||||
---
|
||||
|
||||
Acceptance criteria:
|
||||
- Query claims queued autonomy runs before passing commands to attachment
|
||||
generation.
|
||||
- Only successfully claimed commands are injected as queued-command
|
||||
attachments.
|
||||
- Failed claims are treated as stale and removed from the in-memory queue.
|
||||
- Claiming reads persisted run state once per turn rather than once per
|
||||
command.
|
||||
### AUT-008: Finalize consumed autonomy runs on async-generator close
|
||||
|
||||
## AUT-010: Cancel proactive and cron runs dropped before enqueue
|
||||
- Type: Bug | Priority: P0 | Status: Draft
|
||||
- Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
|
||||
Type: Bug
|
||||
Priority: P1
|
||||
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` 状态。
|
||||
|
||||
Problem:
|
||||
`/proactive` and scheduled-task producers persist autonomy runs before
|
||||
returning queue commands. If the component is disposed or headless input closes
|
||||
after persistence but before enqueue, the queued run is left on disk with no
|
||||
in-memory command to consume it.
|
||||
**Evidence**: Claimed run IDs 在 queued attachment 注入期间收集。Completion/failure finalization 仅在 `yield* queryLoop(...)` 正常返回或抛出后执行。
|
||||
|
||||
Evidence:
|
||||
- `createProactiveAutonomyCommands()` commits runs before returning commands.
|
||||
- `commitAutonomyQueuedPrompt()` persists scheduled-task runs before callers
|
||||
enqueue them.
|
||||
- Callers checked `disposed` / `inputClosed` after command creation and could
|
||||
return without terminalizing the run.
|
||||
**Acceptance criteria**: Consumed autonomy runs 从 `finally` 路径 finalize。Normal completion 标记 consumed runs 为 completed 并入队下一步 managed flow。Generator close 和 user abort terminals 标记 consumed runs 为 cancelled。
|
||||
|
||||
Acceptance criteria:
|
||||
- Proactive hook cancellation checks run both before commit and after command
|
||||
creation.
|
||||
- Headless proactive and cron paths cancel any already-created command that is
|
||||
dropped due to input close.
|
||||
- REPL scheduled-task cleanup cancels already-created commands when unmounted.
|
||||
- A regression test verifies a proactive command created but dropped before
|
||||
enqueue is marked cancelled.
|
||||
---
|
||||
|
||||
## AUT-011: Replace query transition `any` stubs with typed contracts
|
||||
### AUT-009: Claim queued autonomy runs before attachment injection
|
||||
|
||||
Type: Test/Type Safety
|
||||
Priority: P2
|
||||
Status: Draft
|
||||
Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
- Type: Bug | Priority: P0 | Status: Draft
|
||||
- Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
|
||||
Problem:
|
||||
`src/query/transitions.ts` defined both `Terminal` and `Continue` as `any`.
|
||||
That allowed new terminal reasons such as `model_error` and continuation
|
||||
reasons such as `collapse_drain_retry` to drift without compiler checks.
|
||||
**Problem**: Query loop 在 attachment generation 之前过滤了 stale queued autonomy commands,但直到 attachments 已经 yield 后才将 runs 标记为 `running`。在这两步之间的并发 cancel 仍然可以将 cancelled prompt 发送到模型上下文中。
|
||||
|
||||
Evidence:
|
||||
- Claude cross-validation flagged the `Terminal = any` contract as a remaining
|
||||
issue.
|
||||
- Tightening the type immediately caught that
|
||||
`collapse_drain_retry.committed` is a `number`, not a `boolean`.
|
||||
**Evidence**: `partitionConsumableQueuedAutonomyCommands()` 仅检查持久化状态。`markAutonomyRunRunning()` 之前在 `getAttachmentMessages()` 之后运行。
|
||||
|
||||
Acceptance criteria:
|
||||
- `Terminal` is a concrete union of query terminal reasons.
|
||||
- `Continue` is a concrete union of continuation reasons and payloads.
|
||||
- `bun run typecheck` validates all query return sites against that contract.
|
||||
**Acceptance criteria**: Query 在将 commands 传递给 attachment generation 之前 claim queued autonomy runs。只有成功 claimed 的 commands 被注入为 queued-command attachments。Failed claims 视为 stale 并从内存队列移除。
|
||||
|
||||
## AUT-012: Avoid provider test settings-module mock pollution
|
||||
---
|
||||
|
||||
Type: Test Reliability
|
||||
Priority: P2
|
||||
Status: Draft
|
||||
Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
### AUT-010: Cancel proactive and cron runs dropped before enqueue
|
||||
|
||||
Problem:
|
||||
The provider tests previously mocked `settings.js`. A minimal mock broke other
|
||||
tests that imported additional settings exports in the same Bun process; the
|
||||
expanded mock avoided the failure but over-coupled the provider test to
|
||||
unrelated settings internals.
|
||||
- Type: Bug | Priority: P1 | Status: Draft
|
||||
- Patch status: Implemented in `fix/autonomy-lifecycle`.
|
||||
|
||||
Evidence:
|
||||
- Full test runs observed cross-file settings mock pollution.
|
||||
- `src/utils/model/providers.ts` only needs the real `getInitialSettings()`
|
||||
behavior.
|
||||
**Problem**: `/proactive` 和 scheduled-task producers 在返回 queue commands 之前持久化 autonomy runs。如果组件在持久化之后、enqueue 之前被 dispose 或 headless input 关闭,queued run 留在磁盘上但没有内存 command 来消费它。
|
||||
|
||||
Acceptance criteria:
|
||||
- Provider tests do not mock `settings.js`.
|
||||
- `modelType` precedence is exercised through an injected settings snapshot,
|
||||
leaving global bootstrap state untouched.
|
||||
- Provider tests pass when run alongside permissions tests and the provider
|
||||
matrix.
|
||||
**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 一起运行时通过。
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[agent-comm-fix-jira-tasks]] - Agent 通讯修复 Jira Task
|
||||
- [[agent-comm-fix-questions]] - Agent 通讯修复问题文档
|
||||
- [[three-tier-gating]] - 三层门禁系统
|
||||
|
||||
Reference in New Issue
Block a user