Files
claude-code/docs/jira/P2-ENDPOINTS-SPEC.md
unraid 8945f08708 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>
2026-05-09 14:58:26 +08:00

432 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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*,破坏面更小。