Skip to content

Commit 84636f6

Browse files
committed
docs(versions): 0-C1 行数红线验收与门槛更正
1 parent 038a52b commit 84636f6

2 files changed

Lines changed: 21 additions & 5 deletions

File tree

‎docs/standards/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
|------|------|:---:|:---:|
99
| [git-workflow.md](./git-workflow.md) | Git 分支/提交规范(Conventional Commits) | ✅ 必用 | ✅ 必用 |
1010
| [ai-coding.md](./ai-coding.md) | AI 协作方式 + 代码生成七维度硬性标准 | ✅ 必用 | ✅ 必用 |
11-
| [line-limit-exemptions.md](./line-limit-exemptions.md) | 行数豁免登记(>300 行文件清单,配合 ai-coding) | ✅ | ✅ |
11+
| [line-limit-exemptions.md](./line-limit-exemptions.md) | 行数豁免登记(**生成物**,>300 行文件清单;口径与守卫见 `scripts/line-limits.mjs`) | ✅ | ✅ |
1212
| [documentation.md](./documentation.md) | 文档编写规范(含归档机制) | ✅ 必用 | ✅ 必用 |
1313
| [testing.md](./testing.md) | 测试策略与规范 | ✅ 必用 | ✅ 必用 |
1414
| [code-review.md](./code-review.md) | 代码审查流程 | ⬜ 可选 | ✅ |

‎docs/versions/v0.22.md‎

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,9 @@
5656
5757
## 验收门槛(11 条,全文见规格 §11)
5858

59-
1. 4 个 >600 行文件 → **0**;>300 行 100% 在豁免表内且数值与实测一致
60-
> ⚠️ **本门槛按现计划不可能达成(2026-09-11 实测复核,非本系列产出)**:`docs/tech-debt/review-2026-09-11.md` 独立实测的真实缺口是 **>600 硬限 15 个**(Rust 10 / 前端 5 —— 规格所列「4 个」只扫了前端,且漏掉 `SessionListPanel.tsx` 604)、**301–600 行 46 个从未登记**、豁免表 **12 组重复 + 1 条幽灵条目(`ActionCenterOverlay.tsx` 已不存在)+ 77 条数值偏差 ≥15 行**。已登记 **TD-2026-09-11-H**。
61-
> ⇒ **需裁决**:是(a)把门槛从「4 个」改为实测的「15 个」并相应扩大批 0 范围,还是(b)明确写出「4 个主要文件 + 其余登记」并说明理由。**控制方未擅自改门槛**(属用户决策),仅在此标注事实。
62-
> 另:测量口径**已裁决**(2026-09-11,见 AGENTS.md §3.1)—— 以 `[System.IO.File]::ReadAllLines(path, UTF8).Count` 为**唯一**判据;禁用 `Measure-Object -Line`(只数非空行,既有豁免登记值出自它)、`Get-Content`(PS 5.1 下按 GBK 解码 UTF-8,**少算可达 56 行**)与字节 `0x0A` 计数(末尾无换行时少算 1)。详见下方「本机工具链的读数陷阱」。
59+
1. **15 个 >600 行文件 → 0**(实测值:前端 5 + Rust 10;规格原文的「4 个」只扫了前端且漏掉 `SessionListPanel.tsx`);>300 行 **100% 在豁免表内且数值与实测一致**。
60+
> **2026-09-11 用户裁决**:范围取实测 15 个;口径取「全部行数」,**以 `[System.IO.File]::ReadAllLines(path, UTF8).Count` 为准**(即 `scripts/line-limits.mjs`),**禁用 `Get-Content`(少算可达 56 行)· `Measure-Object -Line`(只数非空行)· 字节 `0x0A` 计数(末尾无换行时少算 1)**。
61+
> 执行机制:`node scripts/line-limits.mjs`(本地提交门禁 + CI `--full` 守数值),>600 用**棘轮**只减不增 —— 拆分由 0-C2(前端 5)/ 0-C3(Rust 10)推进,每拆完一个从 `FROZEN_OVER_LIMIT` 删一行。
6362
2. 手写弹层 20 → 全走 `Modal`;z-index 不同值 17 → **≤6 档**;`role="dialog"` + 焦点陷阱 **20/20**
6463
3. 空态 / 加载 / 错误行 / 弱化文本 / 卡片边框 五类重复 → 各自 **1 个原语**
6564
4. CSS 变量 0 → 覆盖全部语义色/字阶/间距/圆角/时长/缓动;hex 88 → **≤ token 数**
@@ -112,6 +111,8 @@
112111
**陷阱 1 · 行数 —— `Get-Content` 会少算**
113112

114113
本机 harness 的 `pwsh` 实为 **Windows PowerShell 5.1**(ANSI 码页 `gb2312`),`Get-Content` 会按 GBK 解码 UTF-8 文件并**吞掉换行、把行数少算**(实测:`index.ts` 19→12、`paths.test.ts` 130→112、`NoteListView.tsx` 654→609;**全量 868 文件实测最大少算 56 行**:`live_session_pause.rs` 353→297 —— **足以把越 300 红线的文件读成达标**)。
114+
115+
**文档域可远超此量级(2026-09-11 批 0-C1 补测)**:本批台账(`.superpowers/sdd/2026-09-11-frontend-redesign-batch0c1-line-limits/progress.md`,该目录不进 git)实测 **真实 385 行 / `Get-Content` 报 247 行 —— 少算 138 行(36%)**,因为少算幅度随**中文密度**放大;Task 5 复测同一文件(已增至真实 494 行)时 `Get-Content` 报 356 行,**两次差值同为 138 行** ⇒ 该偏差**不随文件增长而收敛**。⇒ 「禁用 `Get-Content` 数行」**不是只对源码域成立**。
115116
⇒ **AGENTS.md §3 的「≤300 / >600」以 `[System.IO.File]::ReadAllLines(path, UTF8).Count` 为唯一口径**(即 `node scripts/line-limits.mjs`);禁用 `Get-Content`、`Measure-Object -Line`(只数非空行)与**字节 `0x0A` 计数**(对末尾无换行的文件会少算 1,本仓实测 8 个这样的源文件)。该失真已造成一次真实险情(据此误判 `IconName` 未导出)。
116117
治理侧(口径未定义、15 个 >600 硬限违规、豁免表数值过期)见 `docs/tech-debt/review-2026-09-11.md`;工具侧见批 0-B 台账。
117118
> ⚠️ 上句**故意不写成 Markdown 链接**:该文件目前**未入 git**(`docs/tech-debt/` 整个目录 0 tracked)。写成链接会让**新克隆断链**、并让 `docs-check` 在别人机器上变红 —— 而在本机因文件存在而通过(这类"本地绿、别处红"的掩盖正是本批要消灭的缺陷类)。该文件入库后可改回链接。
@@ -131,6 +132,21 @@
131132
> 注意一项**装载敏感的偶发失败**:`ffmpeg::tests::run_captured_handles_large_output` 内含 10s 墙钟超时,同时跑 `cargo build` + `vitest` 时被拖超时失败,单独重跑 8.55s 通过 ⇒ 判定门禁时须串行执行(或单独复跑该用例再下结论)。
132133
⇒ 治本方向(未执行,留给依赖治理):把 `ort/` 下的 DLL 与其 import lib 对齐到同一版本,并消除 system32 的同名抢占。本次 DeepSeek 修复的验证全程走 `--test app_lib_tests`,不受该问题影响。
133134

135+
**工具链真相 1 · 本地提交门禁此前从未武装(2026-09-11,批 0-C1 Task 4 发现,已修正)**
136+
137+
本克隆此前**从未安装 husky** —— `core.hooksPath` **为空**、无 `.git/hooks/pre-commit`、无 `node_modules` ⇒ `.husky/pre-commit`(lint-staged)与 `.husky/commit-msg`(commitlint)在本机**对所有提交都是静默失效的**:不只是某个批次,而是**历史上每一次提交**,**包括批 0-A / 0-B / 0-C1 的全部交付提交**(旁证:控制方在本会话提交 40+ 次,从未见过任何 lint-staged / commitlint 输出)。⇒ **新克隆若未 `npm install`,门禁默认失效且无任何提示**(不报错、不警告,提交照常成功)。
138+
现状:**已武装**(`npm install` + `npm run prepare`)—— `node_modules/` 与 `.git/config` 的 `core.hooksPath=.husky/_` 两项环境变更**都不进 git**;此后提交会**真被 lint-staged + commitlint 拦**(已取得实测拦截证据:`(c) 超过 300 行但未登记:app/src/__probe-lines.ts(320 行)`、`husky - pre-commit script failed`、HEAD 未动)。
139+
同一轮还补了**门禁自身的覆盖**:lint-staged 增加 `{package.json,scripts/line-limits.mjs,docs/standards/line-limit-exemptions.md}` → `node scripts/line-limits.mjs --full` 条目 —— 否则「改工具 / 改登记表」在本地没有任何自动拦截(也因此,改 `package.json` 会一并触发这条 `--full` 校验)。
140+
141+
**工具链真相 2 · 门禁的失败路径曾是破坏性的(lint-staged@15.5.0,2026-09-11 实测并加固)**
142+
143+
`lint-staged@15.5.0` 默认 `stash:true` + `hidePartiallyStaged:true`,其**失败路径**是「先毁工作树,再赌一次还原」:`git stash create` + `stash store` 备份 → 跑任务 → **失败则 `git reset --hard HEAD`**(清掉整个工作树)→ `git stash apply --quiet --index <备份>` 重建 → `cleanup` 把备份 `stash drop`(实现见 `node_modules/lint-staged/lib/gitWorkflow.js` 与 `runAll.js`)。
144+
⇒ **实测曾使未暂存改动当场消失**:暂存一个故意越线的探针文件、同时在 `docs/standards/README.md` 留一处**纯未暂存**改动,提交 `[FAILED]` 后那处改动**从工作树消失**,且 `git stash list` **为空**(只剩悬空 commit `c85e00a1`);`git diff HEAD c85e00a1` 证明备份里**确实含**该改动 ⇒ **还原那一半没兑现**。复跑同一实验时内容侥幸还在,但**整个文件被重写**(LF→CRLF、sha256 变化)—— 「内容还在」是那次 `apply` 恰好成功,**不是设计保证**。
145+
⇒ **加固**:`.husky/pre-commit` 改为 `npx lint-staged --no-stash --no-hide-partially-staged`(上游 `--no-stash` 本就 **imply 关掉 hide**;第二个 flag 仍写死,防将来 imply 变化后悄悄退回「藏了未暂存部分却没有备份可还原」—— 那条路失败时必丢)。加固后 lint-staged 在**任何路径**都不碰工作树与索引(不 `stash create`、不 `reset --hard`、不 `checkout --force`、不 `stash drop`),而拦截力不变(实测 `[FAILED]` + `exit=1`、`husky - pre-commit script failed (code 1)`、HEAD 未动、未暂存改动 **sha256 前后相同**)。
146+
**代价(须知)**:① 门禁看到的是**工作树态**,不再是「隐去未暂存部分的索引态」—— 本仓两个检查都是**全树只读扫描**,看工作树反而口径单一,故可接受;② 落在受管 glob 上的**部分暂存文件会在跑完时被整文件 `git add`** ⇒ **不丢内容,但抹掉「只提交一半」的意图**(提交前看 `git status`,`MM` 会变成 `M `);③ 部分暂存时会残留 `.git/lint-staged_unstaged.patch`(没有步骤再删它)。
147+
**补救(失败后怀疑丢了改动)**:备份是一个 `WIP on <分支>: <HEAD>` 的**悬空 commit** —— `git stash list` 为空**不代表**它不存在:`git fsck --dangling` 列出悬空 commit → `git diff --name-status HEAD <备份ID>` 先确认确实含你的改动 → `git stash apply --index <备份ID>` 整份还原(索引 + 工作树),或 `git checkout <备份ID> -- <path>` 只取回单个文件。
148+
⚠️ **因此切勿运行 `git gc --prune=now`**:这些悬空 commit 是万一丢失改动时的**唯一找回途径**(控制方那次丢失的改动,就是从 `c85e00a1` 找回来的)。
149+
134150
## 边界(红线延续,全文见规格 §3)
135151

136152
- 不写「自动替你决定」的能力;AI 一律默认关、可降级、须授权

0 commit comments

Comments
 (0)