20 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | |||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 01-credential-slot-api | 02 | execute | 2 |
|
|
true |
|
|
并通过一个临时探针 .tsx 文件验证外部消费者可以从 @/lib/api 入口解析新增的 4 个符号;探针验证完成后删除。
Purpose:把 Phase 1 的「成功 = 代码 + 文档 + 类型可被消费」三件套全部落地,为 Phase 2/3 提供干净起点。
Output:docs/修改记录.md(修改);plan 落地后无新代码文件残留(探针文件验证后删除)。
<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/phases/01-credential-slot-api/01-CONTEXT.md @.planning/phases/01-credential-slot-api/01-RESEARCH.md @.planning/phases/01-credential-slot-api/01-01-SUMMARY.md@CLAUDE.md @docs/修改记录.md @package.json @next.config.mjs @lib/api/credential-slot.ts @lib/api/index.ts
Task 1:在 docs/修改记录.md 顶部追加 Phase 1 条目<read_first>
- docs/修改记录.md L1-50(特别是 L9-20 头部「修改格式说明」 + L24-47 已存在的 [2026-05-07] Phase 2 条目作为格式模板)
- CLAUDE.md L70-95「项目修改记录规则」 — 强制每次代码改动追加到顶部、跨项目独立维护
- .planning/phases/01-credential-slot-api/01-CONTEXT.md 节「修改记录」段(L152-156)— 锁定的跨项目联动文案
- .planning/phases/01-credential-slot-api/01-RESEARCH.md 「Code Examples」节内的「docs/修改记录.md 顶部追加条目」完整模板
</read_first>
docs/修改记录.md
在 `docs/修改记录.md` 中找到这一行:<!-- 新的修改记录添加在此处下方,最新的在最前面 -->
在该注释行之后、紧贴现有 ### [2026-05-07] Phase 2 — 锁定后端通用凭据槽位 REST 接口契约(消费方文档化) 条目之前,插入以下完整 Markdown 块(之间留 1 个空行):
### [2026-05-08] Phase 1(前端)凭据槽位 API 客户端
配套服务端 Phase:[../qy_lty/.planning/phases/02-admin-rest/](../../qy_lty/.planning/phases/02-admin-rest/)(已落地,commit 46d72b8)
覆盖前端需求:CRED-FE-01
- **文件路径**:
- `lib/api/credential-slot.ts`(新增)
- `lib/api/index.ts`(修改)
- **修改类型**: 新增(API 客户端层;纯逻辑,无 UI 改动)
- **修改内容**:
- 新建 `lib/api/credential-slot.ts`,封装:
- 类型 `CredentialSlot { appId, accessTokenMasked, updatedAt }`(脱敏掩码语义命名)
- 类型 `CredentialSlotUpdatePayload { appId, accessToken }`(明文语义命名)
- 适配器 `mapBackendCredentialSlot()`(snake_case → camelCase)
- API 函数 `getCredentialSlot()` / `updateCredentialSlot(payload)`,分别走 `apiClient.get` / `apiClient.put` 命中 `/v1/admin/credential-slot/`,沿用仓库统一的 `response.data?.data || response.data` 双保险解包;PUT body 仅传 `{ app_id, access_token }`,不携 `updated_at`(与 `updateAiModel` / `updateOutfit` 风格一致)
- `lib/api/index.ts` 末尾追加具名 re-export,让组件层可 `import { getCredentialSlot, type CredentialSlot } from '@/lib/api'`
- **修改原因**:
- 启动 Milestone v1.0「通用凭据槽位前端集成」,本 phase 为后续 Phase 2(RBAC + 入口控件)、Phase 3(编辑对话框 + Sonner 反馈)提供调用层基础
- `accessTokenMasked` vs `accessToken` 故意命名不同,让 TS 编译期捕捉「把脱敏字符串当真值回写 PUT」的 bug
- **服务端联动**: 无 — Phase 1 是纯 API client 层落地(无 UI 改动),调用的后端接口由 qy_lty 后端 Milestone v1.0 Phase 2 提供(commit `46d72b8` 已建立前后端互引修改记录);本 phase 不引入新跨项目代码契约,无需再次互引。前端 UI 集成(Phase 2 + 3)引入实质用户能力时再评估是否需要新一轮互引
关键约束:
- 插入位置必须在
<!-- 新的修改记录添加在此处下方,最新的在最前面 -->注释之后、### [2026-05-07] Phase 2 — 锁定后端通用凭据槽位 REST 接口契约(消费方文档化)标题之前(项目约定:最新在前) - 顶部
### [2026-05-08]必须用今天日期2026-05-08(与 RESEARCH 的 「Researched: 2026-05-08」一致;不是 2026-05-07) - 必须出现关键字符串:
CRED-FE-01、46d72b8、accessTokenMasked、accessToken、lib/api/credential-slot.ts、lib/api/index.ts、/v1/admin/credential-slot/ - 「服务端联动」字段必须明确写出「无 — ... commit
46d72b8已建立 ... 本 phase 不引入新跨项目代码契约,无需再次互引」(per CONTEXT.md 锁定文案) - 不要修改
docs/修改记录.md中任何已有条目;只做顶部插入 - 不要在 qy_lty 项目侧建立新条目(CONTEXT.md 锁定:本 phase 不需要新建跨项目互引)
<acceptance_criteria>
grep -nF "[2026-05-08] Phase 1(前端)凭据槽位 API 客户端" docs/修改记录.md命中 1 次- 该新条目的行号 < 现有
[2026-05-07] Phase 2 — 锁定后端通用凭据槽位 REST 接口契约标题的行号(最新在前顺序正确) grep -F "CRED-FE-01" docs/修改记录.md命中 ≥1 次grep -F "46d72b8" docs/修改记录.md命中 ≥1 次(plan 01 之前已存在 1 次,本 plan 后应为 ≥2 次)grep -F "accessTokenMasked" docs/修改记录.md命中 ≥1 次grep -F "lib/api/credential-slot.ts" docs/修改记录.md命中 ≥1 次grep -F "/v1/admin/credential-slot/" docs/修改记录.md命中 ≥1 次grep -F "无需再次互引" docs/修改记录.md命中 ≥1 次- 现有 [2026-05-07] Phase 2 条目内容完全不变(行级 diff 仅为顶部插入,不修改既有行) </acceptance_criteria>
46d72b8 / accessTokenMasked / 文件路径 / 服务端联动文案)齐全
Task 2:跑双重验证(npm run lint + npx tsc --noEmit)+ 临时探针验证 barrel 入口可解析
<read_first>
- package.json L9 — 确认 lint 脚本是 next lint(per RESEARCH 问题 7:只跑 ESLint,不跑 tsc)
- next.config.mjs(L17 / L20)— 确认 eslint.ignoreDuringBuilds 与 typescript.ignoreBuildErrors 仅影响 next build,不影响显式 next lint 与 npx tsc --noEmit
- tsconfig.json — 确认 strict 模式开启
- lib/api/credential-slot.ts(plan 01 落地)+ lib/api/index.ts(plan 01 落地)— 类型与导出已就位
- .planning/phases/01-credential-slot-api/01-RESEARCH.md 「Pitfall 5: 包管理器混用导致 lockfile 漂移」节 — 验证步骤只读不写,不要跑 npm install
</read_first>
(不创建持久化新文件;仅临时探针 lib/api/__phase1_probe__.ts,验证后删除)
步骤 1:创建临时类型探针文件 lib/api/__phase1_probe__.ts(用 .ts 而非 .tsx,因不引入 React;__ 前后缀降低被 IDE/lint 误识别为业务文件的风险)
写入以下完整内容:
// 临时探针 — Phase 1 plan 02 验证 barrel 入口可正确解析新增符号;验证后立即删除
import {
getCredentialSlot,
updateCredentialSlot,
type CredentialSlot,
type CredentialSlotUpdatePayload,
} from "@/lib/api"
async function __probe(): Promise<void> {
const slot: CredentialSlot = await getCredentialSlot()
const payload: CredentialSlotUpdatePayload = {
appId: slot.appId,
accessToken: "plaintext-not-masked", // 故意写明文,type 系统应允许
}
const next: CredentialSlot = await updateCredentialSlot(payload)
void next.accessTokenMasked // 触达字段证明类型形状
}
void __probe
步骤 2:跑 npx tsc --noEmit
npx tsc --noEmit
退出码必须为 0。如有错误:
- 若错误指向
__phase1_probe__.ts的import "@/lib/api"—— 说明 plan 01 的index.tsre-export 有问题,回 plan 01 排错 - 若错误指向
lib/api/credential-slot.ts—— 说明 plan 01 的类型定义有问题,回 plan 01 排错 - 若错误指向其他文件(项目中的存量类型问题,与本 phase 无关)—— 记录错误清单到 SUMMARY,但本 task 仍判定通过,因为本 phase 的责任范围是新增文件不引入类型回归
关键判定规则:把 npx tsc --noEmit 输出存到临时文件,过滤出仅与 lib/api/credential-slot.ts 或 __phase1_probe__.ts 或 lib/api/index.ts 相关的错误行;这三处错误数必须为 0。其他文件的存量错误不算 phase 1 失败。
步骤 3:跑 npm run lint
npm run lint
退出码必须为 0。如有警告/错误:
- 若错误/警告指向新增文件
lib/api/credential-slot.ts或__phase1_probe__.ts—— 必须修复 - 若错误/警告指向
lib/api/index.ts但仅限新增的具名 re-export 块 —— 必须修复 - 若错误/警告指向其他存量文件 —— 记录到 SUMMARY,本 task 仍判定通过
注意 next lint 默认对项目所有 .ts / .tsx 跑;如果 ESLint 配置严格,__phase1_probe__.ts 中的 void __probe 与未使用变量可能触发 no-unused-vars。如真触发,添加文件级 // eslint-disable-next-line @typescript-eslint/no-unused-vars 注释或将 __probe / __probe2 等命名调整避免触发,但优先调整代码而非禁用规则。
步骤 4:删除临时探针文件
rm lib/api/__phase1_probe__.ts
(Windows PowerShell 等价:Remove-Item lib/api/__phase1_probe__.ts)
步骤 5:再跑一次 npx tsc --noEmit 与 npm run lint,确认删除探针后两条命令仍全部退出码 0(防止漏删导致后续 phase 把临时文件当真)
关键约束(per RESEARCH Pitfall 5):
- 不要跑
npm install/pnpm install/yarn install(lockfile 漂移风险,本 phase 不引入新依赖) - 不要修改
package.json/package-lock.json/yarn.lock/pnpm-lock.yaml - 不要修改
next.config.mjs/tsconfig.json/.eslintrc*(CONTEXT.md / RESEARCH.md 均隐含锁定) - 探针文件必须删除,不允许残留任何临时文件到 phase 末态
- 两条验证命令的退出码与「与新增文件相关的错误数」都必须为 0;不可用
--force/--no-warnings等屏蔽手段
<acceptance_criteria>
- 步骤 2:
npx tsc --noEmit在创建探针后退出码 0;如有非 0,输出中没有任何包含lib/api/credential-slot.ts/lib/api/__phase1_probe__.ts/lib/api/index.ts路径的错误行(执行者负责把过滤判定写入 SUMMARY 证据段) - 步骤 3:
npm run lint退出码 0;同上规则,新增/修改的文件零错误零警告 - 步骤 4:
lib/api/__phase1_probe__.ts不存在(grep / Test-Path 验证) - 步骤 5:删除探针后
npx tsc --noEmit与npm run lint仍退出码 0 git status --short(如可用)显示只有lib/api/credential-slot.ts(新增)+lib/api/index.ts(修改)+docs/修改记录.md(修改)三个改动;不允许有__phase1_probe__.ts/pnpm-lock.yaml/yarn.lock/package-lock.json/package.json出现在 diff 中(探针残留或包管理器混用信号) </acceptance_criteria>
-
结构性(plan 01 + plan 02 联合):
lib/api/credential-slot.ts文件存在、4 个公共符号导出、路径与解包行齐全lib/api/index.ts末尾具名 re-export 4 个符号docs/修改记录.md顶部新增 [2026-05-08] Phase 1 条目
-
工具链(本 plan task 2 兜底):
npx tsc --noEmit退出码 0(新增/修改文件零类型错误)npm run lint退出码 0(新增/修改文件零 ESLint 错误)
-
可消费性(本 plan task 2 探针验证):
import { getCredentialSlot, type CredentialSlot } from '@/lib/api'在临时探针文件中类型解析通过- 探针文件删除后两条验证命令仍退出码 0(确认 plan 02 没引入残留文件依赖)
-
跨项目联动:
- 修改记录条目明确写出「无需再次互引(后端 commit
46d72b8已建立)」 - 不修改
qy_lty/docs/修改记录.md(CONTEXT.md 锁定)
- 修改记录条目明确写出「无需再次互引(后端 commit
-
包管理器零漂移:
git status不显示package.json/package-lock.json/yarn.lock/pnpm-lock.yaml的任何修改
<success_criteria>
docs/修改记录.md顶部第一条为[2026-05-08] Phase 1(前端)凭据槽位 API 客户端- 该条目包含全部锁定关键字:
CRED-FE-01、46d72b8、accessTokenMasked、accessToken、lib/api/credential-slot.ts、lib/api/index.ts、/v1/admin/credential-slot/、无需再次互引 - 现有 [2026-05-07] Phase 2 条目内容不变、位置下移
npx tsc --noEmit退出码 0;新增/修改文件零类型错误(存量错误不影响本 phase 判定)npm run lint退出码 0;新增/修改文件零 ESLint 错误- 临时探针
lib/api/__phase1_probe__.ts已删除,git diff 不残留 git status --short仅显示lib/api/credential-slot.ts(新增) +lib/api/index.ts(修改) +docs/修改记录.md(修改)+.planning/...内的 PLAN/SUMMARY 文档;不显示package.json/ 任一 lockfile 改动 </success_criteria>
完成本 SUMMARY 即可宣告 Phase 1 全部交付完成;下一步运行 /gsd-plan-phase 2 启动 RBAC 收敛 + AI 模型页入口。