feat: integrate fork work onto upstream main (squashed)

Squash-merge of feat/autofix-pr-test (69 commits) onto upstream/main
with -X ours strategy (upstream as authoritative for content conflicts).

Key features brought in from fork:
- LocalMemoryRecall + VaultHttpFetch tools (end-to-end wired)
- /local-memory, /local-vault, /memory-stores, /skill-store interactive panels
- /agents-platform, /schedule, /vault command scaffolding
- /login: switch / replace / remove of workspace API key
- statusline refactor (built-in status row, /statusline as info command)
- autofix-pr command + workflow

Conflict resolutions (upstream-wins):
- 10 .js command stubs kept from upstream (alongside fork's .ts implementations)
- src/components/BuiltinStatusLine.tsx accepted upstream's deletion
  (fork's wire-up references in StatusLine.tsx will be cleaned up next)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
unraid
2026-05-08 16:47:29 +08:00
parent 73e54d4bbc
commit 8945f08708
233 changed files with 40597 additions and 341 deletions

View File

@@ -0,0 +1,431 @@
# P2 Endpoints — Reverse-Engineering Spec
**Date:** 2026-04-29
**Binary analyzed:** `C:\Users\12180\.local\bin\claude.exe` (Anthropic official v2.1.123, 253 MB Bun-compiled)
**Method:** `grep -ao` over the binary for path literals, function symbols, JSON keys, telemetry events, and surrounding code fragments.
**Goal:** Decide which P2 endpoints justify fork implementation and produce ready-to-execute plans for the high-value ones.
---
## /v1/skills
### 反向查阅证据
- **路径:**
- `GET /v1/skills?beta=true` (list)
- `GET /v1/skills/{skill_id}?beta=true` (get)
- `GET /v1/skills/{skill_id}/versions?beta=true` (list versions)
- `GET /v1/skills/{skill_id}/versions/{version}?beta=true` (get specific version)
- `POST /v1/skills/{skill_id}/versions?beta=true` (publish new version) — `PNH({body:_,...})`
- Beta gate: `?beta=true` on every call
- **函数符号 (官方 binary):**
`CreateSkill`, `DeleteSkill`, `GetSkill`, `ListSkills`, `getPluginSkills`, `discoveredRemoteSkills`, `getSessionSkillAllowlist`, `formatSkillLoadingMetadata`, `addInvokedSkill`, `clearInvokedSkillsForAgent`, `cappedSkills`, `bundledSkills`, `dynamicSkillDirs`, `dynamicSkillDirTriggers`, `collectSkillDiscoveryPrefetch`
- **HTTP method 推断:** GET (list/get), POST (publish version) — DELETE/PATCH 在 binary 里没找到对应 path 字符串,疑似只读 marketplace + publish
- **Request 字段:** `allowed_tools`, `owner`, `owner_symbol`, `deprecated`(其他字段被 minify 字典化,未泄漏明文)
- **Response 字段:** 同上 + version metadata推断含 `created_at``version` 字符串)
- **Telemetry:** `tengu_skill_loaded`, `tengu_skill_tool_invocation`, `tengu_skill_tool_slash_prefix`, `tengu_skill_file_changed` **全部针对本地/bundled无 marketplace 专属事件**
- **Fork 已有 utility:**
- `src/skills/bundled/` 21+ TS skills不含 marketplace
- `src/skills/loadSkillsDir.ts``bundledSkills.ts`
- `src/services/skill-search/`DiscoverSkillsTool TF-IDF
- `src/services/skill-learning/`(自动学习闭环)
- 缺:远程 marketplace fetch、远程 skill 安装到 `~/.claude/skills/`、版本管理
### 用途推断
`/v1/skills` 是 Anthropic 托管的 skill marketplace类似 npm/cargo 但只读 + 受限 publish让用户在 CLI 里浏览/安装/更新由社区或 Anthropic 官方发布的 markdown skill 包。Fork 当前只有 bundled TS skills**完全没有 user-defined markdown skill 加载机制**(见 `reference_fork_skills_architecture.md` memory即使复刻这个 endpoint 也需要先实施 markdown skill loader 才能消费下载的内容。
### Fork 是否值得实施
- **价值:** **P2-C不建议**
- **工作量估算:** ~1500 行marketplace API client 300 + version diffing 200 + markdown skill loader 400 + install/update flow 250 + UI picker 200 + tests 150
- **依赖订阅用户:** **是**`?beta=true` + Anthropic-managed registry需 Anthropic API key + 大概率需要 Claude.ai 账号才能拉到非空 list
- **类比 fork 已有命令:** `/plugin`plugin marketplace 已恢复,路径类似但 plugin 用本地 git 仓库 + manifest
- **阻塞依赖:** 必须先实施 markdown skill loaderfork **架构上不存在**marketplace 内容需要订阅;社区注册表为空(即使能登录拿到的是 Anthropic-curated 的少数官方 skill
- **替代方案:** 增强 `/plugin` 命令支持 skill 类型 plugin用 git clone + 本地 markdown loader 实现等价能力(成本更低、不依赖 Anthropic 后端)
### 推荐 fork 命令外壳
**SKIP — 不实施。** 如果未来要做,路径是:
1. 先实施 markdown skill loader`~/.claude/skills/<name>/SKILL.md` frontmatter 解析)— 单独 P1 项
2. 复刻 `/plugin` 风格的 `/skills` 命令但 backend 用 git URL 而非 Anthropic API
3. 把 marketplace endpoint 留给上游订阅用户
---
## /v1/code/triggers
### 反向查阅证据
- **路径:**
- `GET /v1/code/triggers` (list)
- `POST /v1/code/triggers` (create)
- `GET /v1/code/triggers/{trigger_id}` (get)
- `POST /v1/code/triggers/{trigger_id}` (update — **不是** PATCH/PUT)
- `POST /v1/code/triggers/{trigger_id}/run` (manual fire)
- DELETE 没在 binary 里看到独立 path推断走 update 设 `enabled:false` 或独立 archive
- **函数符号:** `RemoteTrigger`, `RemoteTriggerTool`, `createTrigger`, `RemoteAgentTask`, `RemoteAgentMetadata`, `RemoteAgentsSkill`, `registerScheduleRemoteAgentsSkill`, `addSessionCronTask`, `getRoutineCronTasks`, `getSessionCronTasks`, `removeSessionCronTasks`, `cancelAllPendingLoopSessionCrons`, `buildCronCreateDescription`, `buildCronCreatePrompt`, `buildCronListPrompt`, `buildCronDeletePrompt`, `getCronJitterConfig`, `isDurableCronEnabled`, `isKairosCronEnabled`
- **HTTP method 完整证据:**binary 文档串)
- `create: POST /v1/code/triggers`
- `update: POST /v1/code/triggers/{trigger_id}`
- `run: POST /v1/code/triggers/{trigger_id}/run`
- `list: GET /v1/code/triggers`
- `get: GET /v1/code/triggers/{trigger_id}`
- **Request 字段:** `cron`, `cron_expression`, `enabled`, `prompt`, `schedule`, `cron_hour`, `cron_minute`, `team_memory_enabled`, `agent_id`(推断,触发器关联到一个 agent
- **Response 字段:** `trigger_id`, `next_run`, `last_run`, `enabled`, `scheduled_task_fire`telemetry 名)
- **Telemetry:** **没有** `tengu_trigger_*` 专属事件(被 ultraplan/sedge 等其他系统的事件覆盖;`scheduled_task_fire` 是状态字符串,不是 telemetry
- **关联 fork:**
- `/agents-platform` 已实现(`agentsApi.ts``/v1/agents`)— **Triggers 是给 Agents 加 cron 调度,关系 = "trigger refs agent"**
- `/schedule` skill在 user `~/.claude/skills/` 列表里)= 这个 endpoint 的 user-facing 入口
-fork **没有** `/schedule` 命令、没有 trigger CRUD client
- **关联 description / 错误文案:** `"Schedule a recurring cron that runs those tasks each tick"`, `"Scheduled recurring job"`, `"Scheduled token refresh for session"`
### 用途推断
让用户给已创建的 remote agent`/v1/agents`)挂上 cron 调度:例如"每天早上 9 点跑这个 agent给我一份昨天 PR 状态摘要"。是 `/agents-platform` 的姐妹功能,**没有它agent 只能手动跑**。绑定到 Anthropic 后端 + Claude.ai 账号(订阅用户的 cloud 远程 agent跟本地 cron 完全不同)。
### Fork 是否值得实施
- **价值:** **P2-A**
- **工作量估算:** ~480 行triggersApi.ts 130 + index.tsx 80 + launchSchedule.tsx 90 + ScheduleView.tsx 120 + parseArgs.ts 30 + tests 30
- **依赖订阅用户:** **是**POST /v1/code/triggers 需要 Bearer auth订阅用户才有可见 trigger 列表)— 但 fork 已经接受这个前提(参考 `/agents-platform` 已上线)
- **类比 fork 已有命令:** `/agents-platform`(同 backend 家族 + 同 auth 模型 + 同 list/get/create/delete UI 模式)
### 推荐 fork 命令外壳
- **命令名:** `/schedule`
- **子命令:** `list` / `get <id>` / `create <args>` / `update <id> <args>` / `run <id>` / `delete <id>` / `enable <id>` / `disable <id>`
- **类型:** local-jsx
- **aliases:** `/cron`, `/triggers`
- **估算行数:**
- `index.tsx` ~80command def + `userFacingName`+ subcommand router
- `launchSchedule.tsx` ~90router 选择 list/get/create/update/run/delete + JWT 注入)
- `triggersApi.ts` ~1305 个 CRUD + run复用 `agentsApi.ts` 的 fetch + auth 模式)
- `ScheduleView.tsx` ~120trigger table、cron 解析显示 next_run、状态切换
- `parseArgs.ts` ~30cron 表达式校验、agent_id 解析、`--enabled` flag
- `__tests__/schedule.test.ts` ~30
- **配套整合:** complementary skill 已存在user `~/.claude/skills/schedule/`fork 可在 launcher 里支持 `--from-skill` 调用 skill 的 prompt 然后落到这个 API
---
## /v1/memory_stores
### 反向查阅证据
- **路径:**
- `POST /v1/memory_stores` (create)
- `GET /v1/memory_stores` (list)
- `GET /v1/memory_stores/{memory_store_id}` (get)
- `POST /v1/memory_stores/{memory_store_id}/archive` (archive — soft delete)
- `GET /v1/memory_stores/{memory_store_id}/memories` (list memories in store)
- `PATCH /v1/memory_stores/{memory_store_id}/memories` (bulk patch)
- `GET /v1/memory_stores/{memory_store_id}/memories/{memory_id}` (get individual memory)
- `POST /v1/memory_stores/{memory_store_id}/memory_versions` (create version)
- `GET /v1/memory_stores/{memory_store_id}/memory_versions/{version_id}` (get version)
- `POST /v1/memory_stores/{memory_store_id}/memory_versions/{version_id}/redact` (PII redaction)
- **函数符号:** `CreateMemoryStore`, `GetMemoryStore`, `ListMemoryStores`, `UpdateMemoryStore`, `DeleteMemoryStore`, `ArchiveMemoryStore`
- **HTTP method:** GET / POST / PATCH多动词明文已泄漏在 `\r\n` 换行串里)
- **Request 字段:** `memories`(数组), `namespace`, `redacted_thinking`(其他字段未泄漏)
- **Response 字段:** 推断含 `memory_store_id`, `memory_id`, `version_id`, `archived_at`, `redacted_at`
- **Telemetry:** `tengu_memory_survey_event`, `tengu_memory_threshold_crossed`, `tengu_memory_toggled`, `tengu_memory_write_survey_event`**不是** memory_stores 专属,是本地 `extractMemories` / `SessionMemory` 服务的事件
- **关联 fork 已有 utility:**
- `/memory` 命令已存在(`src/commands/memory/`)— 但管理本地 `~/.claude/memory/` 文件
- `src/services/extractMemories/`(自动 extract
- `src/services/SessionMemory/`session 级 memory
- **缺:** 远程 memory_stores多 store 命名空间 + 版本控制 + 跨设备同步 + redact
### 用途推断
Anthropic 托管的 memory 持久化层,跟本地 `auto_memory_*.md` 文件的关系类似:本地文件 = 单机 markdownmemory_stores = 跨设备/跨 session 的命名空间化 + 版本化 + PII redact 服务。订阅用户在不同机器之间同步 memoryredact endpoint 让用户主动删除已存储的敏感信息GDPR 合规)。
### Fork 是否值得实施
- **价值:** **P2-B**
- **工作量估算:** ~600 行memoryStoresApi.ts 200 + index.tsx 90 + launchMemoryStore.tsx 120 + MemoryStoreView.tsx 130 + parseArgs.ts 30 + tests 30
- **依赖订阅用户:** **是**cloud 持久化必须有 Anthropic auth
- **类比 fork 已有命令:** `/memory`(本地)+ `/agents-platform`(远程 CRUD 模式)
- **价值降级理由:** fork 现在有非常强的本地 memory 体系(`~/.claude/projects/<project>/memory/*.md` + `extractMemories` + 7-day staleness90% 用户场景不需要远程 store。Marginal value 主要给"多机器同步"用户。
### 推荐 fork 命令外壳
- **命令名:** `/memory-stores`(避免冲突现有 `/memory`
- **子命令:** `list` / `get <id>` / `create <name>` / `archive <id>` / `memories <store_id>` / `memory <store_id> <memory_id>` / `version <store_id> <version_id>` / `redact <store_id> <version_id>`
- **类型:** local-jsx
- **aliases:** `/ms`, `/remote-memory`
- **估算行数:**
- `index.tsx` ~90
- `launchMemoryStore.tsx` ~120subcommand router
- `memoryStoresApi.ts` ~20010 个端点,复用 agentsApi 模式)
- `MemoryStoreView.tsx` ~130store list + drill-down
- `parseArgs.ts` ~30
- tests ~30
- **配套整合:** 在 `/memory` 命令里加 `--push` flag 把本地 memory 推到默认 store联动— 单独跟进项
---
## /v1/vaults
### 反向查阅证据
- **路径:**
- `GET /v1/vaults` (list — POST 推断为 create)
- `GET /v1/vaults/{vault_id}` (get)
- `POST /v1/vaults/{vault_id}/archive` (archive)
- `GET /v1/vaults/{vault_id}/credentials` (list credentials in vault)
- `GET /v1/vaults/{vault_id}/credentials/{credential_id}` (get credential)
- `POST /v1/vaults/{vault_id}/credentials/{credential_id}/archive` (archive credential)
- **函数符号:** `CreateVault`, `GetVault`, `ListVaults`, `UpdateVault`, `DeleteVault`, `ArchiveVault`, `nVaults`(数量统计)
- **HTTP method 推断:** GETlist/get+ POSTarchive+ 推断 POSTcreate/update credentials
- **Request 字段:** `kind`, `secret`, `vault_ids`其他字段未泄漏secret 推断是 credential value类型 enum 含 `kind`
- **Response 字段:** 推断 `vault_id`, `credential_id`, `archived_at`, `kind`(不返回 secret 明文,仅 metadata
- **Telemetry:** **零** `tengu_vault_*` 事件(保护 secret 路径不上报 telemetry符合安全最佳实践
- **关联 fork:** **完全无** vault 相关代码
### 用途推断
Anthropic 托管的 secrets vault让 remote agents`/v1/agents`+ triggers`/v1/code/triggers`)在 cloud 执行时安全地拿到 API key、SSH key、OAuth token 等敏感信息。**不是给本地 CLI 用户管 secret 的** — fork 本地 CLI 已经能直接读环境变量。这是 cloud-first 体验的依赖项。
### Fork 是否值得实施
- **价值:** **P2-C不建议**
- **工作量估算:** ~550 行vaultsApi.ts 180 + index.tsx 90 + launch 110 + view 120 + parseArgs 25 + tests 25
- **依赖订阅用户:** **是**强依赖core feature is cloud secret injection — 本地用户根本用不到)
- **类比 fork 已有命令:** 无;最接近 `/agents-platform`
- **价值降级理由:**
1. fork 用户主要在本地跑 CLIsecret = 环境变量 / `.env` / OS keyring**不需要 cloud vault**
2. 没有 `/v1/code/triggers` 实装时vault 没有消费方
3. Vault binary 里 0 telemetry → 上游也认为这是 plumbing 不是 hero feature
4. 安全敏感路径(参 `~/.claude/rules/deep-debug/security.md`CLI client 实施 cloud secret 操作风险高
- **替代方案:** 不实施;如果用户有跨命令复用 secret 需求,推荐用 `gh auth` / `pass` / OS keyring 集成(独立 P3 项)
### 推荐 fork 命令外壳
**SKIP — 不实施。** 等到 `/schedule` + `/memory-stores` 上线后用户提出真实需求再考虑。
---
## /v1/ultrareview/preflight
### 反向查阅证据
- **路径:** `POST /v1/ultrareview/preflight`(仅一个端点,不像其他端点是完整 CRUD 家族)
- **函数符号:** `fetchUltrareviewPreflight`, `launchUltrareview`, `hasSeenUltrareviewTerms`, `UltrareviewPreflight`, `UltrareviewTerms`, `ultrareviewHandler`
- **HTTP method:** POSTheaders `{...Lf(q),...}`body 推断含 PR 引用)
- **Request 字段:** 推断 `pr_url` / `pr_number` / `repo` / `confirm` flag (从 `launchUltrareview(H, q?.confirm??false)` 推断)
- **Response 字段:** Zod schema 已泄漏明文:
```js
vq.object({
action: vq.enum(["proceed", "confirm", "blocked"]),
billing_note: vq.string().nullable().optional(),
// ...其他字段被截断
})
```
- **Telemetry:** `tengu_review_overage_blocked`, `tengu_review_remote_teleport_failed`, `ultrareview_launch`subtype
- **关联错误文案:**
- `"Ultrareview is currently unavailable."`
- `"Ultrareview is unavailable for your organization."`
- `"Ultrareview requires a Claude.ai account. Run /login to authenticate."`
- `"Repo is too large. Push a PR and use /ultrareview <PR#> instead."`
- `"Ultrareview runs in Claude Code on the web and is unavailable when essential-traffic-only mode is active."`
- `"Ultrareview launched for ${j} (${Sl()}, runs in the cloud). Track: ${J}"`
- **关联 fork 已有 utility:**
- `src/commands/review/ultrareviewCommand.tsx` — 命令骨架已存在
- `src/commands/review/ultrareviewEnabled.ts` — feature gate
- `src/commands/review/UltrareviewOverageDialog.tsx` — overage UI
- `src/services/api/ultrareviewQuota.ts` — quota check
- `src/commands/review/reviewRemote.ts` — remote launch
- **缺:** preflight call **没接进 launch 流程**fork 直接 launch跳过 confirm/blocked 分流)
### 用途推断
`/preflight` 在 launch 之前问 Anthropic 后端三件事:(1) 当前 PR 大小是否超 quota → `blocked`(2) 当前用量是否进入收费区间 → `confirm` + `billing_note`"this run will cost ~$3"(3) 一切 OK → `proceed`。Fork 当前直接 launch 会让用户在使用超额时被静默扣钱或失败,体验不好但不致命。
### Fork 是否值得实施
- **价值:** **P2-A**
- **工作量估算:** ~250 行preflightApi.ts 80 + 扩展 ultrareviewCommand 60 + PreflightDialog.tsx 80 + tests 30
- **依赖订阅用户:** **是** — 但 fork 已经把整个 ultrareview 当成订阅功能(非订阅用户走 `ultrareviewEnabled.ts` 早 return
- **类比 fork 已有命令:** `/ultrareview`本身已存在preflight 只是补缺失的步骤)
### 推荐 fork 命令外壳
**不需要新命令** — 增强已有 `/ultrareview`
- 文件改动:
- 新增 `src/services/api/ultrareviewPreflight.ts` ~80fetchUltrareviewPreflight + Zod schema for `{action, billing_note}`
- 修改 `src/commands/review/ultrareviewCommand.tsx` +50在 `launch` 之前 await preflight分流 proceed/confirm/blocked
- 新增 `src/commands/review/UltrareviewPreflightDialog.tsx` ~80confirm 状态时显示 billing_note + Yes/No
- 修改 `src/components/PromptInput/PromptInput.tsx` 已有 ultrareview hook可能需小调整
- tests `src/services/api/__tests__/ultrareviewPreflight.test.ts` ~30
- **重要:** `blocked` 状态显示 binary 里的明文文案(保持与官方一致),不要自创错误信息
---
## 总优先级表
| Endpoint | 价值 | 估算行数 | 依赖订阅 | 推荐顺序 | fork 命令 |
|----------|:---:|:---:|:---:|:---:|---|
| `/v1/code/triggers` | **P2-A** | ~480 | 是 | **1** | `/schedule` (new) |
| `/v1/ultrareview/preflight` | **P2-A** | ~250 | 是 | **2** | enhance `/ultrareview` |
| `/v1/memory_stores` | P2-B | ~600 | 是 | 3可选 | `/memory-stores` (new) |
| `/v1/skills` | P2-C | ~1500 | 是 | SKIP | — |
| `/v1/vaults` | P2-C | ~550 | 是 | SKIP | — |
**P2-A 总投入:** ~730 行triggers 480 + preflight 250约 1-2 工作日,无 commands.ts 冲突(两个改动是独立目录 + 一个增强已有命令)。
**实施推荐顺序(避免 commands.ts 冲突):**
1. **先做 `/v1/ultrareview/preflight`**(不新增 commands.ts 条目,仅增强 ultrareviewCommand → 零冲突,立刻可上线)
2. **再做 `/v1/code/triggers`** as `/schedule`(新增 commands.ts 1 条,参考 `/agents-platform` 模式)
3. **`/v1/memory_stores`** 视用户反馈再上 — 实施前先设计如何与 `/memory` 联动避免认知混淆
4. **`/v1/skills` 和 `/v1/vaults` SKIP** — 前者依赖 markdown skill loaderfork 架构缺失),后者本地用户不需要
---
## 实施 Plan A — `/v1/ultrareview/preflight`P2-A 第 1 优先)
### 范围
补全 fork `/ultrareview` 命令的 preflight 检查launch 前调 `POST /v1/ultrareview/preflight`,根据 `action` 分流 `proceed` / `confirm` / `blocked`,对齐官方 v2.1.123 行为。
### 上游证据
- 函数 `fetchUltrareviewPreflight`、`launchUltrareview(H,q?.confirm??false)`
- Zod schema: `{action: enum(["proceed","confirm","blocked"]), billing_note: string().nullable().optional()}`
- 错误文案表(见上)
### 文件清单(按此精确改)
| 文件 | 改动类型 | 行数估计 |
|---|---|---|
| `src/services/api/ultrareviewPreflight.ts` | NEW | ~80 |
| `src/services/api/__tests__/ultrareviewPreflight.test.ts` | NEW | ~30 |
| `src/commands/review/ultrareviewCommand.tsx` | EDIT | +50 |
| `src/commands/review/UltrareviewPreflightDialog.tsx` | NEW | ~80 |
| `src/commands/review/__tests__/ultrareviewCommand.test.tsx` | EDIT | +20 |
### 实施步骤
1. **创建 `ultrareviewPreflight.ts`:**
- export `fetchUltrareviewPreflight(args: {pr_url?: string, pr_number?: number, repo: string, confirm?: boolean}): Promise<{action: 'proceed'|'confirm'|'blocked', billing_note: string|null} | null>`
- 调 `POST /v1/ultrareview/preflight` 复用 `src/services/api/claude.ts` 的 auth header 注入(参考已有 `ultrareviewQuota.ts`
- Zod schema 校验响应mismatch 时 log warning + return null不抛错
2. **创建 `UltrareviewPreflightDialog.tsx`:**
- props: `{billingNote: string|null, onConfirm(), onCancel()}`
- Ink 组件,显示 billing_note + 两个按钮 `Proceed` / `Cancel`
- 复用 `src/components/design-system/Dialog`
3. **修改 `ultrareviewCommand.tsx`:**
- 在调 `reviewRemote.ts` launch 之前 `await fetchUltrareviewPreflight(...)`
- `action === 'blocked'`: 显示 `"Ultrareview is currently unavailable."`(或 `billing_note` 如果有return
- `action === 'confirm'`: 渲染 `<UltrareviewPreflightDialog>` → 用户点 Proceed 后才 launch
- `action === 'proceed'`: 直接 launch
- preflight 返回 nullschema mismatch / network: fallback 到当前直接 launch 行为 + warning toast
4. **测试:**
- `ultrareviewPreflight.test.ts`: schema 校验 3 个 casevalid proceed / valid blocked / invalid → null
- `ultrareviewCommand.test.tsx`: mock fetchUltrareviewPreflight 三种返回,断言分流正确
### 验证命令
```bash
cd E:/Source_code/Claude-code-bast-autofix-pr && bun run typecheck && bun test src/services/api/__tests__/ultrareviewPreflight.test.ts src/commands/review/__tests__/ultrareviewCommand.test.tsx
```
### 边界条件
- 网络失败 / 超时 / 401: 返回 nullfallback 到直接 launch保持当前行为不破坏现有用户
- `billing_note` 为 null but action='confirm': 显示通用文案 `"This run may incur additional cost."`
- 用户通过 `--confirm` flag 显式跳过 dialog直接传 `confirm:true` 给 preflight
### 不做
- 不改 `ultrareviewQuota.ts`独立机制preflight 是 quota 的上层)
- 不改 telemetryfork 没有上报 ultrareview 事件,保持)
- 不本地化错误文案(与官方保持英文一致)
### 输出格式
implementer 报告:(1) 5 个文件 diff 摘要;(2) typecheck 输出;(3) test pass count(4) 三种 action 各跑一次手动验证截图(如能)。
### SKIP 路径
如果发现 fork 的 `ultrareviewQuota.ts` 已经做了等价 preflight 检查 → 报告并停止;不要重复实现。
---
## 实施 Plan B — `/v1/code/triggers` as `/schedule`P2-A 第 2 优先)
### 范围
新增 `/schedule` 命令实现 cloud-side trigger CRUD让用户给 `/v1/agents` 创建/管理/触发 cron 调度。复用 `/agents-platform` 的 API client + UI 模式。
### 上游证据
- 完整 CRUD verb 表(见上):`create POST /v1/code/triggers` / `update POST /v1/code/triggers/{id}` / `run POST .../run` / `list GET` / `get GET .../{id}`
- 函数 `RemoteTrigger`, `RemoteTriggerTool`, `createTrigger`, `RemoteAgentsSkill`, `addSessionCronTask`, `buildCronCreatePrompt`
- 字段 `cron`, `cron_expression`, `enabled`, `prompt`, `cron_hour`, `cron_minute`, `team_memory_enabled`
- 命令字面量: `"schedule",aliases:[...]`
### 文件清单
| 文件 | 改动类型 | 行数估计 |
|---|---|---|
| `src/commands/schedule/triggersApi.ts` | NEW | ~130 |
| `src/commands/schedule/index.tsx` | NEW | ~80 |
| `src/commands/schedule/launchSchedule.tsx` | NEW | ~90 |
| `src/commands/schedule/ScheduleView.tsx` | NEW | ~120 |
| `src/commands/schedule/parseArgs.ts` | NEW | ~30 |
| `src/commands/schedule/__tests__/schedule.test.ts` | NEW | ~30 |
| `src/commands.ts` | EDIT | +1 行注册 |
### 实施步骤
1. **复制 `src/commands/agents-platform/agentsApi.ts` → `triggersApi.ts`**:
- 替换路径 `/v1/agents` → `/v1/code/triggers`
- 5 个方法:`listTriggers`, `getTrigger(id)`, `createTrigger(body)`, `updateTrigger(id, body)`, `runTrigger(id)`
- 类型 `Trigger = {trigger_id, cron_expression, enabled, prompt, agent_id, last_run?, next_run?}`
2. **`parseArgs.ts`:**
- 解析 subcommand`list | get <id> | create <args> | update <id> <args> | run <id> | enable <id> | disable <id>`
- cron 表达式校验reuse `cron-parser` 或 fork 现有 utility如果有
3. **`ScheduleView.tsx`:**
- 复用 `AgentsPlatformView.tsx` 的 table 风格
- 列trigger_id (truncated), agent_id, cron, enabled, next_run
- 详情 drill-down 显示完整 prompt
4. **`launchSchedule.tsx`:**
- subcommand router 调对应 API method
- create 时 prompt 用户输入 agent_id或从 `/agents-platform` list 选)
- enable/disable = update 改 `enabled` 字段
5. **`index.tsx`:**
- command def `userFacingName: 'schedule'`, aliases `['cron','triggers']`, type `local-jsx`
6. **`commands.ts`:**
- 在主 `COMMANDS = memoize([...])` 数组加 `scheduleCommand`(不要放 `INTERNAL_ONLY_COMMANDS` — 见 `project_stub_recovery_2026_04_29.md` memory
### 验证命令
```bash
cd E:/Source_code/Claude-code-bast-autofix-pr && bun run typecheck && bun test src/commands/schedule/__tests__/schedule.test.ts
```
### 边界条件
- 401 / 订阅过期: 显示 `"Schedule requires a Claude.ai subscription. Run /login."`(与 ultrareview 文案对齐)
- 空 trigger 列表: 友好提示 + 推荐 `--help`
- 无效 cron 表达式: 客户端 parse 失败立即报错,不打 API
- agent_id 不存在: API 返回 404显示 `"Agent {id} not found. Use /agents-platform to verify."`
### 不做
- 不实施本地 cron daemonfork 已有 `daemon` 模块但跟这个 cloud trigger 是独立体系)
- 不实施 `team_memory_enabled` 字段 UI先支持核心 cron + prompt + agentteam memory 留 follow-up
- 不实现 trigger DELETEbinary 里 path 不明确,先用 archive 或 enabled:false
### 输出格式
implementer 报告:(1) 7 个文件 diff(2) typecheck 输出;(3) test pass(4) 手动 list/create/run 端到端验证(如有 Anthropic API key + 测试账号)。
### SKIP 路径
- 如果发现 binary 里 trigger DELETE 端点存在的更明确证据,可加 deleteTrigger否则只支持 archive。
- 如果 fork 已有用 `RemoteTriggerTool`(按 grep 提示 `src/tasks/RemoteAgentTask/RemoteAgentTask.tsx` 引用),先 read 确认无重叠,避免重写。
---
**End of spec.** 实施 Plan A 和 B 可独立并行(无 commands.ts 顺序依赖Plan A 不动 commands.tsPlan B 加一行。Plan A 优先因为它是 *enhancement* 不是 *new command*,破坏面更小。