docs(GOV-010): 记录开发需求与完成结果

This commit is contained in:
2026-08-13 23:35:50 +08:00
parent e992edccce
commit 61f85e5fa4
6 changed files with 153 additions and 41 deletions
@@ -73,6 +73,8 @@
### Task 1: 治理档案与证据校验
**实施状态:已完成。** 对应提交 `e12c572`,治理测试 9 项通过并已推送 Gitea。
**Files:**
- Modify: `tools/governance/feature-record.test.mjs`
@@ -88,7 +90,7 @@
- Produces: `buildImpactPlanTemplate(featureId: string): string`,生成包含影响范围、风险和同步修改清单的 Markdown 骨架。
- Completion behavior: `finish.mjs` 在文件存在校验后调用证据校验,并一次列出全部无效章节。
- [ ] **Step 1: 先对现有治理符号执行 GitNexus 影响分析**
- [x] **Step 1: 先对现有治理符号执行 GitNexus 影响分析**
Run:
@@ -99,7 +101,7 @@ gitnexus_impact(target="getUnpassedReviewFiles", direction="upstream", includeTe
Expected: LOW 或 MEDIUM;直接同步范围至少包含 `feature-record.test.mjs` 和 `finish.mjs`。若结果为 `partial`,记录限制并继续使用静态引用交叉核对。
- [ ] **Step 2: 写治理规则失败测试**
- [x] **Step 2: 写治理规则失败测试**
在 `feature-record.test.mjs` 中加入以下结构化样例。完整有效档案必须包含:
@@ -148,7 +150,7 @@ assert.deepEqual(getInvalidFeatureEvidence(validReports), []);
再逐一删除章节、提供空正文、提供裸 `无`、裸 `不适用`、`N/A`,断言返回对应的 `文件:章节`。提供 `不适用:本功能不进入生产请求路径,边界仅为开发门禁。`,断言可以通过。
- [ ] **Step 3: 运行测试确认按预期失败**
- [x] **Step 3: 运行测试确认按预期失败**
Run:
@@ -158,7 +160,7 @@ npm run test:governance
Expected: FAIL,原因是 `development-summary.md` 尚未在清单中,且 `getInvalidFeatureEvidence`、`buildImpactPlanTemplate` 尚未导出。
- [ ] **Step 4: 实现最小 Markdown 章节校验**
- [x] **Step 4: 实现最小 Markdown 章节校验**
在 `feature-record.mjs` 中保持单文件职责,加入固定规则:
@@ -186,7 +188,7 @@ const REQUIRED_EVIDENCE_SECTIONS = Object.freeze({
章节解析允许标题前带数字序号,例如 `## 8. 安全策略与评估` 与 `## 安全策略与评估` 视为同一标题;正文截止下一个二级标题。有效正文至少包含一个非标题、非注释、非空白的说明行;若规范化后仅为 `无`、`不适用`、`N/A` 或 `none` 则无效。不要解析业务结论真伪,也不要依赖包含“安全”或“性能”的任意散文。
- [ ] **Step 5: 让开始门禁生成影响计划骨架**
- [x] **Step 5: 让开始门禁生成影响计划骨架**
导出并测试:
@@ -210,7 +212,7 @@ export function buildImpactPlanTemplate(featureId) {
`start.mjs` 在创建 `before.md` 的同一目录创建 `impact-plan.md`;若任一目标文件已存在则在写入前失败,禁止覆盖历史。GOV-010 已有人工影响计划,因此只影响后续功能。
- [ ] **Step 6: 接入完成门禁**
- [x] **Step 6: 接入完成门禁**
`finish.mjs` 读取全部必备文件形成 `Map`,先报告缺失文件,再调用:
@@ -223,7 +225,7 @@ if (invalidEvidence.length > 0) {
已发布 GOV-001 至 GOV-008 不批量修改;它们是不可变历史,也不再重新执行新的完成门禁。仍为 `unreleased` 的 GOV-009、FEAT-MO-001 以及后续档案,在将来完成时必须满足新规则。
- [ ] **Step 7: 运行治理测试**
- [x] **Step 7: 运行治理测试**
Run:
@@ -233,7 +235,7 @@ npm run test:governance
Expected: PASS,覆盖必备清单、有效章节、空章节、裸占位词、带理由不适用和影响计划骨架。
- [ ] **Step 8: 检测变化并提交推送**
- [x] **Step 8: 检测变化并提交推送**
Run GitNexus `detect_changes(scope="all")`,确认只影响治理完成路径。然后:
@@ -249,6 +251,8 @@ Expected: 本地 HEAD 与 `refs/heads/main` 远程 SHA 一致。
### Task 2: 规范、模板与架构事实
**实施状态:已完成。** 对应提交 `3a22fde`,格式、治理和环境相关验证通过并已推送 Gitea。
**Files:**
- Create: `docs/templates/development-summary-template.md`
@@ -270,11 +274,11 @@ Expected: 本地 HEAD 与 `refs/heads/main` 远程 SHA 一致。
- Produces: 后续功能可直接复制的开发总结、安全、性能、GitNexus 和 Review 模板。
- Produces: 前端 Axios/OpenAPI 分工与后端业务模块内按需分层的正式架构事实。
- [ ] **Step 1: 对入口规范和架构文档执行影响检查**
- [x] **Step 1: 对入口规范和架构文档执行影响检查**
Run GitNexus 对 `AGENTS.md`、`code-development-standards.md`、`development-workflow.md` 和 `system-architecture.md` 文件执行 upstream impact。Expected: 文档变化不影响生产执行流;若工具只能返回文件级 LOW/partial,记录限制。
- [ ] **Step 2: 建立与门禁完全一致的模板**
- [x] **Step 2: 建立与门禁完全一致的模板**
`development-summary-template.md` 必须包含 Task 1 的七个二级标题,并在每节说明应记录的事实。PRD 模板新增:
@@ -290,7 +294,7 @@ Run GitNexus 对 `AGENTS.md`、`code-development-standards.md`、`development-wo
代码 Review 模板新增 `安全与残余风险`、`性能与资源影响`、`GitNexus 与同步修改`;规范 Review 模板新增 `安全、性能与架构检查`、`GitNexus 与开发总结检查`。标题必须与 Task 1 校验规则一致。
- [ ] **Step 3: 更新代码开发规范**
- [x] **Step 3: 更新代码开发规范**
明确写入:
@@ -301,7 +305,7 @@ Run GitNexus 对 `AGENTS.md`、`code-development-standards.md`、`development-wo
- 前端 `utils/request.ts` 独占 Axios;业务接口位于 `api/<业务域>/index.ts`;页面、组件、Store、Composable 禁止直接 HTTP;生成 OpenAPI 类型继续作为契约来源。
- 新依赖安装前记录用途、替代、安全、许可证、体积/成本、维护和退出方案。
- [ ] **Step 4: 更新流程与追溯规范**
- [x] **Step 4: 更新流程与追溯规范**
开发前流程要求 GitNexus 同时回答影响其他功能/模块和是否需要同步修改;缺陷修复不例外。开发后流程要求先填写开发总结,再做两类 Review。追溯树加入:
@@ -311,11 +315,11 @@ Run GitNexus 对 `AGENTS.md`、`code-development-standards.md`、`development-wo
并明确 PRD、开发总结、release notes 三者分别记录目标、实际完成和面向版本使用者的变化。
- [ ] **Step 5: 更新系统架构与代理入口**
- [x] **Step 5: 更新系统架构与代理入口**
`system-architecture.md` 增加 Axios/OpenAPI 数据流和业务模块内分层;修正当前仓库结构中不存在的顶层 `contracts/` 表述,使用实际的 `server/openapi`、`server/libs/http-contracts` 和 `server/libs/message-contracts`。`AGENTS.md` 增加强制安全/性能、GitNexus 同步修改、独立开发总结、前后端架构边界。`CHANGELOG.md` 的 Unreleased 增加 GOV-010 条目。
- [ ] **Step 6: 校验标题与格式**
- [x] **Step 6: 校验标题与格式**
Run:
@@ -327,7 +331,7 @@ npm run test:governance
Expected: 所有门禁标题均出现在对应模板或 GOV-010 档案中,格式与治理测试通过。
- [ ] **Step 7: 检测变化并提交推送**
- [x] **Step 7: 检测变化并提交推送**
Run GitNexus `detect_changes(scope="all")`,然后:
@@ -341,6 +345,8 @@ git push origin main
### Task 3: Axios 请求封装与路径别名
**实施状态:已完成。** 对应提交 `4105336`,请求、配置、类型、lint 和格式验证通过并已推送 Gitea。
**Files:**
- Create: `web/src/utils/request.test.ts`
@@ -364,7 +370,7 @@ git push origin main
- Produces: 默认导出 `request`,其 base URL 为 `import.meta.env.VITE_API_BASE_URL || ''`,默认超时 `10_000` 毫秒。
- Produces: `@/*` 同时在 TypeScript、Vite 和 Vitest 解析为 `web/src/*`。
- [ ] **Step 1: 对旧请求符号和 Vite 配置执行影响分析**
- [x] **Step 1: 对旧请求符号和 Vite 配置执行影响分析**
Run:
@@ -376,7 +382,7 @@ gitnexus_impact(target="readDevelopmentPublicEnv", direction="upstream", include
Expected: 旧请求符号风险 LOW/partial,直接引用仅旧测试;Vite 配置影响开发服务器和配置测试,保持现有 `/api` 代理。
- [ ] **Step 2: 记录依赖评估和构建基线**
- [x] **Step 2: 记录依赖评估和构建基线**
在后续 `qa/test-results.md` 预留并最终记录:Axios 1.19.0、MIT、官方仓库、替代项 `fetch/openapi-fetch`、选择原因、退出方式。当前构建基线记录为 JS `163908` 字节、CSS `805` 字节;最终构建使用实际产物重新测量。依赖元数据查询若使用 npm,指定任务临时缓存,避免本机 `~/.npm` 的既有权限问题:
@@ -384,7 +390,7 @@ Expected: 旧请求符号风险 LOW/partial,直接引用仅旧测试;Vite
npm_config_cache=/tmp/a-share-analysis-gov010-npm-cache pnpm view axios version license repository.url --json
```
- [ ] **Step 3: 安装 Axios 并移除旧请求库**
- [x] **Step 3: 安装 Axios 并移除旧请求库**
Run:
@@ -395,7 +401,7 @@ pnpm --filter @a-share-analysis/web add axios@1.19.0
Expected: `web/package.json` 只保留 Axios 作为浏览器 HTTP 请求库,锁文件不再含 `openapi-fetch`。
- [ ] **Step 4: 写 Axios 封装失败测试**
- [x] **Step 4: 写 Axios 封装失败测试**
使用自定义 `AxiosAdapter` 返回确定响应,覆盖:
@@ -419,7 +425,7 @@ await expect(
另外让 adapter 抛出包含 `mysql://root:secret@internal` 的 `AxiosError`,断言最终错误只含 `API 请求失败,请稍后重试`、`kind` 和非敏感 `status`。使用已取消的 `AbortController.signal` 断言取消错误保持 `axios.isCancel(error) === true`。
- [ ] **Step 5: 运行 Web 测试确认失败**
- [x] **Step 5: 运行 Web 测试确认失败**
Run:
@@ -429,7 +435,7 @@ pnpm --filter @a-share-analysis/web test -- src/utils/request.test.ts
Expected: FAIL,原因是 `web/src/utils/request.ts` 尚不存在。
- [ ] **Step 6: 实现类型化 request 包装器**
- [x] **Step 6: 实现类型化 request 包装器**
核心行为:
@@ -461,14 +467,14 @@ export function createRequestClient({
请求拦截器保留为后续认证扩展点,但不提前实现 Token 刷新。`toApiRequestError` 不保存原始错误消息、URL、请求头或响应正文。HTTP 状态只允许保存数字状态码。
- [ ] **Step 7: 增加 `@` 别名并保留现有代理**
- [x] **Step 7: 增加 `@` 别名并保留现有代理**
- `web/tsconfig.json`: `baseUrl: "."`,`paths: { "@/*": ["src/*"] }`。
- `web/vite.config.ts`: `resolve.alias['@'] = path.resolve(webDirectory, 'src')`。
- `web/vitest.config.ts`: 使用 `fileURLToPath(new URL('./src', import.meta.url))` 配置同一别名。
- `vite-config.test.ts`: 同时断言 `resolve.alias` 和原有 `/api` 代理,禁止迁移时破坏同源策略。
- [ ] **Step 8: 删除旧客户端并运行局部验证**
- [x] **Step 8: 删除旧客户端并运行局部验证**
Run:
@@ -480,7 +486,7 @@ pnpm --filter @a-share-analysis/web typecheck
Expected: `rg` 无匹配;请求与 Vite 测试、类型检查通过。
- [ ] **Step 9: 检测变化并提交推送**
- [x] **Step 9: 检测变化并提交推送**
Run GitNexus `detect_changes(scope="all")`,确认只影响 Web 请求基础设施与配置。然后:
@@ -494,6 +500,8 @@ git push origin main
### Task 4: 健康 API 分域与 HTTP 架构边界
**实施状态:已完成。** 对应提交 `d2c1863`,边界测试 16 项、Web 测试 11 项及契约验证通过并已推送 Gitea。
**Files:**
- Create: `web/src/api/health/index.test.ts`
@@ -509,7 +517,7 @@ git push origin main
- Boundary: 只有 `web/src/utils/request.ts` 可以导入 `axios` 或创建 Axios 实例;`web/src` 的其他运行时代码禁止调用全局 `fetch`。
- Boundary: `/api/...` 业务路径字符串只能出现在 `web/src/api/` 或 `web/src/utils/request.ts`;测试和自动生成文件按各自 fixture 验证,不放宽生产源码。
- [ ] **Step 1: 对边界校验符号执行影响分析**
- [x] **Step 1: 对边界校验符号执行影响分析**
Run:
@@ -520,7 +528,7 @@ gitnexus_impact(target="verifyProjectBoundaries", direction="upstream", includeT
Expected: LOW;只影响项目验证和其测试,不进入线上执行流。
- [ ] **Step 2: 写健康 API 失败测试**
- [x] **Step 2: 写健康 API 失败测试**
使用 Vitest mock `@/utils/request`:
@@ -538,7 +546,7 @@ expect(request).toHaveBeenCalledWith({
让 mock 返回完整 `HealthResponseDto`,并通过类型断言证明 `getHealth` 返回 DTO 而不是 `AxiosResponse`。
- [ ] **Step 3: 写边界失败测试**
- [x] **Step 3: 写边界失败测试**
fixture 覆盖以下违规:
@@ -550,7 +558,7 @@ fixture 覆盖以下违规:
合法 fixture 包含 `utils/request.ts` 导入 Axios、`api/health/index.ts` 导入统一 request、页面只导入 `getHealth`。继续保留 Web 禁止导入 Server 和内部消息契约测试。
- [ ] **Step 4: 运行测试确认失败**
- [x] **Step 4: 运行测试确认失败**
Run:
@@ -561,7 +569,7 @@ npm run test:boundaries
Expected: 健康 API 测试因文件不存在失败;边界违规 fixture 因当前校验未识别 Axios/fetch 而失败。
- [ ] **Step 5: 实现健康业务域 API**
- [x] **Step 5: 实现健康业务域 API**
```ts
import type { components } from '@/api/generated/schema';
@@ -581,7 +589,7 @@ export function getHealth(signal?: AbortSignal): Promise<HealthResponseDto> {
保留现有 `api/adapters/health.adapter.ts`;它负责 DTO 到 ViewModel,不移动到全局工具目录,也不接入当前页面。
- [ ] **Step 6: 实现 AST 边界校验**
- [x] **Step 6: 实现 AST 边界校验**
在现有 TypeScript AST 遍历中收集:
@@ -594,7 +602,7 @@ export function getHealth(signal?: AbortSignal): Promise<HealthResponseDto> {
按 `path.relative(webSourceRoot, sourcePath)` 判断允许位置,错误格式必须包含源码路径和违规种类。不要扫描注释或普通展示文本;业务 URL 只检查 CallExpression 参数中的字符串字面量。
- [ ] **Step 7: 运行局部与契约验证**
- [x] **Step 7: 运行局部与契约验证**
Run:
@@ -607,7 +615,7 @@ pnpm typecheck
Expected: 全部 PASS;OpenAPI 输出无业务字段变化,Web 仍不依赖 Server 源码。
- [ ] **Step 8: 检测变化并提交推送**
- [x] **Step 8: 检测变化并提交推送**
Run GitNexus `detect_changes(scope="all")`,然后:
@@ -621,6 +629,8 @@ git push origin main
### Task 5: GOV-010 档案、依赖评估与开发总结
**实施状态:进行中。** 开发总结、发布说明、依赖评估和档案状态已补齐;安全审计发现并通过 `e992edc` 修复 Swagger 的 `js-yaml` 传递依赖漏洞,等待本阶段档案提交。
**Files:**
- Create: `docs/features/GOV-010-development-quality-architecture/development-summary.md`
@@ -635,13 +645,13 @@ git push origin main
- Consumes: Task 1 的固定开发总结章节和 Task 2 模板。
- Produces: 与实际代码、依赖版本、范围变化和测试结果一致的功能档案。
- [ ] **Step 1: 对照 Git diff 更新实际完成事实**
- [x] **Step 1: 对照 Git diff 更新实际完成事实**
`development-summary.md` 必须逐条列出 FR-001 至 FR-010 的实际状态;原始需求和需求变化分别记录。明确写出:当前页面仍未接入健康 API、AI Provider 未实现、后端现有健康模块没有为目录外观迁移。
同时把已批准档案的章节标题规范化为 Task 1 的门禁标题:设计使用 `安全策略与评估`、`性能目标与评估`,测试计划使用 `安全验证`、`性能验证`,GitNexus 影响计划使用 `直接与间接影响`、`跨模块同步修改`。只调整标题和组织,不改变用户已经批准的结论。
- [ ] **Step 2: 完成安全与依赖评估**
- [x] **Step 2: 完成安全与依赖评估**
在设计和总结中记录 Axios 1.19.0、MIT、官方来源、锁文件、替代方案、前端体积增量、维护状态和可回退到原生 fetch 的退出方式。运行:
@@ -657,7 +667,7 @@ git status --short
构建后记录实际 JS/CSS 文件字节数,与 Task 3 基线 `163908/805` 比较;确认 request 没有默认重试,默认超时为 10 秒。治理校验只在开发/发布路径运行,不做生产负载测试,并在“不适用”结论中写清边界。
- [ ] **Step 4: 更新清单与发布说明**
- [x] **Step 4: 更新清单与发布说明**
`manifest.yaml` 状态改为 `verifying`,保留 `release: unreleased`。`release-notes.md` 说明治理门禁、架构规范和 Axios 迁移,不宣称市场概览、AI 或用户功能已完成。