Commit Graph

7 Commits

Author SHA1 Message Date
wangjia a00091329d merge: maestro/tsk_N5wO3Armums2 [重试与超时策略细化(可配 + 退避)]
# Conflicts:
#	src/api/server.ts
#	test/store.test.ts
2026-06-13 10:20:20 +08:00
wangjia fcca3f95e0 fix(executor): node_modules 软链写入仓库本地 exclude,杜绝被提交进历史
上一版软链修复有回归:.gitignore 的 `node_modules/`(带斜杠)只匹配目录不匹配软链,
导致 agent 的 `git add -A` 把 `node_modules -> /abs/path` 软链提交进分支,泄露本机绝对路径
(code review + 安全审计已正确 reject)。改为建软链前先把 node_modules 写进共享
<repo>/.git/info/exclude(git 的 info/exclude 取 common dir,worktree 也读它;untracked、幂等、
不动 tracked 的 .gitignore)。测试加回归断言:git add -A 后软链不出现在 status。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 09:18:18 +08:00
wangjia 9bd02f2479 fix(executor): worktree 软链主仓 node_modules,修 verify exit 127 误判
git worktree 是干净检出不带 gitignored 的 node_modules,导致 verify
(tsc/tsx 等)与执行 agent 跑 npm 脚本时 command not found(exit 127)被误判为失败。
建 worktree 后软链主仓 node_modules:零网络、同平台 native 兼容、被 gitignore 忽略不污染 diff;
非 Node 项目(无 node_modules)自动跳过。removeWorktree 只移除软链不动主仓依赖。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 09:01:47 +08:00
wangjia c89d6d129c feat: 重试与超时策略细化(可配 + 退避)tsk_N5wO3Armums2
## 变更摘要

### 1. 项目级可配重试上限与超时
- `Project` 新增 `maxRetries`(默认 2)和 `timeoutMs`(默认 30min = 1800000ms)字段
- SQLite schema:`projects` 表补 `max_retries` / `timeout_ms` 列(带 DEFAULT 的轻量迁移)
- `createProject` / `patchProject` 支持设置 / 校验新字段(maxRetries>=0, timeoutMs>=1000)
- API `POST /api/projects` 与 `PATCH /api/projects/:id` 透传新字段
- `runner.ts` 将 `project.timeoutMs` 传给 `runClaude`,不再固定 30min

### 2. 失败重试指数退避
- 编排器内存维护 `backoffUntil` Map(taskId → nextRetryAt),daemon 重启后清空
- 退避公式:`min(30s * 2^(attempt-1), 10min)`,第 1 次 30s / 第 2 次 60s / ...
- `claimable()` 过滤退避冷却中的任务
- `nowMs` 注入点(默认 `Date.now`)使测试可快进时钟验证退避行为

### 3. needs_attention 一键重投
- `Task` 新增 `retryBaseline` 字段(默认 0):记录上次重投时的失败 run 基线
- `Store.requeueTask(taskId)`:设置基线 = 当前失败 run 数 → 转 `queued`(仅限 needs_attention)
- 编排器用净失败数(`allFailed - retryBaseline`)判断是否已耗尽重试次数
- API `POST /api/tasks/:id/requeue` + MCP `requeue_task` 工具

### 4. 测试
- 重命名 `MAX_RETRIES` → `DEFAULT_MAX_RETRIES`,新增导出 `computeBackoffMs`
- 新增测试(共 +18):maxRetries=1/0、退避时序(精确 ms 边界)、重投后基线重置
- 迁移测试扩展:验证旧库补列后 maxRetries/timeoutMs/retryBaseline 使用默认值

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 04:04:41 +08:00
wangjia bb6186902a feat: 项目 logo + 侧栏拖动排序 + 合并修复(主检出干净时 in-place)
- 项目 logo:仓库内文件(logo/icon/favicon 等多路径)→git remote 头像→自定义(URL/相对路径)→
  首字母徽章兜底;GET /api/projects/:id/logo(文件流/302),配置面板加 Logo 输入
- 侧栏项目拖动排序:projects.sort_order + POST /api/projects/reorder,乐观更新
- 合并修复:默认分支正被主检出占用时,若工作区干净则直接在主检出 in-place 合并
  (用户手动合并的等价操作,安全);脏工作区拒绝并提示提交/暂存或仅通过
- schema: projects.logo / sort_order(ensureColumn 平滑迁移)

测试 75/75(merge 用例改为干净→成功/脏→拒绝)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 03:45:24 +08:00
wangjia 740d2c2637 feat: PR 审核流程 + 自动合并 + macOS 通知 + 订阅额度透传 + 归档详情
PR 流程(开发→提PR→CodeReview→安全审计→审核→通过即合并):
- reviewer 拆分为 code review 与安全审计两个独立 CC run(kind=reviewer/security),
  TaskResult 四字段(summary/verdict + securitySummary/securityVerdict),闸上两节报告两枚结论徽章
- executor/merge.ts: 通过即合并——临时 worktree 内 merge --no-ff,绝不碰用户工作区/不 push;
  冲突安全拒绝(报冲突文件);重复合并幂等;合并后回收执行 worktree + 删分支
- decide 路由 merge:false 逃生口 + 看板「仅通过」按钮(目标分支被工作区检出时用)

通知(daemon/notify.ts):
- macOS 原生通知: 进审核闸(复审建议拒绝标⚠)/连续失败需人工/合并完成
- 同任务同类型 60s 抑制、osascript 转义截断、MAESTRO_NOTIFY=0 关闭

订阅额度透传(daemon/usage.ts):
- OAuth usage API(与 Claude Code/claude-hud 同源),凭证 keychain→内存零泄漏
- 60s 成败双缓存+并发去重+5s 超时,失败降级 null
- GET /api/agents 顶层 usage 字段;Agent 面板显示 5h/周用量条+重置倒计时(>80%琥珀/>95%红)

看板与生命周期:
- 归档区: 深度1整树完成沉底,时间倒序分页(尺寸 chip 10/20/50/100 置底)
- 归档详情对话框: 全属性/执行历史与时长/审批记录/状态流转时间线(GET /api/tasks/:id/events)
- 容器收口: 已拆解 Hard 子任务全 done 自动 done(afterDone 逐级向上)
- 同步按钮收进配置面板;执行白名单扩测试命令(npm/go/shellcheck/make/pytest)
- Agent 面板显示调度模式与各复杂度模型;被依赖阻塞→被阻塞

测试: 74/74(新增 merge 6/notify 10/usage 7/容器收口/双复审适配)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 03:22:30 +08:00
wangjia f18db021c3 feat: Phase2 完整管线——score 调度 + 自动复审 + 模型分级 + 归档与详情
调度:
- model/scoring.ts: score = 自身分(P0=3/P1=2/P2=1) + 已完成依赖分(链条惯性)
  + 等待解锁的 blocked 任务分(解锁加权),编排器与 nextExecutable 同一打分
- createTask 校验 deps 存在且同项目(依赖图天然无环)
- daemon 重启中断自愈: executing 任务标 failed run 后重新入队(reconcileInterrupted)

执行管线:
- executor/cc.ts: 公共 headless CC 执行器(转录/超时/模型回退重试)
- executor/reviewer.ts: 执行后自动复审(只读 CC 审 diff),固定模板 summary
  (做了什么/怎么做/测试/CodeReview/安全Review/结论) + VERDICT 解析
- executor/models.ts: 按复杂度选模型(easy→sonnet/medium→opus/hard→fable5),
  env 可覆盖、project.model 最优先、不可用自动回退链
- runner: 测试/构建命令白名单(npm/go/shellcheck/make/pytest),prompt 要求实跑测试
- TaskResult 加 summary/verdict; RunKind 加 reviewer
- 容器收口: 已拆解 Hard 子任务全 done → 容器自动 done(afterDone 逐级向上)

看板:
- 五徽章组(待审批/待执行/执行中/被阻塞/总量,hover 展开,均不含已完成)
- 归档区: 深度1整树完成沉底,时间倒序分页(10/20/50/100 chip 选择)
- 归档详情对话框: 全属性/执行历史与时长/审批记录/状态流转时间线(含相关人或事)
- Agent 面板显示调度模式 + 各复杂度实际模型
- 结果闸展示复审 summary + 建议通过/拒绝徽章
- 筛选修复(组选与单选分离、已拆解移出进行中)、同步按钮收进配置面板、
  保存配置自动收起、预览全宽、被依赖阻塞→被阻塞
- API: GET /api/tasks/:id/events(任务级事件时间线)、/api/agents 带 scheduling/models

测试: 49/49(新增 scoring/复审/模型/容器收口/deps 校验/中断恢复)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 02:46:37 +08:00