- 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),验收标准均可枚举或可机检
8.5 KiB
AGENTS.md - Agent 接入手册
面向 AI Agent(以及新加入的人类协作者)的组件库使用规范。本文件同时是项目入口文档。
环境准备(新 Agent 必读,先跑通再干活)
- 包管理器必须用 pnpm:包间依赖用
workspace:*协议,npm 不支持。安装依赖:pnpm install。 - 构建工具:TypeScript 5(
tsc)。若环境未全局安装,可使用托管工作区的副本:C:/Users/shawn/.workbuddy/binaries/node/workspace/node_modules/typescript(本仓库历史即如此构建)。 - Node:>= 18,ESM(
"type": "module")。 - 验证自检:装好后先跑
npm run check(build → demo → style → typecheck → smoke → index → verify → lint-iterations → audit:visual)确认基线全绿,再开始改代码。
编码规范(强制)
所有 TS / JS 代码遵循 CODING.md:注释一律中文(函数级 /*** 作用 ***/、行尾 // 短注释),代码紧凑 + 行工整、卫语句单行,高可扩展、低抽象、可读性优先。
注释强制门禁:npm run style(即 ua style)机器检查——导出必须有 /*** ***/ 注释、接口字段必须有行尾注释、行注释必须中文,并强制分层包 src 下单文件 ≤ 200 行(types.ts 与 index.ts 作为类型/导出汇总豁免);有违规即退出码 1,改完才能提交。
项目结构(权威定义见 ARCHITECTURE.md)
分层目录,依赖方向单向 apps → skin → core → design:
packages/core/table-core(@ui-arch/table-core):Headless 表格逻辑内核packages/core/frame(@ui-arch/frame):signal + hyperscript 微框架packages/skin/ui(@ui-arch/ui):67 个 DOM 组件(表单 / 反馈 / 浮层 / 导航 / 表格),样式只消费令牌packages/design/tokens(@ui-arch/tokens):设计令牌packages/tools/cli(@ui-arch/cli):ua命令行 + MCP 注册表服务(private)apps/demo(@ui-arch/demo):交互演示,产物 apps/demo/dist/demo.htmlapps/docs:文档站,纯产物(ua docs 生成)
门禁一条龙: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 用于确认是否漂移。
提交信息规范:COMMITTING.md(<type>(<scope>): <中文祈使句>),ua commit-lint + commit-msg 钩子自动校验,迭代提交用 iter(<条目id>): <subject>。
Agent 查询组件库的三种方式(ua info <组件id> 直接出 props/步骤/示例)
- MCP(推荐):在
~/.workbuddy/mcp.json注册:
{
"mcpServers": {
"ui-arch-registry": {
"command": "node",
"args": ["<仓库绝对路径>/packages/tools/cli/bin/ua.js", "mcp"]
}
}
}
可用工具:list_components / get_component / search_components / get_tokens(返回 --ua-* 令牌清单,避免硬编码颜色间距)/ list_recipes / get_recipe(取跨组件组合配方:骨架代码 + 要点 + 用到的组件 id,配好再逐个 get_component 查参数)。
-
CLI:
node packages/tools/cli/bin/ua.js list [--json|--components] | search <关键词> | info <name> [--json] | recipes [编号] [--json] | index | docs | style | verify | changelog(--json给脚本与 Agent 用,不必解析文本);search覆盖 id / 标题 / 参数名 / 参数说明 / 步骤五层,命中非 id 标题时会标出命中字段(如「← 参数说明含『处理中』」),--json附带matched字段 -
静态索引:
.ua/index.json(机器可读索引)、llms.txt(速览)或llms-full.txt(全量 Agent 文档:逐组件参数 / 回调 / 手把手步骤 / 令牌 / 组合配方,无图形纯文本,喂给 Agent 首选)。
贡献新组件的强制约定
- 按
ARCHITECTURE.md分层模型确定目录归属:逻辑→core,渲染→skin,令牌→design,脚本→tools - 新包必须包含
ua.manifest.json(name/type/description/tags/api/usage),否则不会被索引;type 取值:headless-core / skin-dom / design-tokens / tooling - 行为逻辑放 core 包,DOM 渲染放 skin 包;皮肤间不互相依赖,公共逻辑下沉 core
- 皮肤包禁止硬编码颜色/间距,一律使用
--ua-*令牌 - 选择类状态一律存 rowKey,不存行索引
- 改动后运行
npm run index刷新注册表;新增组件记得在 manifest 的docs.components里补参数表与手把手步骤,npm run docs会同步生成人类版文档站与 llms-full.txt
新增组件落点清单(照单打勾,漏一处 npm run check 就会红)
一个新组件要动 10 处,缺任何一处 verify 都会报错,别靠记忆:
| # | 落点 | 具体动作 |
|---|---|---|
| 1 | packages/skin/ui/src/<id>.ts |
组件实现(单文件 ≤ 200 行,导出带 /*** */ 注释) |
| 2 | packages/skin/ui/src/types.ts |
<组件>Props 接口 + 逐字段行尾注释;嵌套项类型(如 TabItem)也放这里 |
| 3 | packages/skin/ui/src/index.ts |
末尾追加 export { xxx } from './xxx.js'; |
| 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):一句话说明 |
| 6 | 同上 → docs.components |
{ id, title, demo, props[], example, steps[] }:props 里每个字段名必须在实现源码里真实出现,且 <组件>Props 的字段一个都不能漏(verify 双向校验) |
| 7 | apps/demo/main.ts |
新增 section('<demo 锚点>', ...) 并真实调用该组件(verify 会查) |
| 8 | README.md |
<!-- ua:components --> 区块补 id、「分组:」行补归组(数字交给下一步自动同步) |
| 9 | npm run sync-counts |
自动把三份文档里的「N 个组件 / 共 N 个」改成清单实际数量(幂等;漏改时 verify 报行号) |
| 10 | npm run docs |
重新生成 llms-full.txt 与 apps/docs/index.html(不跑 verify 会报 llms-full 漂移) |
改既有组件的入参同样要走 5、6、10 三步;只加一个可选参数也要补文档行,否则双向校验失败。