docs(iteration): 选题规则增加域轮换与视觉欠账优先

- backlog 条目新增可选字段 domain(new/tune/visual/tooling),存量 225 条
  按标题关键词回填(new 53 / tooling 38 / tune 134)
- 每轮选题改为先取 open 且 domain=visual 的条目,无视觉欠账再按数组顺序
- 新增《域轮换与视觉欠账优先》三条:连续 3 轮至少 1 轮 visual、视觉欠账
  优先于新增组件、新增组件必须声明只消费 --ua-* 令牌
- AGENTS 落点清单第 4 条补禁止新增硬编码阴影/时长/字号;门禁链描述补
  lint-iterations 与 audit:visual
- 灌入 8 条 domain=visual 欠账(g179…g186),验收标准均可枚举或可机检
This commit is contained in:
HIsheR
2026-10-26 16:49:49 +08:00
parent ee6d84457a
commit d048717e76
4 changed files with 536 additions and 231 deletions
+522 -225
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -7,7 +7,7 @@
1. **包管理器必须用 pnpm**:包间依赖用 `workspace:*` 协议,npm 不支持。安装依赖:`pnpm install`。 1. **包管理器必须用 pnpm**:包间依赖用 `workspace:*` 协议,npm 不支持。安装依赖:`pnpm install`。
2. **构建工具**:TypeScript 5(`tsc`)。若环境未全局安装,可使用托管工作区的副本:`C:/Users/shawn/.workbuddy/binaries/node/workspace/node_modules/typescript`(本仓库历史即如此构建)。 2. **构建工具**:TypeScript 5(`tsc`)。若环境未全局安装,可使用托管工作区的副本:`C:/Users/shawn/.workbuddy/binaries/node/workspace/node_modules/typescript`(本仓库历史即如此构建)。
3. **Node**:>= 18,ESM(`"type": "module"`)。 3. **Node**:>= 18,ESM(`"type": "module"`)。
4. **验证自检**:装好后先跑 `npm run check`(build → demo → style → typecheck → smoke → index → verify)确认基线全绿,再开始改代码。 4. **验证自检**:装好后先跑 `npm run check`(build → demo → style → typecheck → smoke → index → verify → lint-iterations → audit:visual)确认基线全绿,再开始改代码。
## 编码规范(强制) ## 编码规范(强制)
@@ -27,7 +27,7 @@
- `apps/demo`(@ui-arch/demo):交互演示,产物 apps/demo/dist/demo.html - `apps/demo`(@ui-arch/demo):交互演示,产物 apps/demo/dist/demo.html
- `apps/docs`:文档站,纯产物(ua docs 生成) - `apps/docs`:文档站,纯产物(ua docs 生成)
**门禁一条龙**:`npm run check` = build + demo + style + typecheck + smoke + index + verify,提交前必过。`ua verify` 校验清单 ↔ 文档 ↔ 演示一致(docs.components 的 id 必须在 api.exports 有对应条目、props 必须带 n/t/d、每个文档字段名必须在组件实现源码里真实出现(改名后忘改文档会直接报错)、反向也校验 `src/types.ts` 里 `<组件>Props`(可用清单的 `propsType` 覆盖接口名,`false` 表示无入参)每个字段都在文档 props 表登记(新加字段忘了写文档会报错)、demo 锚点必须在 `apps/demo/main.ts` 中存在,且该组件必须被 demo 真实调用 `id(` / `id.`),检查皮肤包样式表无硬编码颜色(`#hex` 一律禁止,必须走 `--ua-*` 令牌)与令牌引用有效(`var(--ua-*)` 必须是 tokens.css 已定义或组件自设的变量)、核对每个 `--ua-color-*` 都在 `[data-theme='dark']` 里有覆盖值且暗色块没有凭空多出的变量名(新增颜色令牌漏写暗色值直接报错),核对 README 的 `<!-- ua:components -->` 区块与「分组:」行都覆盖清单组件集合(漏写/多写/重复都报错),并交叉校验 backlog 的 done 条目与 `.ua/iterations.log` 的 done 留痕一一对应(另外查 backlog id 不重复、g 编号严格递增、同一 id 只有一条 done 留痕,且留痕 ts 带 +08:00、时间线不回退、不落在未来——都是过去手工插条目/手写时间戳踩过的坑);配方还要求编号连续、每条都有代码块与要点,且代码块里至少认出一个已注册组件 id(拼错组件名时 `ua recipes` 会把它列成空组件表)。 **门禁一条龙**:`npm run check` = build + demo + style + typecheck + smoke + index + verify + lint-iterations + audit:visual,提交前必过。`ua audit:visual` 统计皮肤包里五类硬编码视觉字面量(字号 / 动效时长 / 阴影 / 圆角 / 焦点环)并与 `.ua/visual-baseline.json` 做棘轮:任一类超过基线即退出码 1 并指出疑似引入的提交;迁移脚本 `npm run visual:migrate` 可把字面量幂等改写成令牌。`ua verify` 校验清单 ↔ 文档 ↔ 演示一致(docs.components 的 id 必须在 api.exports 有对应条目、props 必须带 n/t/d、每个文档字段名必须在组件实现源码里真实出现(改名后忘改文档会直接报错)、反向也校验 `src/types.ts` 里 `<组件>Props`(可用清单的 `propsType` 覆盖接口名,`false` 表示无入参)每个字段都在文档 props 表登记(新加字段忘了写文档会报错)、demo 锚点必须在 `apps/demo/main.ts` 中存在,且该组件必须被 demo 真实调用 `id(` / `id.`),检查皮肤包样式表无硬编码颜色(`#hex` 一律禁止,必须走 `--ua-*` 令牌)与令牌引用有效(`var(--ua-*)` 必须是 tokens.css 已定义或组件自设的变量)、核对每个 `--ua-color-*` 都在 `[data-theme='dark']` 里有覆盖值且暗色块没有凭空多出的变量名(新增颜色令牌漏写暗色值直接报错),核对 README 的 `<!-- ua:components -->` 区块与「分组:」行都覆盖清单组件集合(漏写/多写/重复都报错),并交叉校验 backlog 的 done 条目与 `.ua/iterations.log` 的 done 留痕一一对应(另外查 backlog id 不重复、g 编号严格递增、同一 id 只有一条 done 留痕,且留痕 ts 带 +08:00、时间线不回退、不落在未来——都是过去手工插条目/手写时间戳踩过的坑);配方还要求编号连续、每条都有代码块与要点,且代码块里至少认出一个已注册组件 id(拼错组件名时 `ua recipes` 会把它列成空组件表)。
**变更日志**:`CHANGELOG.md` 由 git 提交史生成(`npm run changelog`),**不进 `npm run check`**——它包含每个提交自身,提交后必然与历史差一条,只能作为「发版前刷新」步骤;`npm run changelog:check` 用于确认是否漂移。 **变更日志**:`CHANGELOG.md` 由 git 提交史生成(`npm run changelog`),**不进 `npm run check`**——它包含每个提交自身,提交后必然与历史差一条,只能作为「发版前刷新」步骤;`npm run changelog:check` 用于确认是否漂移。
@@ -72,7 +72,7 @@
| 1 | `packages/skin/ui/src/<id>.ts` | 组件实现(单文件 ≤ 200 行,导出带 `/*** */` 注释) | | 1 | `packages/skin/ui/src/<id>.ts` | 组件实现(单文件 ≤ 200 行,导出带 `/*** */` 注释) |
| 2 | `packages/skin/ui/src/types.ts` | `<组件>Props` 接口 + 逐字段行尾注释;嵌套项类型(如 `TabItem`)也放这里 | | 2 | `packages/skin/ui/src/types.ts` | `<组件>Props` 接口 + 逐字段行尾注释;嵌套项类型(如 `TabItem`)也放这里 |
| 3 | `packages/skin/ui/src/index.ts` | 末尾追加 `export { xxx } from './xxx.js';` | | 3 | `packages/skin/ui/src/index.ts` | 末尾追加 `export { xxx } from './xxx.js';` |
| 4 | `packages/skin/ui/ui.css` | 样式只消费 `--ua-*`(禁 `#hex`),动效要带 `prefers-reduced-motion` 兜底 | | 4 | `packages/skin/ui/ui.css` | 样式只消费 `--ua-*`(禁 `#hex`),动效要带 `prefers-reduced-motion` 兜底;**禁止新增硬编码 `box-shadow` / 动效时长 / `font-size` 字面值**,一律用 elevation(`--ua-shadow-1..4`)/ motion(`--ua-duration-*` + `--ua-ease`)/ 字号(`--ua-font-size-*`)令牌,焦点环用 `--ua-focus-ring`,`npm run audit:visual` 会让计数上涨的提交直接红 |
| 5 | `packages/skin/ui/ua.manifest.json` → `api.exports` | 一行 `xxx(props):一句话说明` | | 5 | `packages/skin/ui/ua.manifest.json` → `api.exports` | 一行 `xxx(props):一句话说明` |
| 6 | 同上 → `docs.components` | `{ id, title, demo, props[], example, steps[] }`:props 里每个字段名必须在实现源码里真实出现,且 `<组件>Props` 的字段一个都不能漏(verify 双向校验) | | 6 | 同上 → `docs.components` | `{ id, title, demo, props[], example, steps[] }`:props 里每个字段名必须在实现源码里真实出现,且 `<组件>Props` 的字段一个都不能漏(verify 双向校验) |
| 7 | `apps/demo/main.ts` | 新增 `section('<demo 锚点>', ...)` 并**真实调用**该组件(verify 会查) | | 7 | `apps/demo/main.ts` | 新增 `section('<demo 锚点>', ...)` 并**真实调用**该组件(verify 会查) |
+10 -2
View File
@@ -42,9 +42,9 @@ qa/probe ──门禁通过──▶ qa/stable ──人工审阅──▶ main
## 每轮迭代流程(自动化 Agent 执行) ## 每轮迭代流程(自动化 Agent 执行)
1. **同步**:`git fetch --all --prune`,切到 `qa/stable` 并 `git pull`;从其最新提交强制重建 `qa/probe` 并切换过去。 1. **同步**:`git fetch --all --prune`,切到 `qa/stable` 并 `git pull`;从其最新提交强制重建 `qa/probe` 并切换过去。
2. **选题**:读 `.ua/backlog.json`,取第一条 `status === "open"` 的条目;若全部关闭,按《选题规则》自行补充一条新点子后继续。 2. **选题**:读 `.ua/backlog.json`,先取 `status === "open"` 且 `domain === "visual"` 的条目(有多条取编号最小的一条);没有视觉欠账时再按数组顺序取第一条 `status === "open"` 的条目;若全部关闭,按《选题规则》自行补充一条新点子后继续。
3. **实现**:按 `CODING.md` 编码规范实现,保持低侵入,单文件 < 200 行,涉及组件需同步 manifest/docs/llms-full.txt。 3. **实现**:按 `CODING.md` 编码规范实现,保持低侵入,单文件 < 200 行,涉及组件需同步 manifest/docs/llms-full.txt。
4. **门禁**:跑 `npm run check`(build → demo → style → typecheck → smoke → index → verify)。 4. **门禁**:跑 `npm run check`(build → demo → style → typecheck → smoke → index → verify → lint-iterations → audit:visual)。
- **通过**:提交到 `qa/probe`,提交信息按 `COMMITTING.md` 规范(`iter(<条目id>): <中文祈使句>`,元数据变更用 `chore(backlog): 记录 <id> 完成`;commit-msg 钩子自动校验),推送 `qa/probe`,fast-forward 合并到 `qa/stable` 并推送;将 backlog 条目 `status` 置为 `done` 并随迭代提交。 - **通过**:提交到 `qa/probe`,提交信息按 `COMMITTING.md` 规范(`iter(<条目id>): <中文祈使句>`,元数据变更用 `chore(backlog): 记录 <id> 完成`;commit-msg 钩子自动校验),推送 `qa/probe`,fast-forward 合并到 `qa/stable` 并推送;将 backlog 条目 `status` 置为 `done` 并随迭代提交。
- **失败**:尝试修复一次;仍失败则放弃本轮——`qa/probe` 直接重置回 `qa/stable`,backlog 条目在 `notes` 里追加失败原因、`status` 保持 `open`,提交并推送该元数据变更(仅改 `.ua/backlog.json`,不碰代码)。 - **失败**:尝试修复一次;仍失败则放弃本轮——`qa/probe` 直接重置回 `qa/stable`,backlog 条目在 `notes` 里追加失败原因、`status` 保持 `open`,提交并推送该元数据变更(仅改 `.ua/backlog.json`,不碰代码)。
5. **留痕**:在 `.ua/iterations.log` 追加一行 JSON,**字段统一**:`{"ts":"本地ISO时间","id":"条目id","result":"done|aborted","commit":"短哈希","summary":"一句话"}`。硬性规范:`ts` 必须来自 `date` 命令实测(本地时间,带 +08:00 偏移,**禁止手写或用 UTC 换算**);时长结论必须来自两次时间查询之差,禁止使用「大约/接近」等估算词;并发实例格式不得自创变体。随本轮提交。`ua lint-iterations` 会把每行 `commit` 拿到 git 历史里回查:哈希必须真实存在、主题必须指向同一条目(`iter(<id>)`,早期无 scope 的 `iter: <id>` 也认),伪造或抄错哈希直接判违规。 5. **留痕**:在 `.ua/iterations.log` 追加一行 JSON,**字段统一**:`{"ts":"本地ISO时间","id":"条目id","result":"done|aborted","commit":"短哈希","summary":"一句话"}`。硬性规范:`ts` 必须来自 `date` 命令实测(本地时间,带 +08:00 偏移,**禁止手写或用 UTC 换算**);时长结论必须来自两次时间查询之差,禁止使用「大约/接近」等估算词;并发实例格式不得自创变体。随本轮提交。`ua lint-iterations` 会把每行 `commit` 拿到 git 历史里回查:哈希必须真实存在、主题必须指向同一条目(`iter(<id>)`,早期无 scope 的 `iter: <id>` 也认),伪造或抄错哈希直接判违规。
@@ -56,6 +56,14 @@ qa/probe ──门禁通过──▶ qa/stable ──人工审阅──▶ main
- 单轮改动范围可控:新增文件 + 少量既有文件修改,避免跨包大规模重构。 - 单轮改动范围可控:新增文件 + 少量既有文件修改,避免跨包大规模重构。
- 每条点子必须写清 `title / motivation / acceptance`(验收标准,可被 `npm run check` 与人工检查验证)。 - 每条点子必须写清 `title / motivation / acceptance`(验收标准,可被 `npm run check` 与人工检查验证)。
### 域轮换与视觉欠账优先
`backlog.json` 的条目带可选字段 `domain`:`new`(新增组件)/ `tune`(既有组件打磨)/ `visual`(视觉地基与观感)/ `tooling`(门禁、CLI、文档、配方)。选题按下面三条排队,保证视觉欠账会被持续消化,而不是永远排在「加新组件」后面:
1. **域轮换**:连续 3 轮迭代中,至少 1 轮的条目 `domain` 为 `visual`。若已连续 3 轮都不是 visual,下一轮必须从 open 的 visual 条目里选。
2. **视觉欠账优先**:只要存在 `status === "open"` 且 `domain === "visual"` 的条目,它的优先级高于 `domain === "new"` 的条目——先清视觉欠账,再加新组件(视觉地基不牢,新组件只是把漂移再复制一份)。
3. **新增组件的入库门槛**:`domain === "new"` 的条目,验收标准里必须写明「样式只消费 `--ua-*` 令牌,禁止新增硬编码阴影/时长/字号」,否则该条不得入库。视觉类改进的验收标准要能落到 `npm run audit:visual` 的计数上(涨了就是没做完)。
## 人工介入点 ## 人工介入点
- 审阅 `qa/stable` 的提交,确认质量后合入 `main`(PR 或本地 merge 后推送)。 - 审阅 `qa/stable` 的提交,确认质量后合入 `main`(PR 或本地 merge 后推送)。
+1 -1
View File
@@ -6,7 +6,7 @@
```bash ```bash
pnpm install # 包间依赖用 workspace:*,npm 不支持 pnpm install # 包间依赖用 workspace:*,npm 不支持
npm run check # 门禁一条龙:build → demo → style → typecheck → smoke → index → verify npm run check # 门禁一条龙:build → demo → style → typecheck → smoke → index → verify → lint-iterations → audit:visual
npm run demo # 打开演示:apps/demo/dist/demo.html npm run demo # 打开演示:apps/demo/dist/demo.html
npm run docs # 生成人类文档站 apps/docs/index.html + Agent 全量文档 llms-full.txt npm run docs # 生成人类文档站 apps/docs/index.html + Agent 全量文档 llms-full.txt
npm run changelog # 依据 git 提交史重写 CHANGELOG.md(发版前跑;changelog:check 可查漂移) npm run changelog # 依据 git 提交史重写 CHANGELOG.md(发版前跑;changelog:check 可查漂移)