@zyaiting/keelson 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +101 -0
  3. package/README_CN.md +101 -0
  4. package/bin/keelson.js +15 -0
  5. package/hooks/codebuddy-session.mjs +67 -0
  6. package/hooks/opencode-session.mjs +65 -0
  7. package/hooks/prompt-state.mjs +66 -0
  8. package/hooks/session-start.mjs +94 -0
  9. package/package.json +64 -0
  10. package/registry/models.json +118 -0
  11. package/registry/platforms.json +92 -0
  12. package/skills/keelson/SKILL.md +44 -0
  13. package/skills/keelson/references/build.md +61 -0
  14. package/skills/keelson/references/context.md +34 -0
  15. package/skills/keelson/references/debug.md +46 -0
  16. package/skills/keelson/references/design-lenses.md +78 -0
  17. package/skills/keelson/references/discover.md +70 -0
  18. package/skills/keelson/references/engineer.md +110 -0
  19. package/skills/keelson/references/frontend-delivery.md +38 -0
  20. package/skills/keelson/references/frontend-interaction.md +31 -0
  21. package/skills/keelson/references/frontend-review.md +33 -0
  22. package/skills/keelson/references/frontend-visual.md +31 -0
  23. package/skills/keelson/references/frontend.md +33 -0
  24. package/skills/keelson/references/handoff.md +43 -0
  25. package/skills/keelson/references/harness.md +54 -0
  26. package/skills/keelson/references/interview.md +120 -0
  27. package/skills/keelson/references/land.md +47 -0
  28. package/skills/keelson/references/model.md +29 -0
  29. package/skills/keelson/references/plan.md +106 -0
  30. package/skills/keelson/references/reconcile.md +61 -0
  31. package/skills/keelson/references/shape.md +86 -0
  32. package/skills/keelson/references/verify.md +64 -0
  33. package/skills/keelson/templates/GLOSSARY.md +5 -0
  34. package/skills/keelson/templates/INTENT.md +22 -0
  35. package/skills/keelson/templates/NOW.md +9 -0
  36. package/skills/keelson/templates/README.md +60 -0
  37. package/skills/keelson/templates/ROADMAP.md +12 -0
  38. package/skills/keelson/templates/change-quick.md +16 -0
  39. package/skills/keelson/templates/change.md +32 -0
  40. package/skills/keelson/templates/delta-spec.md +12 -0
  41. package/skills/keelson/templates/handoff.md +27 -0
  42. package/skills/keelson/templates/ledger.md +3 -0
  43. package/skills/keelson/templates/resident-block.md +7 -0
  44. package/skills/keelson/templates/rules-general.md +10 -0
  45. package/skills/keelson/templates/rules-index.md +5 -0
  46. package/skills/keelson/templates/spec.md +14 -0
  47. package/skills/keelson/templates/tasks.md +9 -0
  48. package/skills/keelson/templates/workflow.md +18 -0
  49. package/skills/zh/keelson/SKILL.md +46 -0
  50. package/skills/zh/keelson/references/build.md +61 -0
  51. package/skills/zh/keelson/references/context.md +34 -0
  52. package/skills/zh/keelson/references/debug.md +46 -0
  53. package/skills/zh/keelson/references/design-lenses.md +78 -0
  54. package/skills/zh/keelson/references/discover.md +70 -0
  55. package/skills/zh/keelson/references/engineer.md +110 -0
  56. package/skills/zh/keelson/references/frontend-delivery.md +38 -0
  57. package/skills/zh/keelson/references/frontend-interaction.md +31 -0
  58. package/skills/zh/keelson/references/frontend-review.md +33 -0
  59. package/skills/zh/keelson/references/frontend-visual.md +31 -0
  60. package/skills/zh/keelson/references/frontend.md +33 -0
  61. package/skills/zh/keelson/references/handoff.md +43 -0
  62. package/skills/zh/keelson/references/harness.md +54 -0
  63. package/skills/zh/keelson/references/interview.md +120 -0
  64. package/skills/zh/keelson/references/land.md +47 -0
  65. package/skills/zh/keelson/references/model.md +29 -0
  66. package/skills/zh/keelson/references/plan.md +106 -0
  67. package/skills/zh/keelson/references/reconcile.md +61 -0
  68. package/skills/zh/keelson/references/shape.md +86 -0
  69. package/skills/zh/keelson/references/verify.md +64 -0
  70. package/skills/zh/keelson/templates/GLOSSARY.md +5 -0
  71. package/skills/zh/keelson/templates/INTENT.md +22 -0
  72. package/skills/zh/keelson/templates/NOW.md +9 -0
  73. package/skills/zh/keelson/templates/README.md +60 -0
  74. package/skills/zh/keelson/templates/ROADMAP.md +12 -0
  75. package/skills/zh/keelson/templates/change-quick.md +16 -0
  76. package/skills/zh/keelson/templates/change.md +32 -0
  77. package/skills/zh/keelson/templates/delta-spec.md +12 -0
  78. package/skills/zh/keelson/templates/handoff.md +27 -0
  79. package/skills/zh/keelson/templates/ledger.md +3 -0
  80. package/skills/zh/keelson/templates/resident-block.md +7 -0
  81. package/skills/zh/keelson/templates/rules-general.md +10 -0
  82. package/skills/zh/keelson/templates/rules-index.md +5 -0
  83. package/skills/zh/keelson/templates/spec.md +14 -0
  84. package/skills/zh/keelson/templates/tasks.md +9 -0
  85. package/skills/zh/keelson/templates/workflow.md +18 -0
  86. package/src/cli.js +87 -0
  87. package/src/commands/ablate.js +96 -0
  88. package/src/commands/ask.js +64 -0
  89. package/src/commands/attest.js +71 -0
  90. package/src/commands/check.js +127 -0
  91. package/src/commands/context.js +95 -0
  92. package/src/commands/design.js +63 -0
  93. package/src/commands/doctor.js +157 -0
  94. package/src/commands/focus.js +84 -0
  95. package/src/commands/guide.js +59 -0
  96. package/src/commands/handoff.js +41 -0
  97. package/src/commands/hook.js +23 -0
  98. package/src/commands/impact.js +58 -0
  99. package/src/commands/init.js +289 -0
  100. package/src/commands/land.js +258 -0
  101. package/src/commands/models.js +62 -0
  102. package/src/commands/new.js +70 -0
  103. package/src/commands/platforms.js +39 -0
  104. package/src/commands/retro.js +114 -0
  105. package/src/commands/status.js +115 -0
  106. package/src/commands/uninstall.js +30 -0
  107. package/src/commands/validate.js +117 -0
  108. package/src/lib/args.js +30 -0
  109. package/src/lib/changes.js +114 -0
  110. package/src/lib/check-activity.js +29 -0
  111. package/src/lib/config.js +102 -0
  112. package/src/lib/decisions.js +59 -0
  113. package/src/lib/evidence.js +127 -0
  114. package/src/lib/fs.js +126 -0
  115. package/src/lib/git.js +353 -0
  116. package/src/lib/glob.js +54 -0
  117. package/src/lib/health.js +113 -0
  118. package/src/lib/lifecycle.js +120 -0
  119. package/src/lib/maintenance.js +66 -0
  120. package/src/lib/markdown.js +438 -0
  121. package/src/lib/models.js +195 -0
  122. package/src/lib/out.js +13 -0
  123. package/src/lib/paths.js +82 -0
  124. package/src/lib/rules.js +27 -0
  125. package/src/lib/runtime-path.js +22 -0
  126. package/src/lib/session.js +100 -0
  127. package/src/lib/specs.js +345 -0
  128. package/src/lib/transaction.js +93 -0
  129. package/src/platforms/index.js +3 -0
  130. package/src/platforms/integration.js +384 -0
  131. package/src/platforms/registry.js +46 -0
  132. package/src/platforms/runtime.js +249 -0
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: keelson
3
+ description: 面向含 .keelson/ 目录项目的工程控制层。用于探索想法、修改代码、修复/调试、前端设计与 UX 评审、继续之前的工作,或改进反复出现的工程失败。把“对话会话”和“长期 work item”分开,因此用户可以一直追问,而不需要主动宣布任务何时开始或结束。
4
+ ---
5
+
6
+ # Keelson
7
+
8
+ 项目本地执行内核是 `keelson guide workflow`。Keelson 约束的是**状态转换与证据**,不是实现口味。用户指令和项目指令优先。
9
+
10
+ ## 判断对话意图,不把生命周期当成用户意图
11
+
12
+ | 意图 | 常见请求 | 首先读取 |
13
+ |---|---|---|
14
+ | **Explore** | 比较、解释、“应该怎么做”、“深挖一下” | `discover.md` + `interview.md`;明确要求修改之前保持只读 |
15
+ | **Change** | 构建、新增、重构、迁移、“再顺便改……” | `shape.md` → `context.md`;边界/术语问题读 `model.md`,非显然技术选择读 `engineer.md`,只有风险触发时才读 `design-lenses.md`;spec 级再加 `plan.md` |
16
+ | **Fix** | bug、测试失败、异常行为 | `debug.md`,随后 `verify.md` |
17
+ | **Resume** | 继续、接着做 | `keelson focus --auto` + 当前上下文;只有真正跨人/跨机器交接时才读 `handoff.md` |
18
+ | **Improve** | 重复错误、Harness/rule/流程问题、retro | `harness.md` + `reconcile.md` |
19
+
20
+ “完成”**不是一种用户意图**,也绝不依赖用户说“做完了”。它是状态转换:当前 focus change 的 acceptance、阻塞问题/假设、rollout 和当前工作树上的新鲜 verification 全部满足后,状态自动成为 `ready`。这时自动执行 Finish 路径(`verify.md` → `land.md` → `reconcile.md`),然后才能宣称完成。
21
+
22
+ - 涉及界面设计、评审、交互或响应式时,加载 `frontend.md`;用 `keelson design` 读取具体动作指导。区分浏览器观察与代码检查。
23
+
24
+ ## 执行规则
25
+
26
+ - conversation/session 只是焦点指针。关闭窗口、长时间不说话、继续追问,都**不能**把 change 判成完成。
27
+ - 有 session identity 时,`keelson new` 自动把新 change 绑定到当前会话。同一目标的追问继续使用它;独立的新修改目标创建新 change 并移动 focus。
28
+ - Resume 时先用 `keelson focus --auto`;可以根据 branch 或唯一活动 change 给出候选,但存在歧义时绝不静默绑定。
29
+ - `NOW.md` 为 First contact 时,只推断并确认 `INTENT.md`;不要盘点整个仓库生成 specs/rules。
30
+ - 非平凡修改先读取当前上下文;改共享模块前运行 `keelson impact <files>`。
31
+ - 只在 decision frontier 提问。先做风险触发式盲点扫描,再按 `interview.md` 每轮最多三个独立、已就绪的所有者决策:具体场景/选项、推荐默认值,“不确定”是合法路由。仓库证据、小实验或 Agent 工程判断能解决的事绝不问用户。
32
+ - 非显然机制/架构选择走 `engineer.md`:先还原事实、结果、约束和不变量,再写可证伪 hypothesis,用最便宜的实验/消融区分方案;复杂度必须用证据证明自己值得存在。
33
+ - 只给工作本身定大小:trivial 直接改;quick 轻量 change;spec 先写验收、行为 delta 和计划,在用户已有授权内推进;只澄清尚未解决的所有者决策。
34
+ - 工件是信息容器,不是仪式。不要创建空 roadmap/glossary/rule/task/ledger/handoff/spec。
35
+ - `tasks.md` 只是执行计划,不拥有“完成”判定权。只要 acceptance 与新鲜证据已经满足,未勾选的旧计划不能覆盖这个事实;实现路径变化时应重写或删除过时任务。
36
+ - 知识维护属于 Keelson 内部职责。RECONCILE 时自动重写、拆分、去重超压的长期文档,大 spec 由 `land` 自动分片;除非涉及产品语义决策,否则绝不要求用户维护 Keelson。
37
+ - 始终区分**代码现实、已确认真相、计划变更**;未决问题只阻塞依赖它的切片。
38
+ - 宣称完成必须有当前工作树上的新鲜 `keelson check --record` 证据;不得为了通过检查而削弱验收。
39
+ - change 一旦成为 `ready`,就应自动 land,不等待用户说特殊结束语;若仍缺所有者决策,只停在那个决策上。
40
+ - `handoff.md` 只用于真正跨人/跨机器或明确所有权转移;普通跨会话接续由长期 change 工件 + Git 私有目录中的会话状态 完成。
41
+ - 重复失败提升为最窄的长期控制:spec → 作用域 rule → 可执行 fitness check;随后删除冗余 prose。
42
+ - 只使用 `light | standard | deep`,绝不持久化带日期模型 ID。
43
+
44
+ 用户通常只需要 `init`、`status`、`doctor`、`update`、`uninstall`;其余由 Agent 使用。
45
+
46
+ 用 `keelson guide <name>` 按需读取下表引用(省略 `.md`)。首次执行配置检查先审阅命令,再用 `--trust` 明确信任;已有用户授权不重复确认。
@@ -0,0 +1,61 @@
1
+ # Building(构建)
2
+
3
+ 按切片逐个执行 `tasks.md`。怎么做由你选;这里只写容易出错的部分。
4
+
5
+ ## 裁定,而不是停顿
6
+ <!-- keelson: id=build.rulings | without: 代理把会话卡在计划早已回答的问题上;或者悄悄决定,推理过程丢失 | sunset: never -->
7
+
8
+ 计划是论证;specs 和 `INTENT.md` 是权威;两者都没回答的,由你在 `INTENT.md → Authorizations` 的范围内裁定。在授权范围内遇到歧义或计划缺陷时,决定、记录、继续:
9
+
10
+ ```markdown
11
+ ### Ruling: ack semantics
12
+ At-least-once with idempotent consumers. Exactly-once would need a broker feature we do not run. Cost if wrong: duplicate side effects in `notify`, bounded by the idempotency key.
13
+ ```
14
+
15
+ 超出授权范围的,就是未决问题:写进 `change.md → Open questions` 并注明它阻塞什么,然后去建它不阻塞的切片。只有四件事让你彻底停下:不可逆或破坏性操作;涉及安全的操作;工作树之外、按惯例应先询问的副作用(合并、推到共享分支、发布、外部调用);计划烂到每条路都是猜。
16
+
17
+ ## 按 effort 层级分派子代理
18
+ <!-- keelson: id=build.dispatch | without: 一个上下文包揽一切,越装越满质量越差,而且不管任务难易成本都一样 | sunset: 宿主没有子代理工具时,本节自然失效 -->
19
+
20
+ 任务大体独立、宿主提供子代理时,每个任务派一个全新的子代理,模型由它的 effort 层级解析:`keelson models --resolve <tier>` 打印当前平台的别名(或者把层级按能力从低到高映射到子代理工具暴露的别名上)。交给子代理的是任务文本、命中的 rules、相关 spec 和验证命令。绝不把你的整段对话塞给它。
21
+
22
+ 更多 Agent 不是线性的 throughput multiplier。任务共享可变状态、同一契约,或者需要持续互相同步时,coordination/merge cost 可能超过并行收益;此时保持串行。只有边界清楚、输出可以独立验证、最终 merge contract 明确时才并行。不要靠“再加几个 Agent”挽救一个高度耦合的任务。
23
+
24
+ 每个任务之后,由一个评审子代理(层级 ≥ `standard`,绝不低于实施者)对照 spec 和 rules 检查 diff。两者都记进 ledger:
25
+
26
+ ```markdown
27
+ ### Dispatch: task 2 → standard (sonnet)
28
+ Result: pass
29
+ Implemented paged query; reviewer accepted. Verify `npm test -- orders.repo` exit 0.
30
+ ```
31
+
32
+ `Dispatch:` 正文的第一行是 `Result: pass` 或 `Result: fail`;`keelson retro` 只数这一行,不看散文里的用词。
33
+
34
+ 任务的验证在同一层级失败两次,就升一级重新分派,并记录:
35
+
36
+ ```markdown
37
+ ### Escalate: task 2 light → standard
38
+ Two failures on boundary handling; light-tier output ignored the empty-page case.
39
+ ```
40
+
41
+ 升级只针对"做出来但做错了"的工作,不针对根本没跑起来的分派:限流、超时、工具报错,在同一层级稍等后重试一次,再不行就由你自己内联完成并记一条(`### Note: task 3 inline after two dispatch errors`)。`deep` 是最高层级,没有更高可升;`deep` 的验证失败则停下来问。任务紧耦合,或没有子代理工具:自己内联执行,仍然一次一个任务,仍然记 ledger。
42
+
43
+ ## 并行工作
44
+ <!-- keelson: id=build.parallel | without: 两个写代码的人在同一分支上互相覆盖,或者两个变更用两种方式实现同一契约 | sunset: never -->
45
+
46
+ 多个写代码的人(人或代理)同时工作时,每个变更用自己的分支或 worktree(`keelson new --worktree`)。共享接口在任何一方实现之前先对齐:在 delta spec 里约定契约,落地或引用它,然后再建。两个活动变更触及同一能力或同样声明的路径时,`keelson status` 会警告;把它当作"先谈",不是锁。磁盘上的文件不是分布式锁,分支也消除不了语义冲突;跨机器的认领和合并控制属于任务系统、pull request 和 CI。把别人的变更集成进你的之后,重新跑验证;旧证据按定义已经过期。
47
+
48
+ 对方所有者联系不上时(无人值守运行、同事不在线),既不要等待,也不要假装重叠不存在:把你对共享需求的 delta 压到这次变更允许的最小范围,在 ledger 里记一条 `### Note:`、在 `NOW.md` 里写一行说明重叠,并在写回和完成报告里说出来。`keelson land` 落地时会点名重叠的变更;它们的落地会停在漂移门禁上,直到其所有者重新读过合并后的 spec。
49
+
50
+ ## 工作过程中让工件保持真实
51
+ <!-- keelson: id=build.update-artifacts | without: tasks.md 和 change.md 描述的是计划而不是实际发生的事;下一个会话信了过期的文字 | sunset: never -->
52
+
53
+ 任务在验证通过时打勾,不是写完时。验收项在它的检查跑过之后打勾。构建中途设计变了,就改 `change.md`;行为变了,再改 delta spec。没有东西是锁死的;唯一的规则是每次提交时文件都反映现实。变更没做完就要停下,`keelson handoff <name>` 并填好它(见 `handoff.md`)。
54
+
55
+ <!-- guided -->
56
+ ## 行为有明确规格时先写测试
57
+ delta spec 里有 scenario 的地方,先按 scenario 写失败的测试,看它失败,实现,看它通过。没有 scenario 的地方,自己判断测试是否是最便宜的证据。视觉探索和未知 API 可以先做一个小原型。
58
+
59
+ ## 叙述
60
+ 工具调用之间最多一行短话。记录由 ledger 和工具输出承担。
61
+ <!-- /guided -->
@@ -0,0 +1,34 @@
1
+ # 上下文与影响
2
+
3
+ 项目资料随项目增长;每个任务要读的内容,不能随全部历史一起增长。先知道去哪里找,再只打开这次变更需要的。
4
+
5
+ ## 三层
6
+ <!-- keelson: id=context.layers | without: 每个会话要么读全部、要么什么都不读;约定要么淹没、要么漏掉 | sunset: never -->
7
+
8
+ 1. **稳定入口** — 常驻块、`INTENT.md`、`ROADMAP.md → Now`,以及由 `**` 路由的 rules。每次都读;刻意保持短小。
9
+ 2. **任务资料** — 当前的 `change.md`、它点名的能力的 specs、你将改动路径命中的 rules、覆盖这些能力的测试,以及 spec 链接到的任何 `refs` 文档。`keelson context --paths <files>` 会打印其中大部分。
10
+ 3. **按需展开** — 调用方、其他入口、相邻模块、git 历史里的过往变更。有问题时再打开,不要预先加载。
11
+
12
+ 绝不因为某条始终有效的约束很少用到就降级它。`**` 之下的安全和兼容性规则每次都读;这正是 `**` 的用意。
13
+
14
+ ## 影响是分析出来的,不是查出来的
15
+ <!-- keelson: id=context.impact | without: 代理把 rules 索引和 diff 当成完整的波及范围,漏掉目录之外的调用方 | sunset: never -->
16
+
17
+ `keelson impact <files>` 按名字列出导入方、文本或路径匹配的 specs、适用的 rules,以及声明了相同路径或能力的活动变更。这是导航。改共享模块之前,靠阅读回答:
18
+
19
+ - 谁调用它?包括 grep 看不见的动态入口:CLI 命令、定时任务、路由、事件处理器、模板。
20
+ - 同一行为有没有另一条进入路径(页面旁边的下载 API,请求处理器旁边的批处理任务)?
21
+ - 哪些数据约束、权限规则或兼容性承诺依赖它?查 spec 的 `Decisions`。
22
+ - 别人的活动变更是否触及同一契约?`keelson status` 会显示共享契约。
23
+
24
+ 把答案写进 `change.md → Impact`。只列出 diff 里文件的 Impact 段不是分析。
25
+
26
+ ## 预算
27
+ <!-- keelson: id=context.budget | without: 上下文不够时,代理悄悄丢掉已经读过的约束,或者靠猜而不是读 | sunset: never -->
28
+
29
+ 一个变更的资料装不下时,不要把约束概括成更宽松的说法。缩小切片,或继续按需读取并说明你还没检查什么。"尚未检查:……"写在 `NOW.md → Blocked / uncertain`。
30
+
31
+ <!-- guided -->
32
+ ## spec 变更的阅读顺序
33
+ `INTENT.md` → `ROADMAP.md → Now` → `change.md` → 它点名的能力 specs → 命中的 rules → 这些能力的测试 → 对你将改动的文件跑 `keelson impact` → 它找到的调用方 → spec 在 `refs` 下链接的任何文档。
34
+ <!-- /guided -->
@@ -0,0 +1,46 @@
1
+ # Debugging(调试)
2
+
3
+ 不知道原因的修复只是恰好通过的猜测。本参考的存在,是为了让原因被找到、被命名,并反馈回项目。
4
+
5
+
6
+ 界面工作按需加载 `frontend.md`;视觉与交互验收遵循 `frontend-review.md` 和 `frontend-delivery.md`。
7
+
8
+ ## 先复现,再定位,再修
9
+ <!-- keelson: id=debug.reproduce-first | without: 代理凭假设改代码;症状挪了位置,原因还在,bug 换个名字回来 | sunset: 当 retro 显示 guessed-fix = 0 across the last 20 root-cause entries(最近 20 条根因记录中 guessed-fix 为 0)时 -->
10
+
11
+ 1. 完整读错误和堆栈。它通常直接指出那一行。
12
+ 2. 确定性地复现:一个失败的测试、一个脚本,或精确的步骤。复现不了,就无法知道它已被修好。
13
+ 3. 定位:观察到的行为从哪里开始偏离预期?在边界处加日志或断言,而不是通读一切。
14
+ 4. 提出一个假设,用最小的改动验证它,然后才写修复。
15
+ 5. 再次运行复现;必须通过。保留反向检查:把修复撤掉,回归测试要失败。然后 `keelson check --record`。
16
+
17
+ 如果连续三个假设都失败,停下来从头重读问题;你很可能在错误的层。
18
+
19
+ ## 命名根因
20
+ <!-- keelson: id=debug.category | without: bug 一个一个修,背后的模式永远看不见 | sunset: never -->
21
+
22
+ 追加到当前 change 的 ledger(或为这次修复创建一个 quick change):
23
+
24
+ ```markdown
25
+ ### Root cause: implicit-assumption
26
+ Callback handler assumed exactly one delivery; broker guarantees at-least-once.
27
+ Fix: idempotency key on `notify`. Prevention: rule in `rules/services.md`.
28
+ ```
29
+
30
+ 分类,每条一个:
31
+
32
+ | 分类 | 含义 |
33
+ |---|---|
34
+ | `missing-rule` | 没有约定说明该怎么做 |
35
+ | `cross-layer` | 两层之间的契约不清楚 |
36
+ | `propagation` | 改了一处,漏了依赖它的地方 |
37
+ | `test-gap` | 单元通过,集成失败 |
38
+ | `implicit-assumption` | 代码依赖了没写下来的东西 |
39
+ | `guessed-fix` | 之前的修复处理的是症状,不是原因 |
40
+
41
+ 分类是 `missing-rule` 或 `cross-layer` 时,提出本可以预防它的 rule 或 spec 需求,并趁上下文新鲜时加上。
42
+
43
+ <!-- guided -->
44
+ ## 修复方式不明显时
45
+ 问问最近改了什么(对失败区域 `git log -p`)、数据长什么样、失败是在你的代码里还是在对某个依赖的假设里。这三者是不同的层;先选层,再找行。
46
+ <!-- /guided -->
@@ -0,0 +1,78 @@
1
+ # 风险触发式设计镜头
2
+
3
+ 这些是 **Agent 内部工程镜头,不是架构问卷**。只启用当前变更真正触发的镜头。先读仓库和已有契约,再把发现路由成默认值、实验、验收、检查或一个真正属于所有者的决定。
4
+
5
+
6
+ 界面工作按需加载 `frontend.md`;视觉与交互验收遵循 `frontend-review.md` 和 `frontend-delivery.md`。
7
+
8
+ ## 触发、检查、路由
9
+ <!-- keelson: id=lenses.triggered | without: 每个功能都被迫走巨型清单,而真正重要的跨领域风险仍可能因为机械打勾而漏掉 | sunset: never -->
10
+
11
+ | 镜头 | 常见触发 | 提问前先检查 | 优先沉淀为 |
12
+ |---|---|---|---|
13
+ | 用户 + 领域 | 新流程、含糊名词、多角色 | actor/job、现有流程、共享语言、所有权边界 | 场景/非目标;术语真重要时才进 glossary |
14
+ | 数据 + 完整性 | 持久化、schema、导入导出、删除、金额 | 真源、不变量、生命周期、保留、迁移、审计/对账 | requirement + 迁移/回滚/对账证据 |
15
+ | 安全 + 隐私 | 登录、权限、secret、PII、上传、不可信输入/工具 | 资产、信任边界、最小权限、滥用途径、验证 | 负向 acceptance + 安全检查 |
16
+ | 并发 + 异步 | queue、webhook、worker、实时、多写者 | 重复、顺序、幂等、重试、超时、取消、部分失败 | 重复/乱序/重试/故障测试 |
17
+ | API + 兼容性 | 公共 API、event/schema/config/存储格式 | 消费方、版本、breaking 定义、弃用、rollout/rollback | 兼容契约 + rollout 证据 |
18
+ | 可靠性 + 运维 | 错误处理、清理/资源生命周期、关键路径、后台任务、外部依赖 | 完整失败路径、恢复、观察者所见状态、可观测性、安全降级 | 对抗性回归 + 恢复检查;适用时附运维指针 |
19
+ | 性能 + 成本 | 明确延迟/吞吐/数据量/成本目标、测出的热点 | workload、SLO、基线、增长假设、资源上限 | 实测/load/cost 检查;不凭想象加缓存 |
20
+ | 界面 + 可访问性 | UI、表单、导航、交互流程 | 主任务、错误/恢复、键盘/focus、理解成本、破坏性操作 | usability/accessibility acceptance |
21
+ | AI + 非确定性 | LLM、Agent、RAG、模型/工具调用 | eval case、fallback、数据边界、prompt/tool injection、授权、可复现性 | eval 集 + 安全/fallback acceptance |
22
+
23
+ 触发某个镜头只意味着“检查这个维度”,**绝不意味着把这一行所有问题都问给用户**。
24
+
25
+ ## 修复前先把失败契约变成可执行测试
26
+ <!-- keelson: id=lenses.failure-contract | without: 错误处理修复只覆盖最早的失败,后续 finalizer 或观察者仍可能丢失异常或看到损坏的状态 | sunset: never -->
27
+
28
+ 涉及错误处理或资源生命周期时,编辑前先追踪完整调用路径,包括嵌套清理、finalizer、通知和最终调用方。在现有计划或测试笔记中简短记录各阶段:哪里可能失败、哪些动作仍须执行、观察者应看到什么状态、哪些异常必须到达调用方。从请求和已有契约推导这些义务;区分明确需求与额外的鲁棒性探测。
29
+
30
+ 在实现**之前**,把风险最高的组合变成一个失败回归测试:在同一次执行的多个阶段注入不同异常,包含适用的最后一个观察者;系统支持时,使用嵌套或已经激活的资源。断言要求的最终状态,以及传播异常的身份、次数和契约要求的顺序;在观察者执行当时检查它所见的状态。单异常测试通过,不能证明多阶段同时失败的契约成立。只覆盖受影响的生命周期,不为此发明通用框架或穷尽式故障矩阵。
31
+
32
+ ## 优先简单、可逆的架构
33
+ <!-- keelson: id=lenses.simplicity | without: Agent 会为假想规模提前设计、在压力尚不存在时增加抽象,或者把所有未来可能性都当成今天的需求 | sunset: never -->
34
+
35
+ 使用能满足当前契约、并保留可信演进路径的最简单设计。新增 service、queue、cache、抽象层、数据库、框架或协议之前,先说清楚**现在**到底是哪一个具体压力需要它。
36
+
37
+ 未来规模/功能只是 hypothesis,不是 requirement。能低成本验证的就做 spike/实测;以后能局部修改的就优先采用可逆方案继续推进。优先“深模块 + 窄接口”,不要为了形式漂亮堆很多只镜像实现的浅包装。
38
+
39
+ ## 把风险变成证据,而不是散文
40
+ <!-- keelson: id=lenses.evidence | without: 设计评审留下大量看起来很完整的文档,但代码变化后关键性质没有真正受到保护 | sunset: never -->
41
+
42
+ 每个触发镜头最终必须落成以下一种或几种:
43
+
44
+ - **已有保证**:已有 spec/rule/test 已覆盖 → 直接复用;
45
+ - **所有者决定** → 在 decision frontier 只问那个问题;
46
+ - **工程默认值** → 自行决定;只有未来工作需要理由时才记录;
47
+ - **低成本未知** → spike、原型、实测 或查看 telemetry;
48
+ - **稳定不变量** → 窄作用域 rule,能自动化时优先 fitness/check;
49
+ - **验收/证据义务** → 加入对应的故障/兼容/安全/性能/迁移/可访问性场景;
50
+ - **明确不在范围内** → 只有省略会像遗漏时才点名一次。
51
+
52
+ 不要因此创建一份通用 NFR 文档或架构检查清单。
53
+
54
+ ## 用 Fitness Function 保护架构
55
+ <!-- keelson: id=lenses.fitness | without: 架构质量依赖评审者记住文字规则,随着项目演进会逐渐腐化 | sunset: never -->
56
+
57
+ 长期架构性质只要能机械测量,就优先做成 `config.yaml → check`,不要反复靠散文提醒:
58
+
59
+ - 禁止的依赖方向;
60
+ - 公共 schema/API 兼容性;
61
+ - latency 或 bundle-size 上限;
62
+ - migration 可回滚检查;
63
+ - security/static-analysis 策略;
64
+ - accessibility 测试;
65
+ - 确定性的 contract/eval suite。
66
+
67
+ 文字只保留足够解释**为什么**存在这个 guard、适用于哪里。重复出现的 review comment 本身就是信号:应该用 fitness check 或更窄的 rule 替代散文。
68
+
69
+ ## 优先处理不可逆风险
70
+ <!-- keelson: id=lenses.priority | without: Agent 会围绕可逆的实现品味争论,却对数据损失、权限、兼容、迁移或故障语义默默猜测 | sunset: never -->
71
+
72
+ 大致按这个顺序解决:
73
+
74
+ **不可逆数据/安全/生产副作用 → 对外兼容/迁移/昂贵长期承诺 → 故障/并发正确性 → 用户可见行为/可访问性 → 有测量依据的可靠性/性能/成本 → 可逆实现偏好**
75
+
76
+ 安全内部使用紧凑循环:**保护什么 → 可能怎么出错 → 什么控制负责预防/检测 → 什么证据证明控制有效**。
77
+
78
+ 性能和规模先测量再加机制。分布式/异步场景默认考虑重试与部分失败,除非 transport contract 明确证明不会发生。破坏性行为必须把恢复/回滚说清楚。
@@ -0,0 +1,70 @@
1
+ # 发现真正想要的是什么
2
+
3
+ 用户往往没法在第一句话里把完整需求说清楚,也不应该先学会哪些工程选型重要。发现阶段要在任何人挑数据库之前,先找到请求背后的问题。属于所有者的不确定性按 `interview.md` 处理;只有工作真实触发跨领域风险时才读 `design-lenses.md`。
4
+
5
+ ## 先谈场景,再谈技术
6
+ <!-- keelson: id=discover.scenario-first | without: 第一个问题就是负责人答不上来的技术选型,产品被他们的猜测塑形 | sunset: never -->
7
+
8
+ 当请求是一个产品想法("做一个团队知识库"、"加上协作")时,不要问存储、框架或表结构。先问哪种用法处在中心,给出的备选要在"用户会做什么"上真正不同:
9
+
10
+ > 下面哪一种最接近大家用它做的第一件事?
11
+ > A. 几个人编辑同一批文档。
12
+ > B. 把公司资料收集起来,用来搜索。
13
+ > C. 把资料交给一个助手,由它回答问题。
14
+ > D. 最终都要;第一版应该先选一个。
15
+ > 第一版我建议只选一个:权限、搜索、助手、共同编辑各自都带来复杂度,叠在一起会把项目拖停。
16
+
17
+ 每个问题保持小:只解决一个具体决定,给足够理解它的场景,再给推荐默认值和最重要的一项取舍。选项只是工具,不是固定格式。负责人说“不知道”时按 `interview.md` 路由:自己调查、采用可逆默认值,或用最小示例/实验把后果变得可见。绝不把术语再重复一遍、说得更响。
18
+
19
+ ## 哪些未知该提出来
20
+ <!-- keelson: id=discover.frontier | without: 要么每个未知都变成问题、什么都开不了工,要么代理自己拍板了产品问题 | sunset: never -->
21
+
22
+ 提问之前先把每个未知归类:
23
+
24
+ | 未知 | 处理 |
25
+ |---|---|
26
+ | 能从代码、测试或文档里查到 | 自己读;绝不问 |
27
+ | 项目已有惯例 | 跟随惯例;在写回里提一句 |
28
+ | 低风险、容易撤销 | 自行决定,在你的授权范围内记为已确认 |
29
+ | 纯技术、负责人没有理由关心 | 选一个合理默认;用一行说明 |
30
+ | 改变产品对用户的行为 | 问,并附推荐 |
31
+ | 改变长期架构、成本或对外承诺 | 先解释,再确认 |
32
+ | 破坏数据、扩大权限、触及生产 | 永远明确确认 |
33
+
34
+ 只有答案会改变结果的问题才交给负责人。其余都是默认值,或是落地前会浮现出来的 `(assumed)` 决策。
35
+
36
+ ## 只在决策前沿提问
37
+ <!-- keelson: id=discover.decision-frontier | without: the agent either interrupts for facts it could investigate, invents user-owned intent, or asks low-value questions whose answers do not change the work | sunset: never -->
38
+
39
+ 提问前,先按“谁有能力解决这个缺口”来分类:
40
+
41
+ | 缺口 | 处理 |
42
+ |---|---|
43
+ | 仓库或上下文已经确定 | 直接使用,并在写回中指出依据 |
44
+ | 属于现实世界(代码行为、API 契约、实测、依赖能力) | 自己调查,或做一个小实验 |
45
+ | 属于用户且会阻塞结果(目标、范围、验收、风险容忍度、公开承诺) | 只问一个问题 |
46
+ | 不阻塞,或很容易撤销 | 按授权决定,或留给后续切片 |
47
+ | 证据已经耗尽 | 标为 UNKNOWN;不要把不确定性改写成用户的观点 |
48
+
49
+ 选择“实际信息价值”最高的缺口:哪个答案最可能改变下一个切片,再结合猜错它的代价。提问前先走 `interview.md` 的 Question Protocol。得到答案后更新写回,再重新判断决策前沿。“只问一个问题”只用于**真正阻塞工作的不确定性**,不是仪式:没有由用户掌握的关键缺口时,一个问题都不要问,直接推进。
50
+
51
+ ## 范围守卫
52
+ <!-- keelson: id=discover.scope-guard | without: 第一个请求就同时要五个独立领域,集成风险、调试成本和需求变动叠加放大 | sunset: never -->
53
+
54
+ 当一个请求捆着好几个领域(身份、支付、实时协作、助手、插件、移动端),把它们点名为独立领域并提出顺序:其他领域都依赖的那个先做,其余作为后续里程碑写进 `ROADMAP.md → Next`。理由不是代码写不出来,而是每多一个领域,前面那些出错的方式就成倍增加,而此时还什么都没验证过。用大白话把这一点说出来。
55
+
56
+ ## 先探索,再承诺
57
+ <!-- keelson: id=discover.explore | without: 一个便宜的实验就能用证据解决的问题,却被逼成了抽象决策 | sunset: never -->
58
+
59
+ 当选择可逆而负责人拿不准时,不要催着做决定。提供一个 spike、原型、mock 或 实测,规模刚好回答一个问题:两个小 UI 变体供挑选;加缓存之前先 实测;采用某个库之前先 spike。把结果作为证据记进 ledger(`### Note:`),把它产生的决策记到 `## Decisions` 下。
60
+
61
+ ## 引导模式只增加教学,不负责“能不能看懂”
62
+ <!-- keelson: id=discover.guided | without: 易懂的提问被错误地锁在新手开关后面,或者教学内容变成永久项目仪式 | sunset: never -->
63
+
64
+ 场景优先、合理默认值和可理解的问题永远开启。`guide: true` 只额外增加教学:
65
+
66
+ - 大白话决定理解以后,简短补上对应工程概念;
67
+ - 应用 rule/constraint 时解释一句为什么;
68
+ - spec change land 后补一个短教学说明:关键决定、原因、工程思想、何时应重新考虑。
69
+
70
+ 教学说明只留在对话里。引导模式不改变工件、gate,也不改变谁拥有某个决定。
@@ -0,0 +1,110 @@
1
+ # 工程决策方法
2
+
3
+ 当一个技术选择并不显然、撤销成本高,或者它依赖“性能更好、可靠性更高、可扩展、成本更低、可维护性更强”等主张时,读取本文件。这里是一套**做选择的方法**,不是又一张清单。`model.md` 负责领域语言和边界,`design-lenses.md` 负责指出哪类风险值得看,本文件负责说明如何推理、如何取得证据。
4
+
5
+ ## 从第一性问题出发,而不是从既有解法出发
6
+ <!-- keelson: id=engineer.first-principles | without: 用户点名的技术或已有惯例被误当成需求本身,设计开始优化某个机制而不是最终结果 | sunset: never -->
7
+
8
+ 选 pattern 或产品之前,把问题还原成六类信息:
9
+
10
+ 1. **已观察事实** —— 代码、测试、telemetry、文档或用户真实建立了什么事实。
11
+ 2. **结果** —— 这次变更最终必须产生什么可观察结果。
12
+ 3. **硬约束** —— 兼容、法规、授权、预算、平台、期限。
13
+ 4. **不变量** —— 即使实现换掉也必须一直成立的东西。
14
+ 5. **假设** —— 目前相信、但还没有证据的判断。
15
+ 6. **机制** —— cache、queue、service、database、framework、pattern、模型阶段、抽象层。
16
+
17
+ 机制是 hypothesis,不是 requirement。把技术名删掉再问:**如果不存在这个机制,到底哪条性质会失败?** 现有架构是重要证据,也经常构成兼容性约束;但“以前一直这么做”本身不能成为继续复制偶然复杂度的理由。
18
+
19
+ 优先选择能保留结果、约束和不变量的最小问题定义。当前契约或测量趋势没有要求时,不提前替未来更大的问题设计。
20
+
21
+ ## 增加机制之前,先写出可证伪的主张
22
+ <!-- keelson: id=engineer.hypothesis | without: 架构只用“更快”“更安全”“更可扩展”等形容词解释,最后无法区分有效改进与偶然结果 | sunset: never -->
23
+
24
+ 对于真正重要且不确定的选择,先用紧凑格式写工程主张:
25
+
26
+ ```text
27
+ Hypothesis: 机制 X 在条件 Z 下改善/保护响应 Y。
28
+ Baseline: 当前方案或更简单的方案 B。
29
+ Measure: M。
30
+ Decision threshold: T。
31
+ Budget: 足以区分方案的最小实验。
32
+ ```
33
+
34
+ 例如:“cache 在 500 rps 下把列表 p95 保持在 200 ms 内”;“idempotency key 在 at-least-once 重试时阻止重复扣款”;“第二个 Agent 的独立 review 能发现实现者自己遗漏的 requirement gap”。
35
+
36
+ 如果主张不能直接量化,就找最强的可观察 proxy 或结构性证据;两者都没有时,把它当作所有者取舍或可逆默认值,而不是已被证明的工程事实。
37
+
38
+ ## 用最便宜、但足以改变决定的实验
39
+ <!-- keelson: id=engineer.experiment | without: 本可用一个薄端到端切片、spike、实测 或故障注入解决的问题,被长时间停留在直觉争论里 | sunset: never -->
40
+
41
+ 选择能区分方案的最低成本探针:
42
+
43
+ - **Tracer bullet** —— 先让一个真实用户动作端到端穿过所有必要层。
44
+ - **Spike / prototype** —— 用完即弃,用来学习 API、集成、UI 交互或迁移限制。
45
+ - **实测 / load test** —— 用代表性 workload 检验性能或成本主张。
46
+ - **Failure injection** —— timeout、retry、duplicate、crash、依赖丢失、partial failure。
47
+ - **Ablation / counterfactual** —— 去掉或简化某个机制,看它宣称的收益是否一起消失。
48
+
49
+ 实验事实进 ledger;只有由实验产生的长期决定进入长期知识。Prototype 跑通过一次,并不等于那份 prototype code 就应该直接进生产。
50
+
51
+ ## 消融用于归因,不用于走形式
52
+ <!-- keelson: id=engineer.ablation | without: 完整系统一旦通过,里面新增的每个组件都会永久留下,即使从未证明过它真的贡献了任何东西 | sunset: never -->
53
+
54
+ 当一个机制声称值得它带来的复杂度时,把它和更简单的 baseline 比较:
55
+
56
+ 1. 尽可能保持 workload、环境、配置、数据集和 random seed 一致。
57
+ 2. 测 baseline。
58
+ 3. disable、remove 或 simplify 这个机制。
59
+ 4. 测同一响应。
60
+ 5. 用**实验前就确定**的 threshold 比较差异。
61
+
62
+ 效果可以忽略时,这个机制还没有赚到它的复杂度;删除它,或者把结论标成 inconclusive。结果有噪声就重复,不挑最好看的一次。
63
+
64
+ 一次只改一个因素的 ablation 会漏掉交互效应。如果 X 只有在 Y 存在时才有作用,就用最小的组合矩阵(很多时候 2×2 已经够)而不是根据孤立移除直接下结论。目标是取得足以支撑工程决定的因果信息,不是做统计表演。
65
+
66
+ ## 只有“以后很难改”时才升级成架构问题
67
+ <!-- keelson: id=engineer.architecture | without: 每个代码组织选择都被叫作“架构”,真正昂贵的边界反而没有显式比较取舍 | sunset: never -->
68
+
69
+ 当决定范围广或撤销昂贵时才把它当 architecture:data ownership/schema、public contract、trust boundary、deployment/service boundary、concurrency model、durable storage、外部平台依赖,或者会被大量后续变更继承的运行拓扑。
70
+
71
+ 存在真正的架构分叉时:
72
+
73
+ - 把相关 **quality-attribute scenario** 写成:stimulus → environment → expected response → measurable response。
74
+ - 选定前画**两个可信设计**。只有真实 fork 才这样做,不为了填模板硬造第二个方案。
75
+ - 按当前需要比较:复杂度、可修改性、可靠性、安全、性能/成本、可测试性、迁移/回滚、运维、blast radius、可逆性。
76
+ - 选择满足当前测量/需求、同时保留可信演进路径的最简单方案。
77
+ - 决定跨领域且以后很贵时,如果项目配置了 `refs.decisions`,写一个短 ADR:context、decision、consequences,以及**什么时候应该重审**。
78
+ - 可以度量的架构特征变成 `fitness` check。
79
+
80
+ 架构不是图画了多少张、pattern 用了多少个;架构是会塑造后续变化成本的关键边界和取舍。保持 **conceptual integrity**:宁要少量一致的概念和边界,也不要每个局部都很聪明、结果每加一个功能就得再学一套心智模型。
81
+
82
+ ## 让变化尽量局部
83
+ <!-- keelson: id=engineer.structure | without: 接口直接镜像 framework/database,调用方知道太多实现细节,一个小产品改动会扩散到很多无关模块 | sunset: never -->
84
+
85
+ - **隐藏复杂度。** 宁要小接口 + 深实现,不要很多暴露内部细节的薄 wrapper。调用方需要知道得越少越好。
86
+ - **让 policy 远离易变 detail。** 当真实边界能降低替换/测试成本时,不让 domain/use-case 直接依赖 framework、transport、database 或 vendor-specific shape。
87
+ - **一起变化的东西尽量放在一起。** 一个功能反复需要改五个目录,是边界有问题的证据。
88
+ - **边界跟着领域走。** 同一个词在两个区域含义或不变量不同,就用 `model.md` 明确 bounded context 与翻译关系。
89
+ - **Pattern 是共同词汇,不是目标。** 问题已经长成某个 pattern 的形状时才给它命名。
90
+ - **新基础设施必须说明当前压力。** 新 queue、cache、service、datastore、framework、protocol 或 abstraction 必须能指向当前约束、测量结果或 failure mode。
91
+
92
+ ## 安全地演进现有系统
93
+ <!-- keelson: id=engineer.evolution | without: 没人真正理解的旧行为被一次性重写,回归要等切换后才发现,现代化风险集中到一次发布 | sunset: never -->
94
+
95
+ 面对已有/legacy code,按 **characterize → 找 seam → 小步 behavior-preserving refactor → verify → 再改行为**。Refactoring 本身不是行为修改,而是为后续行为修改创造更安全的形状。
96
+
97
+ 无法一次安全替换时,优先 parallel change / branch by abstraction 或增量 strangler:新旧实现先在受控边界后共存,traffic/data/caller 再逐步迁移。风险高时明确 rollback 或 reverse migration。
98
+
99
+ 绿地集成先用一条薄 tracer bullet 证明完整路径,再横向铺开。除非所有者接受 cutover 风险,并且有证据表明增量迁移显著更差,否则不要默认 big-bang rewrite。
100
+
101
+ **Second-system 检查:** 旧系统很痛苦,不代表重写时可以把多年积压的 feature、abstraction、platform 想法一次全塞进去。替换范围仍然只服务当前 outcome;与验收无关的 wishlist 拆成独立 change。
102
+
103
+ ## 把长期质量变成可执行约束
104
+ <!-- keelson: id=engineer.fitness | without: 架构质量只能依靠 reviewer 记住散文,导致同一约束被一遍遍重新发现、重新违反 | sunset: never -->
105
+
106
+ “快”“可靠”“安全”“可扩展”都不是可执行 requirement。给它范围和响应指标,写入 spec;当命令能测时,加入 `config.yaml → check`,`kind: fitness`。
107
+
108
+ Fitness check 保护的是**重要性质**,不是某个喜欢的实现形状。某条 dependency-direction check 在它保护稳定 policy 时可能合理;“系统必须分五层”则不是有价值的 fitness function,除非五层本身就是需求。
109
+
110
+ 同一种 review comment 反复出现,是信号:要么设计该继续简化,要么那条 invariant 应该自动化。
@@ -0,0 +1,38 @@
1
+ # 前端交付与迭代
2
+
3
+ 让响应式、性能和视觉验证始终对应同一条真实用户路径。
4
+
5
+ ## 适应真实条件
6
+ <!-- keelson: id=frontend-delivery.adaptation | without: 一张固定截图掩盖溢出和移动端不可达控件 | sunset: never -->
7
+
8
+ 检查所需宽屏、窄屏和中间宽度,拖动尺寸找到内容实际失效的位置,据此选择断点,不只按设备名。保留有意义内容与阅读顺序,不在手机上隐藏难处理的部分。
9
+
10
+ 检查换行、滚动区、固定区域、触摸可达性与视口高度。表格可有意横向滚动,但需保留关系和滚动提示;页面意外溢出是缺陷。适用时测试缩放、横屏、移动键盘、指针与键盘输入,确保主操作和错误信息可达。在受影响布局复查真实长内容、空内容和密集内容。
11
+
12
+ ## 测量受影响路径
13
+ <!-- keelson: id=frontend-delivery.performance | without: 凭想象优化增加机制,却没有减少用户等待 | sunset: never -->
14
+
15
+ 优化前记录路径、设备/网络条件、测量方法与相关现有预算,定位主要来源:下载、字体、图像、渲染、事件处理、长列表或重复请求。使用已有工具,不为显得专业引入框架。
16
+
17
+ 采用有证据支持的最小改进,例如设置尺寸的适当图像、延后非关键资源、减少重复工作或拆分实测较重路径。在可比条件重测,并确认正确性与交互质量。不把一次开发机样本当通用提升,也不牺牲可访问内容换数字。
18
+
19
+ ## 提取并记录稳定约定
20
+ <!-- keelson: id=frontend-delivery.system | without: 一次性抽象不断增殖,文档设计偏离代码 | sunset: never -->
21
+
22
+ extract 先寻找真实重复用法与行为差异,按当前技术栈、命名和所有权边界整合稳定语义 token 与组件。保留公共 props、响应式、可访问性和异常状态,先迁移代表性调用并验证再扩展。不抽象单次使用,不构建带几十个无关开关的万能组件。
23
+
24
+ document 检查真实 CSS/主题文件与代表性组件,在已有文档记录 token 角色、字体、间距、布局、状态、可访问模式与示例;链接代码,不复制全部实现。区分建议与已观察约定,实施后同步文档,只保留后续需要的决策。
25
+
26
+ ## 有依据地探索与迭代
27
+ <!-- keelson: id=frontend-delivery.iteration | without: 变体仅换颜色,迭代没有基于任务的选择依据 | sunset: never -->
28
+
29
+ explore 只在不确定性值得时,用相同真实内容和任务比较少量构图或交互明显不同的方案,说明各自改进与代价。根据问题选择代码原型或图像工具,不把图片当可用软件。已有授权内实施选定方向,只有尚未解决且属于所有者的选择才提问。
30
+
31
+ iterate 查看实际渲染界面,提出一个高影响假设,修改一个完整区域,重载并对照;可行时保留应用状态,检查相邻状态。达到验收后停止,不追逐无限装饰变体。临时分支、原型和生成素材属于本任务工件;保留选定交付与必要证据,只删除本次创建且可丢弃的产物。
32
+
33
+ ## 完成浏览器闭环
34
+ <!-- keelson: id=frontend-delivery.browser | without: 代码通过检查,浏览器才显现的视觉和交互问题仍被交付 | sunset: never -->
35
+
36
+ 发生界面修改或需要视觉/交互结论时,使用宿主浏览器工具或项目已有浏览器测试打开运行中的应用。确认目标路由与资源真实加载,亲自查看截图,执行主操作及相关恢复,检查关联控制台/网络错误。保留路由、视口、代表性数据、步骤、结果,以及足够复现的截图或测试记录。
37
+
38
+ 修复后重载并重复受影响场景,旧图片不能证明新状态。视觉观察、交互执行和自动检查是不同证据,按现有验证流程记录,不能把打印指导当检查结果。工具或服务不可用时继续独立检查,明确未验证场景与具体补验步骤,不能标记浏览器验收通过。交付时删除可丢弃任务产物,保留审阅需要的证据。
@@ -0,0 +1,31 @@
1
+ # 交互与内容
2
+
3
+ 从真实用户路径与数据生命周期出发,覆盖实际存在的状态,不虚构无关功能。
4
+
5
+ ## 定义状态与恢复
6
+ <!-- keelson: id=frontend-interaction.states | without: 理想路径可用,但失败丢失输入或显示虚假成功 | sunset: never -->
7
+
8
+ 对受影响控件或区域确定适用的初始、加载、空态、部分结果、成功、错误、禁用与只读状态,明确各状态可用动作及转换条件。区分权限不足与临时失败,也区分无内容与筛选无结果。
9
+
10
+ 保存反馈依据真实请求结果。提交中防止重复副作用,保留可恢复输入,并沿用项目方式处理迟到或乱序响应。重试、取消和返回不得静默丢失工作;相关时模拟慢速、离线、失败和中断。没有恢复契约就不伪装乐观成功。错误文案说明问题、影响和可行下一步,诊断不得暴露秘密。
11
+
12
+ ## 让控件可操作
13
+ <!-- keelson: id=frontend-interaction.controls | without: 鼠标演示通过,键盘、触摸或辅助使用却失败 | sunset: never -->
14
+
15
+ 优先使用语义正确的原生元素和成熟项目组件。控件有明确可访问名称,输入有关联持久标签,帮助和错误能对应字段;占位符不是标签。必要动作不能只依赖悬浮或颜色。
16
+
17
+ 实际检查 Tab 顺序、可见焦点、键盘提交和相关弹层。模态打开与关闭需正确管理焦点,隐藏控件不能继续参与交互。验证保留输入并帮助定位错误字段;沿项目方式让动态反馈可供辅助技术访问。破坏性动作按真实后果提供确认或恢复;普通操作无需增加权限弹窗。
18
+
19
+ ## 理清文案与首次使用
20
+ <!-- keelson: id=frontend-interaction.content | without: 用户不知道控件含义或如何得到有用结果 | sunset: never -->
21
+
22
+ 按钮用动作动词,标题帮助定位,辅助文本只解释必要约束。使用产品术语,避免内部实现词汇。把模糊失败提示改为具体恢复方式;动作不可用而原因不明显时解释原因。
23
+
24
+ onboard 从首个有用任务开始。空态区分尚未创建、无搜索结果、无权限与加载失败,并提供正确下一步。需要时再教学,非必要引导可跳过,不默认增加强制导览或欢迎弹窗。示例保留用户数据,不暗示示例内容来自真实客户。
25
+
26
+ ## 施加内容与语言压力
27
+ <!-- keelson: id=frontend-interaction.locale | without: 翻译与真实值破坏布局或改变含义 | sunset: never -->
28
+
29
+ 沿用项目本地化机制,不用碎片拼接待翻译句子。按支持范围检查较长译文、混合文字、复数、数字/日期/时区格式与文字方向;需要双向文字支持时优先使用逻辑布局属性。
30
+
31
+ 检验长名称、长错误、缺失值、大数值和不能自然换行的内容。语言切换与资源失败时保留任务上下文,不因为样例短就任意限制输入。说明实际检查的语言与方向,不能仅凭源码宣称覆盖。
@@ -0,0 +1,33 @@
1
+ # 前端审查与打磨
2
+
3
+ audit 寻找可观察缺陷;critique 评审任务理解与设计选择;polish 修复范围内的不一致并验证结果。
4
+
5
+ ## 观察运行中的界面
6
+ <!-- keelson: id=frontend-review.observe | without: 源码检查被误认为已查看真实界面 | sunset: never -->
7
+
8
+ 按项目正常方式启动应用。记录路由、视口、内容与状态,打开页面并亲自查看截图,再形成视觉判断。走通主要路径,检查相关键盘和窄屏路径,观察第一视觉焦点、下一步是否清楚、反馈与恢复是否真实。
9
+
10
+ 审查 audit 时检查语义、名称与标签、键盘与焦点、对比度、状态恢复、响应式及相关运行问题;评审 critique 时解释层级、分组、信息顺序、密度、品牌表达如何影响任务。区分观察、假设和审美建议。仅要求审查时输出发现,不静默修改文件。
11
+
12
+ 截图只证明一个渲染状态,不证明交互可用。截图成功不等于已审阅图片。自动扫描只能识别部分问题,仍需人工键盘、视觉与任务检查。不要为凑清单编造问题。
13
+
14
+ ## 让发现能被执行
15
+ <!-- keelson: id=frontend-review.findings | without: 主观形容词没有对应可复现问题与修复优先级 | sunset: never -->
16
+
17
+ 每条重要发现写明位置与触发条件、观察到的行为、用户影响、证据及最小有效修复。先解决任务阻塞、工作丢失和状态误导,再处理可操作性、理解、层级与一致性,最后处理装饰。没有明确依据就不打分。
18
+
19
+ 例如:“保存失败后按钮仍显示已保存,用户可能带着未保存修改离开。让反馈取决于服务端结果,保留输入并提供重试。”具体前后场景比“更直观”有用。
20
+
21
+ ## 在范围内打磨
22
+ <!-- keelson: id=frontend-review.finish | without: 收尾变成重设计,或用装饰掩盖未解决缺陷 | sunset: never -->
23
+
24
+ 任务可用后,检查对齐、间距节奏、文字角色、图标大小与基线、控件高度、语义颜色、悬浮/焦点/按下/禁用状态和内容一致性。使用已有 token,移除偶发特例,保留有意差异。先解决截断、加载跳动和模糊错误,再做微装饰。
25
+
26
+ 检查真实最密和最空内容,不只看理想样例。局部授权保持局部改动;共享 token 变化后复查关联状态和组件。
27
+
28
+ ## 在同一场景复查
29
+ <!-- keelson: id=frontend-review.acceptance | without: 构建通过被报告为视觉验收通过 | sunset: never -->
30
+
31
+ 修改后使用原路由、视口、数据与状态复查。视觉改动查看前后渲染图片,行为改动实际执行操作,用现有自动化保护稳定契约。证据必须在最后一次相关编辑之后取得。
32
+
33
+ 分别报告视觉观察、执行的交互、自动检查和未验证范围。浏览器或必要服务不可用时,列出受阻场景,明确写浏览器视觉/交互未验证,继续独立工作;不能将证据缺失改写为通过,也不能降低验收让门禁变绿。
@@ -0,0 +1,31 @@
1
+ # 视觉设计
2
+
3
+ 根据产品、内容与任务选择表达。已有设计决策优先于通用风格偏好。
4
+
5
+ ## 先构图,再装饰
6
+ <!-- keelson: id=frontend-visual.hierarchy | without: 所有元素争抢注意力,重复容器掩盖信息关系 | sunset: never -->
7
+
8
+ 先排序内容重要性,再决定大小、位置、对齐、间距与容器。相关信息靠近,独立主题分开;主操作容易找到,不给每个操作同等强调。密集业务工具与阅读页面需要不同节奏。
9
+
10
+ layout 建立清晰阅读顺序、一致对齐与少量间距尺度,用真实宽窄内容检验。simplify 减少重复标签、嵌套装饰和无谓选择,保留必要信息与可发现性。bolder 通过比例、对比、构图或图像强化一个有意义焦点;quieter 减少争抢强调与装饰,保留层级和品牌。不默认所有内容套卡片,也不默认首屏都是居中标题加徽章。
11
+
12
+ ## 用真实内容排版
13
+ <!-- keelson: id=frontend-visual.typography | without: 示例标题精致,但正文与多语言数据不可读 | sunset: never -->
14
+
15
+ 复用项目字体,为标题、正文、标签、辅助文本和数据建立有限角色。一起调整字号、字重、行高与行长,不用放大所有文字代替层级。使用真实存在的字重,让回退字体在资源加载期间保持可读。
16
+
17
+ 检查长标题、较长按钮、混合文字、数字列、缺失字形与字体加载跳动。数字对齐要符合任务。必要内容必须能理解,截断需有可用的完整内容入口;避免固定高度在缩放时裁剪文字。只加载需要的字体资源,遵守项目交付约束。
18
+
19
+ ## 让颜色与图像承担作用
20
+ <!-- keelson: id=frontend-visual.color | without: 装饰损害可读性、状态识别与产品真实性 | sunset: never -->
21
+
22
+ 为文本、背景、边界、交互、状态与强调使用语义 token。检查真实前景和背景组合,包括交互状态;错误、成功和选中不能只靠颜色。尊重品牌色,同时修正不可读组合。其他主题只在项目支持或用户要求时检查。
23
+
24
+ 图像应解释产品或内容。查看裁切、焦点、比例、清晰度、资源缺失与加载布局。装饰图像避免重复朗读,信息图像应有等价可访问说明。复用授权项目素材,合适且有工具时生成新素材。不编造客户、认证、评价或产品效果填充布局。
25
+
26
+ ## 让动效与细节服务任务
27
+ <!-- keelson: id=frontend-visual.motion | without: 动画拖延操作,减少动态效果后必要反馈消失 | sunset: never -->
28
+
29
+ 说明每个动画表达什么:反馈、空间连续性、进度或有意义的状态转换。保持可中断,并能应对快速重复输入;合适时采用利于合成的属性,不默认过渡所有属性。避免布局跳动、延迟显示必要内容和阻挡主要任务的效果。
30
+
31
+ 检查减少动态效果偏好、取消、快速切换和进入/退出路径。减少动效后仍需表达结果与错误。delight 只增加契合场景、回应真实进展的小细节,避免假进度、意外声音、强制庆祝或分散注意的循环。表现性效果在较弱设备条件下也需保留控件与阅读顺序。