mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-18 14:25:51 +00:00
refactor: 简化/复用/防御 — 清理 PR #386 审计发现
简化 (S1, S2): - src/cli/print.ts: 抽出 dispatchHeadlessCronCommand 本地 helper,把 cron 三个入口(onFire / onFireTask agent / onFireTask 非-agent)共享的 「dedup-claim → input-close-recheck → onSuccess」管线集中到一处, 避免三个分支在「claim 与 dispatch 之间发生 inputClosed」的处理上漂移。 enqueueAndRun 再抽出来,使两个非-agent 分支共用一个 onSuccess 回调。 约 -55 行重复模板。 - src/utils/autonomyPersistence.ts: 新增 retainActiveFirst<T> 泛型 helper —— active 记录无条件保留(不参与 cap),inactive 按 timestamp desc 填满剩余预算;统一 selectPersistedAutonomyRuns / Flows 的两阶段 排序语义。 - src/utils/autonomyRuns.ts、autonomyFlows.ts: 改用 retainActiveFirst, 删掉重复的内联两阶段排序逻辑。 复用 (R1, review #8): - tests/mocks/file-system.ts: 新增 readTempFile / tempPathExists 两个 Bun.file 包装,补齐 Node fs.readFileSync / existsSync 在测试里的 Bun-only 等价物。 - src/utils/__tests__/autonomyRuns.test.ts: 把全部 Node fs/path 导入 (existsSync, readFileSync, mkdir, writeFile, path.join/resolve)替换为 tests/mocks/file-system 的共享 helper + node:path(带 node: 前缀)。 不再有 6 处 mkdir + writeFile 模板,统一用 writeTempFile(自带 mkdir-p)。 解决 review #8 (Major) 的 Bun-only 运行时契约违反。 防御 (D1, OOM 早期信号): - src/services/compact/postCompactCleanup.ts: 在 void import().then() 末尾 补 .catch(logError)。当前 attributionHooks 是 stub,但当真实现被恢复 且 sweepFileContentCache 抛错时,这个 .catch 阻止它变成 unhandled rejection(函数返回值是 void,调用者无从观察异步失败)。 - src/utils/autonomyRuns.ts: 给 active runs 加 100 条软上限 + 一次性 warn。selectPersistedAutonomyRuns 仍然永不淘汰 active 记录,但跨过 阈值时 logError 一次,作为 finalize-leak 早期信号——避免 active 无限 增长悄悄使 AUTONOMY_RUNS_MAX 失效。
This commit is contained in:
@@ -3,7 +3,10 @@ import { mkdir, writeFile } from 'fs/promises'
|
||||
import { dirname, join, resolve } from 'path'
|
||||
import { getProjectRoot } from '../bootstrap/state.js'
|
||||
import { AUTONOMY_DIR, type AutonomyTriggerKind } from './autonomyAuthority.js'
|
||||
import { withAutonomyPersistenceLock } from './autonomyPersistence.js'
|
||||
import {
|
||||
retainActiveFirst,
|
||||
withAutonomyPersistenceLock,
|
||||
} from './autonomyPersistence.js'
|
||||
import { getFsImplementation } from './fsOperations.js'
|
||||
|
||||
const AUTONOMY_FLOWS_MAX = 100
|
||||
@@ -170,26 +173,12 @@ function isManagedFlowStatusActive(status: AutonomyFlowStatus): boolean {
|
||||
function selectPersistedAutonomyFlows(
|
||||
flows: AutonomyFlowRecord[],
|
||||
): AutonomyFlowRecord[] {
|
||||
// Two-phase sort. Phase 1: priority sort (active flows first, then by
|
||||
// updatedAt desc) selects the AUTONOMY_FLOWS_MAX most-relevant records to
|
||||
// retain — active flows are guaranteed a slot before any inactive flow is
|
||||
// considered. Phase 2: re-sort the retained slice by updatedAt desc only,
|
||||
// so the persisted file is in plain reverse-chronological order regardless
|
||||
// of activity status. Listings/UI consume the persisted order directly.
|
||||
const retained = flows
|
||||
.slice()
|
||||
.map(cloneFlowRecord)
|
||||
.sort((left, right) => {
|
||||
const leftActive = isManagedFlowStatusActive(left.status)
|
||||
const rightActive = isManagedFlowStatusActive(right.status)
|
||||
if (leftActive !== rightActive) {
|
||||
return leftActive ? -1 : 1
|
||||
}
|
||||
return right.updatedAt - left.updatedAt
|
||||
})
|
||||
.slice(0, AUTONOMY_FLOWS_MAX)
|
||||
|
||||
return retained.sort((left, right) => right.updatedAt - left.updatedAt)
|
||||
return retainActiveFirst(
|
||||
flows.map(cloneFlowRecord),
|
||||
flow => isManagedFlowStatusActive(flow.status),
|
||||
flow => flow.updatedAt,
|
||||
AUTONOMY_FLOWS_MAX,
|
||||
)
|
||||
}
|
||||
|
||||
function defaultFlowSource(params: {
|
||||
|
||||
Reference in New Issue
Block a user