@chinhae/atw-cli 0.5.0 → 0.7.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 (257) hide show
  1. package/README.md +128 -451
  2. package/dist/cli/index.d.ts.map +1 -1
  3. package/dist/cli/index.js +24 -1
  4. package/dist/cli/index.js.map +1 -1
  5. package/dist/commands/channel/adapters/claude.d.ts +44 -2
  6. package/dist/commands/channel/adapters/claude.d.ts.map +1 -1
  7. package/dist/commands/channel/adapters/claude.js +124 -23
  8. package/dist/commands/channel/adapters/claude.js.map +1 -1
  9. package/dist/commands/channel/adapters/codex.d.ts +36 -6
  10. package/dist/commands/channel/adapters/codex.d.ts.map +1 -1
  11. package/dist/commands/channel/adapters/codex.js +150 -10
  12. package/dist/commands/channel/adapters/codex.js.map +1 -1
  13. package/dist/commands/channel/adapters/index.d.ts +33 -4
  14. package/dist/commands/channel/adapters/index.d.ts.map +1 -1
  15. package/dist/commands/channel/adapters/index.js +159 -6
  16. package/dist/commands/channel/adapters/index.js.map +1 -1
  17. package/dist/commands/channel/adapters/omp.d.ts +106 -0
  18. package/dist/commands/channel/adapters/omp.d.ts.map +1 -0
  19. package/dist/commands/channel/adapters/omp.js +405 -0
  20. package/dist/commands/channel/adapters/omp.js.map +1 -0
  21. package/dist/commands/channel/adapters/pi.d.ts +123 -0
  22. package/dist/commands/channel/adapters/pi.d.ts.map +1 -0
  23. package/dist/commands/channel/adapters/pi.js +387 -0
  24. package/dist/commands/channel/adapters/pi.js.map +1 -0
  25. package/dist/commands/channel/adapters/types.d.ts +16 -0
  26. package/dist/commands/channel/adapters/types.d.ts.map +1 -1
  27. package/dist/commands/channel/agent-loader.d.ts +1 -0
  28. package/dist/commands/channel/agent-loader.d.ts.map +1 -1
  29. package/dist/commands/channel/agent-loader.js +45 -5
  30. package/dist/commands/channel/agent-loader.js.map +1 -1
  31. package/dist/commands/channel/dev-parse-trace.d.ts +1 -1
  32. package/dist/commands/channel/dev-parse-trace.d.ts.map +1 -1
  33. package/dist/commands/channel/dev-parse-trace.js +25 -2
  34. package/dist/commands/channel/dev-parse-trace.js.map +1 -1
  35. package/dist/commands/channel/index.d.ts.map +1 -1
  36. package/dist/commands/channel/index.js +44 -12
  37. package/dist/commands/channel/index.js.map +1 -1
  38. package/dist/commands/channel/run.d.ts +39 -2
  39. package/dist/commands/channel/run.d.ts.map +1 -1
  40. package/dist/commands/channel/run.js +227 -68
  41. package/dist/commands/channel/run.js.map +1 -1
  42. package/dist/commands/channel/spawn.d.ts +7 -2
  43. package/dist/commands/channel/spawn.d.ts.map +1 -1
  44. package/dist/commands/channel/spawn.js +35 -1
  45. package/dist/commands/channel/spawn.js.map +1 -1
  46. package/dist/commands/channel/store/events.d.ts +2 -2
  47. package/dist/commands/channel/store/events.d.ts.map +1 -1
  48. package/dist/commands/channel/store/events.js +1 -1
  49. package/dist/commands/channel/store/events.js.map +1 -1
  50. package/dist/commands/channel/supervisor/shutdown.d.ts +2 -0
  51. package/dist/commands/channel/supervisor/shutdown.d.ts.map +1 -1
  52. package/dist/commands/channel/supervisor/shutdown.js +6 -1
  53. package/dist/commands/channel/supervisor/shutdown.js.map +1 -1
  54. package/dist/commands/channel/supervisor.d.ts +2 -2
  55. package/dist/commands/channel/supervisor.d.ts.map +1 -1
  56. package/dist/commands/channel/supervisor.js +26 -3
  57. package/dist/commands/channel/supervisor.js.map +1 -1
  58. package/dist/commands/init.d.ts.map +1 -1
  59. package/dist/commands/init.js +6 -1
  60. package/dist/commands/init.js.map +1 -1
  61. package/dist/commands/mem.d.ts +2 -1
  62. package/dist/commands/mem.d.ts.map +1 -1
  63. package/dist/commands/mem.js +162 -13
  64. package/dist/commands/mem.js.map +1 -1
  65. package/dist/commands/mode.d.ts.map +1 -1
  66. package/dist/commands/mode.js +5 -3
  67. package/dist/commands/mode.js.map +1 -1
  68. package/dist/commands/uninstall.d.ts +5 -3
  69. package/dist/commands/uninstall.d.ts.map +1 -1
  70. package/dist/commands/uninstall.js +40 -16
  71. package/dist/commands/uninstall.js.map +1 -1
  72. package/dist/commands/update.d.ts +34 -0
  73. package/dist/commands/update.d.ts.map +1 -1
  74. package/dist/commands/update.js +209 -11
  75. package/dist/commands/update.js.map +1 -1
  76. package/dist/commands/verify.d.ts +18 -0
  77. package/dist/commands/verify.d.ts.map +1 -0
  78. package/dist/commands/verify.js +75 -0
  79. package/dist/commands/verify.js.map +1 -0
  80. package/dist/configurators/index.d.ts.map +1 -1
  81. package/dist/configurators/index.js +3 -2
  82. package/dist/configurators/index.js.map +1 -1
  83. package/dist/configurators/omp.d.ts +22 -0
  84. package/dist/configurators/omp.d.ts.map +1 -1
  85. package/dist/configurators/omp.js +101 -2
  86. package/dist/configurators/omp.js.map +1 -1
  87. package/dist/configurators/shared.d.ts.map +1 -1
  88. package/dist/configurators/shared.js +39 -7
  89. package/dist/configurators/shared.js.map +1 -1
  90. package/dist/configurators/workflow.d.ts.map +1 -1
  91. package/dist/configurators/workflow.js +5 -1
  92. package/dist/configurators/workflow.js.map +1 -1
  93. package/dist/constants/paths.d.ts +4 -0
  94. package/dist/constants/paths.d.ts.map +1 -1
  95. package/dist/constants/paths.js +4 -0
  96. package/dist/constants/paths.js.map +1 -1
  97. package/dist/migrations/manifests/0.6.0.json +442 -0
  98. package/dist/migrations/manifests/0.7.0.json +1378 -0
  99. package/dist/templates/atw/definition-of-done.md +65 -0
  100. package/dist/templates/atw/gitignore.txt +7 -0
  101. package/dist/templates/atw/index.d.ts +11 -0
  102. package/dist/templates/atw/index.d.ts.map +1 -1
  103. package/dist/templates/atw/index.js +22 -0
  104. package/dist/templates/atw/index.js.map +1 -1
  105. package/dist/templates/atw/scripts/common/active_task.py +2 -2
  106. package/dist/templates/atw/scripts/common/workflow_phase.py +33 -0
  107. package/dist/templates/atw/scripts/cross_model_review.py +3312 -0
  108. package/dist/templates/atw/scripts/decision_log.py +2002 -0
  109. package/dist/templates/atw/scripts/floor_guard.py +642 -0
  110. package/dist/templates/atw/scripts/task.py +25 -6
  111. package/dist/templates/atw/scripts/tickets.py +480 -10
  112. package/dist/templates/atw/workflow-general.md +6 -1
  113. package/dist/templates/atw/workflow.md +346 -26
  114. package/dist/templates/claude/settings.json +12 -0
  115. package/dist/templates/codex/hooks/session-start.py +2 -2
  116. package/dist/templates/common/bundled-skills/atw-askme/SKILL.md +1 -1
  117. package/dist/templates/common/bundled-skills/atw-askme-with-docs/SKILL.md +1 -1
  118. package/dist/templates/common/bundled-skills/atw-channel/SKILL.md +5 -2
  119. package/dist/templates/common/bundled-skills/atw-channel/references/command-reference.md +44 -5
  120. package/dist/templates/common/bundled-skills/atw-channel/references/progress-debugging.md +9 -0
  121. package/dist/templates/common/bundled-skills/atw-channel/references/workers.md +48 -4
  122. package/dist/templates/common/bundled-skills/atw-code-review/SKILL.md +78 -3
  123. package/dist/templates/common/bundled-skills/atw-codebase-design/SKILL.md +2 -2
  124. package/dist/templates/common/bundled-skills/atw-codebase-design/{DESIGN-IT-TWICE.md → design-it-twice.md} +3 -3
  125. package/dist/templates/common/bundled-skills/atw-cross-model-review/SKILL.md +361 -0
  126. package/dist/templates/common/bundled-skills/atw-cross-model-review/agents/openai.yaml +5 -0
  127. package/dist/templates/common/bundled-skills/atw-cross-model-review/references/four-tiers.md +42 -0
  128. package/dist/templates/common/bundled-skills/atw-cross-model-review/references/log-review-questions.md +38 -0
  129. package/dist/templates/common/bundled-skills/atw-cross-model-review/references/questions.md +54 -0
  130. package/dist/templates/common/bundled-skills/atw-cross-model-review/references/recheck-questions.md +42 -0
  131. package/dist/templates/common/bundled-skills/atw-cross-model-review/references/report-format.md +22 -0
  132. package/dist/templates/common/bundled-skills/atw-diagnosing-bugs/SKILL.md +13 -2
  133. package/dist/templates/common/bundled-skills/atw-domain-modeling/SKILL.md +2 -2
  134. package/dist/templates/common/bundled-skills/atw-handoff/SKILL.md +1 -1
  135. package/dist/templates/common/bundled-skills/atw-implement/SKILL.md +37 -1
  136. package/dist/templates/common/bundled-skills/atw-implement-all/SKILL.md +219 -24
  137. package/dist/templates/common/bundled-skills/atw-implement-spec/SKILL.md +237 -18
  138. package/dist/templates/common/bundled-skills/atw-improve-codebase-architecture/SKILL.md +2 -2
  139. package/dist/templates/common/bundled-skills/atw-init-repo/SKILL.md +1 -1
  140. package/dist/templates/common/bundled-skills/atw-init-repo/references/issue-tracker-atw-local.md +7 -1
  141. package/dist/templates/common/bundled-skills/atw-init-repo/references/issue-tracker-atw.md +7 -1
  142. package/dist/templates/common/bundled-skills/atw-map/SKILL.md +1 -1
  143. package/dist/templates/common/bundled-skills/atw-meta/SKILL.md +1 -1
  144. package/dist/templates/common/bundled-skills/atw-meta/references/customize-local/add-project-local-conventions.md +4 -3
  145. package/dist/templates/common/bundled-skills/atw-meta/references/customize-local/change-skills-or-commands.md +21 -16
  146. package/dist/templates/common/bundled-skills/atw-meta/references/customize-local/change-task-lifecycle.md +1 -1
  147. package/dist/templates/common/bundled-skills/atw-meta/references/customize-local/overview.md +1 -0
  148. package/dist/templates/common/bundled-skills/atw-meta/references/local-architecture/task-system.md +2 -1
  149. package/dist/templates/common/bundled-skills/atw-meta/references/platform-files/hooks-and-settings.md +1 -0
  150. package/dist/templates/common/bundled-skills/atw-noob-mode/SKILL.md +1 -1
  151. package/dist/templates/common/bundled-skills/atw-performance/SKILL.md +134 -0
  152. package/dist/templates/common/bundled-skills/atw-performance/agents/openai.yaml +3 -0
  153. package/dist/templates/common/bundled-skills/atw-performance/references/optimization-patterns.md +250 -0
  154. package/dist/templates/common/bundled-skills/atw-performance/references/performance-checklist.md +238 -0
  155. package/dist/templates/common/bundled-skills/atw-performance/references/performance-optimization.md +264 -0
  156. package/dist/templates/common/bundled-skills/atw-prototype/SKILL.md +3 -3
  157. package/dist/templates/common/bundled-skills/atw-prototype/{LOGIC.md → logic.md} +1 -1
  158. package/dist/templates/common/bundled-skills/atw-prototype/references/design-direction.md +91 -58
  159. package/dist/templates/common/bundled-skills/atw-prototype/references/direction-persuasion.md +25 -0
  160. package/dist/templates/common/bundled-skills/atw-prototype/references/style-explorer.md +1 -1
  161. package/dist/templates/common/bundled-skills/atw-prototype/ui.md +194 -0
  162. package/dist/templates/common/bundled-skills/atw-reflect/SKILL.md +77 -0
  163. package/dist/templates/common/bundled-skills/atw-reflect/agents/openai.yaml +5 -0
  164. package/dist/templates/common/bundled-skills/atw-reflect/references/divergent-reviewer.md +38 -0
  165. package/dist/templates/common/bundled-skills/atw-reflect/references/judgment-reviewer.md +37 -0
  166. package/dist/templates/common/bundled-skills/atw-reflect/references/synthesizer.md +63 -0
  167. package/dist/templates/common/bundled-skills/atw-reflect/references/tooling-reviewer.md +48 -0
  168. package/dist/templates/common/bundled-skills/atw-security/SKILL.md +248 -0
  169. package/dist/templates/common/bundled-skills/atw-security/agents/openai.yaml +3 -0
  170. package/dist/templates/common/bundled-skills/atw-security/references/hardening-patterns.md +324 -0
  171. package/dist/templates/common/bundled-skills/atw-security/references/security-checklist.md +248 -0
  172. package/dist/templates/common/bundled-skills/atw-session-insight/SKILL.md +1 -1
  173. package/dist/templates/common/bundled-skills/atw-session-insight/references/cli-quick-reference.md +11 -2
  174. package/dist/templates/common/bundled-skills/atw-spec/SKILL.md +1 -1
  175. package/dist/templates/common/bundled-skills/atw-tdd/SKILL.md +25 -0
  176. package/dist/templates/common/bundled-skills/atw-tickets/SKILL.md +1 -1
  177. package/dist/templates/common/bundled-skills/atw-triage/SKILL.md +5 -5
  178. package/dist/templates/common/bundled-skills/atw-ui/SKILL.md +99 -31
  179. package/dist/templates/common/bundled-skills/atw-ui/references/accessibility-checklist.md +160 -0
  180. package/dist/templates/common/bundled-skills/atw-ui/references/layout-and-viewport.md +7 -5
  181. package/dist/templates/common/bundled-skills/atw-ui/references/media.md +117 -20
  182. package/dist/templates/common/bundled-skills/atw-ui/references/motion.md +47 -23
  183. package/dist/templates/common/bundled-skills/atw-ui/references/play.md +18 -0
  184. package/dist/templates/common/bundled-skills/atw-ui/references/reviewer-manual.md +73 -0
  185. package/dist/templates/common/bundled-skills/atw-ui/references/scroll-narrative.md +98 -0
  186. package/dist/templates/common/bundled-skills/atw-ui/references/tools.md +46 -0
  187. package/dist/templates/common/bundled-skills/atw-ui/references/visual-language.md +40 -24
  188. package/dist/templates/common/bundled-skills/atw-ui/references/visual-review.md +26 -82
  189. package/dist/templates/common/bundled-skills/atw-ui/scripts/shoot.mjs +1721 -0
  190. package/dist/templates/common/bundled-skills/atw-verify-skill/SKILL.md +58 -0
  191. package/dist/templates/common/bundled-skills/atw-verify-skill/agents/openai.yaml +5 -0
  192. package/dist/templates/common/bundled-skills/atw-verify-skill/references/feature-map-example/README.md +47 -0
  193. package/dist/templates/common/bundled-skills/atw-verify-skill/references/feature-map-example/create-note.md +39 -0
  194. package/dist/templates/common/bundled-skills/atw-verify-skill/references/feature-map-example/search.md +45 -0
  195. package/dist/templates/common/bundled-skills/atw-verify-skill/references/generate.md +107 -0
  196. package/dist/templates/common/bundled-skills/atw-verify-skill/references/health-check.md +100 -0
  197. package/dist/templates/common/bundled-skills/atw-verify-skill/references/verify-skill-template.md +99 -0
  198. package/dist/templates/common/bundled-skills/atw-what-happened/SKILL.md +49 -0
  199. package/dist/templates/common/bundled-skills/atw-what-happened/agents/openai.yaml +5 -0
  200. package/dist/templates/common/commands/finish-work.md +10 -1
  201. package/dist/templates/common/commands/start.md +3 -1
  202. package/dist/templates/common/skills/update-spec.md +40 -4
  203. package/dist/templates/copilot/hooks/session-start.py +2 -2
  204. package/dist/templates/dsh/DSH.md +2 -2
  205. package/dist/templates/markdown/spec/backend/quality-guidelines.md.txt +10 -0
  206. package/dist/templates/markdown/spec/frontend/quality-guidelines.md.txt +10 -0
  207. package/dist/templates/omp/config.yml +15 -0
  208. package/dist/templates/omp/extensions/atw/index.ts.txt +135 -18
  209. package/dist/templates/omp/index.d.ts +1 -0
  210. package/dist/templates/omp/index.d.ts.map +1 -1
  211. package/dist/templates/omp/index.js +3 -0
  212. package/dist/templates/omp/index.js.map +1 -1
  213. package/dist/templates/opencode/lib/session-utils.js +4 -2
  214. package/dist/templates/opencode/plugins/inject-workflow-state.js +5 -1
  215. package/dist/templates/pi/extensions/atw/index.ts.txt +80 -7
  216. package/dist/templates/shared-hooks/index.d.ts +8 -1
  217. package/dist/templates/shared-hooks/index.d.ts.map +1 -1
  218. package/dist/templates/shared-hooks/index.js +8 -0
  219. package/dist/templates/shared-hooks/index.js.map +1 -1
  220. package/dist/templates/shared-hooks/inject-workflow-state.py +131 -14
  221. package/dist/templates/shared-hooks/session-start.py +4 -2
  222. package/dist/templates/shared-hooks/show-notice.py +135 -0
  223. package/dist/templates/snow/SNOW.md +1 -1
  224. package/dist/utils/initialized.d.ts +9 -0
  225. package/dist/utils/initialized.d.ts.map +1 -0
  226. package/dist/utils/initialized.js +24 -0
  227. package/dist/utils/initialized.js.map +1 -0
  228. package/dist/utils/managed-removal.d.ts +2 -0
  229. package/dist/utils/managed-removal.d.ts.map +1 -1
  230. package/dist/utils/managed-removal.js +23 -3
  231. package/dist/utils/managed-removal.js.map +1 -1
  232. package/dist/utils/optional-skills.d.ts +2 -0
  233. package/dist/utils/optional-skills.d.ts.map +1 -1
  234. package/dist/utils/optional-skills.js +1 -1
  235. package/dist/utils/optional-skills.js.map +1 -1
  236. package/dist/utils/template-hash.d.ts.map +1 -1
  237. package/dist/utils/template-hash.js +3 -0
  238. package/dist/utils/template-hash.js.map +1 -1
  239. package/dist/utils/uninstall-scrubbers.d.ts +10 -0
  240. package/dist/utils/uninstall-scrubbers.d.ts.map +1 -1
  241. package/dist/utils/uninstall-scrubbers.js +50 -0
  242. package/dist/utils/uninstall-scrubbers.js.map +1 -1
  243. package/dist/utils/verify-entries.d.ts +51 -0
  244. package/dist/utils/verify-entries.d.ts.map +1 -0
  245. package/dist/utils/verify-entries.js +399 -0
  246. package/dist/utils/verify-entries.js.map +1 -0
  247. package/package.json +2 -2
  248. package/dist/templates/common/bundled-skills/atw-prototype/UI.md +0 -174
  249. package/dist/templates/common/bundled-skills/atw-prototype/references/visual-language.md +0 -88
  250. package/dist/templates/common/bundled-skills/atw-prototype/references/visual-review.md +0 -63
  251. package/dist/templates/common/bundled-skills/atw-ui/references/imagery.md +0 -69
  252. /package/dist/templates/common/bundled-skills/atw-codebase-design/{DEEPENING.md → deepening.md} +0 -0
  253. /package/dist/templates/common/bundled-skills/atw-domain-modeling/{ADR-FORMAT.md → adr-format.md} +0 -0
  254. /package/dist/templates/common/bundled-skills/atw-domain-modeling/{GLOSSARY-FORMAT.md → glossary-format.md} +0 -0
  255. /package/dist/templates/common/bundled-skills/atw-improve-codebase-architecture/{HTML-REPORT.md → html-report.md} +0 -0
  256. /package/dist/templates/common/bundled-skills/atw-triage/{AGENT-BRIEF.md → agent-brief.md} +0 -0
  257. /package/dist/templates/common/bundled-skills/atw-triage/{OUT-OF-SCOPE.md → out-of-scope.md} +0 -0
@@ -0,0 +1,399 @@
1
+ /**
2
+ * 验证 skill 的入口页(`atw verify sync`)。
3
+ *
4
+ * 验证 skill 的内容只放一份在 `.atw/verify/<app>/`(docs/adr/0002)。各平台的
5
+ * skill 文件夹里只放一页 `verify-<app>/SKILL.md`:名字与描述抄正文,正文只指向
6
+ * 那份内容。写到哪些文件夹,按 ATW 判断出的已接入平台推导(`getSkillRoots`,
7
+ * 共享文件夹只算一次)。
8
+ *
9
+ * ATW 写过的入口页记在 `.atw/.verify-entries.json`:入口目录 → 写入时 SKILL.md
10
+ * 的内容指纹。与可选 skill 的安装记录一样,记录决定归属:没记录的同名目录不归
11
+ * ATW,永远不碰;有记录但内容指纹对不上(或目录里多了别的文件)的算被人改过,
12
+ * 也不碰,报冲突。
13
+ */
14
+ import fs from "node:fs";
15
+ import path from "node:path";
16
+ import { getConfiguredPlatforms, getSkillRoots, PLATFORM_IDS, } from "../configurators/index.js";
17
+ import { parseFrontmatter } from "../commands/channel/agent-loader.js";
18
+ import { DIR_NAMES } from "../constants/paths.js";
19
+ import { SKILL_NAME_RE } from "./optional-skills.js";
20
+ import { loadProjectMode } from "./project-mode.js";
21
+ import { computeHash } from "./template-hash.js";
22
+ const RECORD_FILE = ".verify-entries.json";
23
+ const ENTRY_FILE = "SKILL.md";
24
+ const FEATURE_INDEX = "features/README.md";
25
+ /** 「完整」要求的六节,按验证 skill 正文里的二级标题逐字比对。 */
26
+ export const VERIFY_SKILL_SECTIONS = [
27
+ "启动",
28
+ "健康检查",
29
+ "操作",
30
+ "证据",
31
+ "清理",
32
+ "辅助脚本",
33
+ ];
34
+ function isRecord(value) {
35
+ return typeof value === "object" && value !== null && !Array.isArray(value);
36
+ }
37
+ function toAbsolute(cwd, relativePath) {
38
+ return path.join(cwd, ...relativePath.split("/"));
39
+ }
40
+ function isInside(root, target) {
41
+ const relative = path.relative(root, target);
42
+ return (relative === "" ||
43
+ (!relative.startsWith("..") && !path.isAbsolute(relative)));
44
+ }
45
+ /**
46
+ * `target` 解析掉链接后是否仍在项目里。不存在的路径按最近一层存在的上级判断,
47
+ * 以免目录本身是指向项目外的链接时,往下写的文件落到外面去。
48
+ */
49
+ function resolvesInsideProject(cwd, target) {
50
+ const projectRoot = fs.realpathSync(cwd);
51
+ let existing = target;
52
+ while (!fs.existsSync(existing)) {
53
+ const parent = path.dirname(existing);
54
+ if (parent === existing)
55
+ return false;
56
+ existing = parent;
57
+ }
58
+ return isInside(projectRoot, fs.realpathSync(existing));
59
+ }
60
+ // =============================================================================
61
+ // Record
62
+ // =============================================================================
63
+ function recordPath(cwd) {
64
+ return path.join(cwd, DIR_NAMES.WORKFLOW, RECORD_FILE);
65
+ }
66
+ /**
67
+ * 每次读都重新校验:记录里的目录会被删,手改或损坏的记录不能指向
68
+ * `<skill 文件夹>/verify-<app>` 之外的任何东西。
69
+ */
70
+ function loadRecord(cwd) {
71
+ let raw;
72
+ try {
73
+ raw = JSON.parse(fs.readFileSync(recordPath(cwd), "utf-8"));
74
+ }
75
+ catch {
76
+ return {};
77
+ }
78
+ if (!isRecord(raw) || !isRecord(raw.entries))
79
+ return {};
80
+ const knownRoots = new Set(getSkillRoots(PLATFORM_IDS, loadProjectMode(cwd)));
81
+ const record = {};
82
+ for (const [entry, hash] of Object.entries(raw.entries)) {
83
+ const parsed = parseEntryPath(entry);
84
+ if (typeof hash === "string" &&
85
+ parsed !== null &&
86
+ knownRoots.has(parsed.root)) {
87
+ record[entry] = hash;
88
+ }
89
+ }
90
+ return record;
91
+ }
92
+ function saveRecord(cwd, record) {
93
+ // 排序,免得记录随处理顺序在代码历史里来回变。
94
+ const entries = Object.fromEntries(Object.entries(record).sort(([a], [b]) => a.localeCompare(b)));
95
+ fs.writeFileSync(recordPath(cwd), JSON.stringify({ version: 1, entries }, null, 2) + "\n");
96
+ }
97
+ function entryPath(root, app) {
98
+ return `${root}/verify-${app}`;
99
+ }
100
+ function parseEntryPath(entry) {
101
+ const match = /^(.+)\/verify-([^/]+)$/.exec(entry);
102
+ if (!match || !SKILL_NAME_RE.test(match[2]))
103
+ return null;
104
+ return { root: match[1], app: match[2] };
105
+ }
106
+ // =============================================================================
107
+ // Body
108
+ // =============================================================================
109
+ /** 去掉单行值两端成对的引号;块写法(`|`、`>`)解析出的值原样返回。 */
110
+ function unquote(value) {
111
+ const quoted = value.length >= 2 &&
112
+ ((value.startsWith('"') && value.endsWith('"')) ||
113
+ (value.startsWith("'") && value.endsWith("'")));
114
+ return quoted ? value.slice(1, -1) : value;
115
+ }
116
+ /** 文件在且解析后仍在项目里;不在返回 "missing",指向项目外返回 "outside"。 */
117
+ function checkFile(cwd, file) {
118
+ let stat;
119
+ try {
120
+ stat = fs.statSync(file);
121
+ }
122
+ catch {
123
+ return "missing";
124
+ }
125
+ if (!resolvesInsideProject(cwd, file))
126
+ return "outside";
127
+ return stat.isFile() ? "ok" : "missing";
128
+ }
129
+ /** 功能地图索引里指向本地 `.md` 文件的链接目标。 */
130
+ function listedFeatureFiles(index) {
131
+ const targets = [];
132
+ for (const match of index.matchAll(/\]\(\s*<?([^)\s>]+)>?[^)]*\)/g)) {
133
+ const target = match[1].split("#")[0];
134
+ if (/^[a-z][a-z0-9+.-]*:/i.test(target))
135
+ continue;
136
+ if (target.endsWith(".md"))
137
+ targets.push(target);
138
+ }
139
+ return targets;
140
+ }
141
+ function entryPage(app, description) {
142
+ return [
143
+ "---",
144
+ `name: verify-${app}`,
145
+ // JSON 字符串即合法的 YAML 双引号写法:冒号、引号、换行都不会把入口页抄坏。
146
+ `description: ${JSON.stringify(description)}`,
147
+ "---",
148
+ "",
149
+ `完整说明在 \`.atw/verify/${app}/\`,先读它(从其中的 \`SKILL.md\` 开始);其中相对路径以那个目录为准。`,
150
+ "",
151
+ ].join("\n");
152
+ }
153
+ /**
154
+ * 正文是否「完整」:有带名字与描述的说明正文、六节齐、功能地图索引在、索引列的
155
+ * 每个功能文件都在(prd.md Further Notes);完整时一并算出入口页内容。
156
+ */
157
+ function checkBody(cwd, app) {
158
+ const dirRel = `${DIR_NAMES.WORKFLOW}/${DIR_NAMES.VERIFY}/${app}`;
159
+ const dir = toAbsolute(cwd, dirRel);
160
+ if (!resolvesInsideProject(cwd, dir)) {
161
+ return { complete: false, reason: `${dirRel}/ points outside the project` };
162
+ }
163
+ const bodyRel = `${dirRel}/${ENTRY_FILE}`;
164
+ const bodyState = checkFile(cwd, toAbsolute(cwd, bodyRel));
165
+ if (bodyState === "outside") {
166
+ return { complete: false, reason: `${bodyRel} points outside the project` };
167
+ }
168
+ if (bodyState === "missing") {
169
+ return { complete: false, reason: `${bodyRel} is missing` };
170
+ }
171
+ const body = fs
172
+ .readFileSync(toAbsolute(cwd, bodyRel), "utf-8")
173
+ .replace(/\r\n/g, "\n");
174
+ const fence = /^---\n([\s\S]*?)\n---(?:\n|$)/.exec(body);
175
+ const frontmatter = parseFrontmatter(fence?.[1] ?? "");
176
+ if (unquote(frontmatter.name ?? "") !== `verify-${app}`) {
177
+ return {
178
+ complete: false,
179
+ reason: `${bodyRel} needs "name: verify-${app}" in its frontmatter`,
180
+ };
181
+ }
182
+ const description = unquote(frontmatter.description ?? "");
183
+ if (description.trim() === "") {
184
+ return {
185
+ complete: false,
186
+ reason: `${bodyRel} needs a description in its frontmatter`,
187
+ };
188
+ }
189
+ // 格式约定(工单 06 的生成器照此写):每节是一个 `## ` 二级标题,标题文字以节名
190
+ // 开头即可,后面可接括注或说明,如 `## 启动(从空数据目录开始)`。
191
+ const headings = [...body.matchAll(/^##[ \t]+(.+?)[ \t]*$/gm)].map((match) => match[1]);
192
+ const missingSections = VERIFY_SKILL_SECTIONS.filter((section) => !headings.some((heading) => heading.startsWith(section)));
193
+ if (missingSections.length > 0) {
194
+ return {
195
+ complete: false,
196
+ reason: `${bodyRel} is missing sections: ${missingSections.join(", ")}`,
197
+ };
198
+ }
199
+ const indexRel = `${dirRel}/${FEATURE_INDEX}`;
200
+ const indexFile = toAbsolute(cwd, indexRel);
201
+ const indexState = checkFile(cwd, indexFile);
202
+ if (indexState === "outside") {
203
+ return {
204
+ complete: false,
205
+ reason: `${indexRel} points outside the project`,
206
+ };
207
+ }
208
+ if (indexState === "missing") {
209
+ return { complete: false, reason: `${indexRel} is missing` };
210
+ }
211
+ const features = listedFeatureFiles(fs.readFileSync(indexFile, "utf-8"));
212
+ if (features.length === 0) {
213
+ return { complete: false, reason: `${indexRel} lists no feature files` };
214
+ }
215
+ for (const feature of features) {
216
+ const featureFile = path.resolve(path.dirname(indexFile), feature);
217
+ const state = checkFile(cwd, featureFile);
218
+ if (state === "outside") {
219
+ return {
220
+ complete: false,
221
+ reason: `${feature} listed in ${indexRel} points outside the project`,
222
+ };
223
+ }
224
+ if (state === "missing") {
225
+ return {
226
+ complete: false,
227
+ reason: `${feature} listed in ${indexRel} is missing`,
228
+ };
229
+ }
230
+ }
231
+ return {
232
+ complete: true,
233
+ page: entryPage(app, description),
234
+ };
235
+ }
236
+ // =============================================================================
237
+ // Sync
238
+ // =============================================================================
239
+ /** `.atw/verify/` 下的应用目录名;目录本身不在时为空。 */
240
+ function listAppDirs(cwd) {
241
+ const dir = path.join(cwd, DIR_NAMES.WORKFLOW, DIR_NAMES.VERIFY);
242
+ let names;
243
+ try {
244
+ names = fs.readdirSync(dir, { withFileTypes: true });
245
+ }
246
+ catch {
247
+ return [];
248
+ }
249
+ // 指向目录的链接也算应用目录,交给后面的项目内检查去拒绝。
250
+ return names
251
+ .filter((dirent) => dirent.isDirectory() ||
252
+ (dirent.isSymbolicLink() &&
253
+ fs
254
+ .statSync(path.join(dir, dirent.name), {
255
+ throwIfNoEntry: false,
256
+ })
257
+ ?.isDirectory()))
258
+ .map((dirent) => dirent.name)
259
+ .sort();
260
+ }
261
+ /** 入口目录仍是 ATW 写的那份:只有 SKILL.md,且内容指纹与记录一致。 */
262
+ function isUnmodified(dir, hash) {
263
+ if (hash === undefined)
264
+ return false;
265
+ try {
266
+ return (fs.readdirSync(dir).join("/") === ENTRY_FILE &&
267
+ computeHash(fs.readFileSync(path.join(dir, ENTRY_FILE), "utf-8")) === hash);
268
+ }
269
+ catch {
270
+ return false;
271
+ }
272
+ }
273
+ /**
274
+ * 卸载时要删的入口目录:记录里有、仍是 ATW 写的那份(规矩同同步时的归属判断);
275
+ * 记录里有但不能删的另列并写明原因。不归 ATW 的同名目录两边都不列。
276
+ */
277
+ export function listRecordedVerifyEntries(cwd) {
278
+ const removable = [];
279
+ const kept = [];
280
+ for (const [entry, hash] of Object.entries(loadRecord(cwd)).sort(([a], [b]) => a.localeCompare(b))) {
281
+ const dir = toAbsolute(cwd, entry);
282
+ const stat = fs.lstatSync(dir, { throwIfNoEntry: false });
283
+ if (stat === undefined)
284
+ continue;
285
+ if (stat.isSymbolicLink()) {
286
+ kept.push({ entry, reason: "now a link" });
287
+ }
288
+ else if (!resolvesInsideProject(cwd, dir)) {
289
+ kept.push({
290
+ entry,
291
+ reason: "the skill folder points outside the project",
292
+ });
293
+ }
294
+ else if (!stat.isDirectory() || !isUnmodified(dir, hash)) {
295
+ kept.push({ entry, reason: "edited since atw wrote it" });
296
+ }
297
+ else {
298
+ removable.push(entry);
299
+ }
300
+ }
301
+ return { removable, kept };
302
+ }
303
+ /**
304
+ * 按 `.atw/verify/` 的现状同步各已接入平台的入口页。`dryRun` 时只算不写,
305
+ * 安装记录也不动。
306
+ */
307
+ export function syncVerifyEntries(cwd, options = {}) {
308
+ const dryRun = options.dryRun === true;
309
+ const result = { entries: [], skipped: [] };
310
+ const roots = getSkillRoots([...getConfiguredPlatforms(cwd)], loadProjectMode(cwd));
311
+ const record = loadRecord(cwd);
312
+ const recordBefore = JSON.stringify(record);
313
+ const appDirs = listAppDirs(cwd);
314
+ const recordedApps = Object.keys(record)
315
+ .map((entry) => parseEntryPath(entry)?.app)
316
+ .filter((app) => app !== undefined);
317
+ const apps = [...new Set([...appDirs, ...recordedApps])].sort();
318
+ for (const app of apps) {
319
+ let body;
320
+ if (!SKILL_NAME_RE.test(app)) {
321
+ result.skipped.push({
322
+ app,
323
+ reason: "app name may only contain letters, digits, '.', '_' and '-' (starting with a letter or digit)",
324
+ });
325
+ continue;
326
+ }
327
+ if (appDirs.includes(app)) {
328
+ body = checkBody(cwd, app);
329
+ if (!body.complete)
330
+ result.skipped.push({ app, reason: body.reason });
331
+ }
332
+ else {
333
+ body = { complete: false, reason: "verify skill is gone" };
334
+ }
335
+ const appRoots = new Set(roots);
336
+ for (const entry of Object.keys(record)) {
337
+ const parsed = parseEntryPath(entry);
338
+ if (parsed?.app === app)
339
+ appRoots.add(parsed.root);
340
+ }
341
+ for (const root of [...appRoots].sort()) {
342
+ const entry = entryPath(root, app);
343
+ const dir = toAbsolute(cwd, entry);
344
+ const hash = record[entry];
345
+ const conflict = (reason) => {
346
+ result.entries.push({ action: "conflict", entry, reason });
347
+ };
348
+ if (!resolvesInsideProject(cwd, toAbsolute(cwd, root))) {
349
+ if (body.complete || hash !== undefined) {
350
+ conflict("the skill folder points outside the project");
351
+ }
352
+ continue;
353
+ }
354
+ const stat = fs.lstatSync(dir, { throwIfNoEntry: false });
355
+ if (stat === undefined) {
356
+ // 记过却不在了:用户自己删的,忘掉;正文完整且平台仍接入时重新补上。
357
+ Reflect.deleteProperty(record, entry);
358
+ if (!body.complete || !roots.includes(root))
359
+ continue;
360
+ if (!dryRun) {
361
+ fs.mkdirSync(dir, { recursive: true });
362
+ fs.writeFileSync(path.join(dir, ENTRY_FILE), body.page);
363
+ }
364
+ record[entry] = computeHash(body.page);
365
+ result.entries.push({ action: "written", entry });
366
+ continue;
367
+ }
368
+ if (!stat.isDirectory() || !isUnmodified(dir, hash)) {
369
+ // 不归 ATW 的同名目录只在要写入口页时才提;与本应用无关时不出声。
370
+ if (hash !== undefined || body.complete) {
371
+ conflict(hash === undefined
372
+ ? "not written by ATW; left as is"
373
+ : "edited since ATW wrote it; left as is");
374
+ }
375
+ continue;
376
+ }
377
+ if (!body.complete) {
378
+ if (!dryRun)
379
+ fs.rmSync(dir, { recursive: true, force: true });
380
+ Reflect.deleteProperty(record, entry);
381
+ result.entries.push({ action: "removed", entry });
382
+ }
383
+ else if (fs.readFileSync(path.join(dir, ENTRY_FILE), "utf-8") === body.page) {
384
+ result.entries.push({ action: "unchanged", entry });
385
+ }
386
+ else {
387
+ if (!dryRun)
388
+ fs.writeFileSync(path.join(dir, ENTRY_FILE), body.page);
389
+ record[entry] = computeHash(body.page);
390
+ result.entries.push({ action: "updated", entry });
391
+ }
392
+ }
393
+ }
394
+ if (!dryRun && JSON.stringify(record) !== recordBefore) {
395
+ saveRecord(cwd, record);
396
+ }
397
+ return result;
398
+ }
399
+ //# sourceMappingURL=verify-entries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-entries.js","sourceRoot":"","sources":["../../src/utils/verify-entries.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chinhae/atw-cli",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "A Team Workflow — an AI workflow framework that encodes your conventions into the process, for writing code and for work that isn't code",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -33,7 +33,7 @@
33
33
  "inquirer": "^9.3.7",
34
34
  "undici": "^6.21.0",
35
35
  "zod": "^4.4.2",
36
- "@chinhae/atw-core": "0.5.0"
36
+ "@chinhae/atw-core": "0.7.0"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@eslint/js": "^9.18.0",
@@ -1,174 +0,0 @@
1
- # 界面原型
2
-
3
- 界面原型分两段:
4
-
5
- - **第一段:选方向。** 做几个风格和结构都明显不同的方向,放进同一个对比页,由用户挑选,再说出具体喜欢和不喜欢哪里。
6
- - **第二段:深化成可交互原型。** 只在问题包含“用起来对不对”时才做:把选定方向做成完整页面,接上按 [LOGIC.md](LOGIC.md) 写的纯逻辑模块,让人能把真实业务流程完整点一遍。
7
-
8
- 两段的产物都是用来做决定的,不是正式代码。选定之后的正式界面由 atw-ui 按设计说明重新实现。
9
-
10
- 如果问题只关于逻辑或状态、与外观无关,分支选错了,改用 [LOGIC.md](LOGIC.md)。
11
-
12
- ## 什么时候用
13
-
14
- - “这个页面应该长什么样?”
15
- - “正式做之前,我想先看看这个后台有几种可能。”
16
- - “给设置页换个布局试试。”
17
- - “这个下单流程连同规则,用起来顺不顺?”(两段都做)
18
- - 任何用户本来要在脑子里对着三张模糊草图纠结一整天的时候。
19
-
20
- ## 承载方式:优先挂在已有页面上
21
-
22
- 界面原型**贴着应用的其他部分**才好判断:真实的顶栏、侧栏、数据和密度。一个孤零零的新页面是真空,每个方案单独看都还行。所以只要有合理的宿主页面,就优先方式 A。
23
-
24
- ### 方式 A:在已有页面上调整(优先)
25
-
26
- 路由已经存在。各方案**在同一路由上**渲染,用 URL 参数 `?variant=` 切换。现有的数据获取、参数和权限都保留,只换渲染部分。
27
-
28
- 还没有页面、但*自然属于某个页面*的东西(后台里的新区块、设置页里的新卡片、现有流程中的新一步)也算方式 A:把方案挂在宿主页面里。
29
-
30
- 这些方案同时放进对比页作为本机地址候选(`"kind": "url"`),并把当前页面作为基线(`"baseline": true`),每个方向都和现状对照。见 [风格对比页](references/style-explorer.md)。
31
-
32
- ### 方式 B:独立小样(没有宿主页面时)
33
-
34
- 只有确实没有可挂靠的页面时才用,例如全新的顶层界面、或嵌不进任何现有位置的流程。先确认:真的没有现有页面能挂吗?空页面会掩盖有数据时才暴露的设计问题。
35
-
36
- 方式 B 默认做成自包含的单个 HTML 小样,直接放进对比页,双击就能打开,不需要服务器。小样必须用到项目里的组件或框架时,按项目已有的路由约定建一个一次性路由,名字里带 `prototype`,同样用 `?variant=` 切换,并作为本机地址候选放进对比页。
37
-
38
- ## 第一段:选方向
39
-
40
- ### 1. 写下问题,定方案数量
41
-
42
- 默认 **3 个方向**。超过 5 个就不再是“明显不同”而是噪音,上限 5。窄小的任务不强求多方案。
43
-
44
- 把计划写成一句话,放在原型所在位置或文件顶部注释里:
45
-
46
- > “设置页的三个方向,用 `?variant=` 在现有 `/settings` 路由上切换,并汇总到对比页。”
47
-
48
- 用户在不在场都适用。
49
-
50
- ### 2. 定调性,写方向卡,做差异检验
51
-
52
- 方向未定时按 [设计方向](references/design-direction.md) 的顺序做:先从产品题材、受众和使用场合推出调性;每个方向从一个具体的生成引擎出发;写文案之前先定首屏骨架;为每个方向填方向卡,写下它的记忆点;最后逐条做差异检验。
53
-
54
- 方向**必须在结构上不同**:布局、信息层级、主要操作方式都不一样,不只是换颜色。三个微调过的卡片网格不是界面原型,是墙纸。两个方向做出来太像时,回到骨架表重选其中一个,不靠换装饰补救。
55
-
56
- 方向由用户的品味来定,不直接采用模型自己想出的方向。用户已经给定方向时跳过这一步,直接进入第二段或交给 atw-ui。
57
-
58
- ### 3. 做小样
59
-
60
- 每个方向只做首屏和最能体现方向的一两个区块;用户明确要完整页面时照做。挑能暴露方向优缺点的内容:含复杂表单的产品不能只做封面。
61
-
62
- 每个方向要守住:
63
-
64
- - 页面的用途和它能拿到的数据;所有方向共享同样的核心内容和主要操作。
65
- - 方式 A 用项目已有的组件库和样式体系(TailwindCSS、shadcn、MUI、纯 CSS 等);方式 B 的独立小样不受此限,但图标只内联用到的 SVG,不引用外部资源。
66
- - 方式 A 中每个方向导出清楚的组件名,例如 `VariantA`、`VariantB`、`VariantC`。
67
-
68
- 示例内容按真实产品的样子写,避免整数指标和“标题”“描述”这类占位字;画面上不出现“示例”“示意图”“按钮未接入”这类制作说明,这些写进交付说明。视觉层级、字体、色彩和留白的判断见 [视觉语言](references/visual-language.md)。
69
-
70
- ### 4. 生成对比页
71
-
72
- 按 [风格对比页](references/style-explorer.md) 准备 `manifest.json`,把方向卡里的北极星、字体、色板和特征写进去,用内置生成器组装成一个离线 HTML。不要每次自己重做对比工具。对比页和 manifest 放在 ATW 任务目录(没有任务时放在原型旁边),不写进技能安装目录。
73
-
74
- ### 5. 交给用户选
75
-
76
- 给出简短的方向清单和对比页,附推荐理由,请用户选定,并说出具体喜欢和不喜欢哪里。用户只说“再高级一点”这类模糊词时,用设计方向里的翻译表追问,或拿两张小样让用户比较。
77
-
78
- 交付对比页时,把一轮独立评审作为**推荐的下一步**告诉用户:说明它能改善什么(打破几个方向共用的模板骨架)、大约需要多少时间和调用,由用户决定是否执行,不默认派发。用户同意时按 [视觉评审协议](references/visual-review.md) 给每个方向各评审、修改一轮;用户直接选定方向时跳过。
79
-
80
- 用户明确让你自行决定、或当前无法交互时,仍然先做小样、生成对比页留档,再按任务适配、辨识度和可执行性选定,并说明理由。
81
-
82
- 选定后写一份简短的**设计说明**:用户任务、内容与主动作、选定方向(附方向卡)、用户的喜欢与不喜欢、视觉关系、关键状态、设备约束和验收重点。放在 ATW 任务目录的 `ui-direction.md`;已有说明直接更新。这份说明是第二段和 atw-ui 的依据。
83
-
84
- ## 第二段:深化成可交互原型
85
-
86
- 只有问题包含业务规则或完整操作流程时才做;只问外观时,第一段选定后就收尾。
87
-
88
- ### 1. 先写逻辑模块
89
-
90
- 按 [LOGIC.md](LOGIC.md) 第 2 步,把业务规则写成一个纯模块(reducer、状态机或纯函数),不碰 DOM。这部分以后能整体搬进正式代码,是第二段最值得保留的产物。
91
-
92
- ### 2. 选定方向做成完整页面
93
-
94
- 把选定方向从小样扩展成完整页面,作为逻辑模块外面的一层外壳:页面只调用模块、渲染模块返回的状态。关键状态都要在界面上有样子——空、加载、成功、失败、被拒绝的非法操作——不只做漂亮的默认状态。
95
-
96
- 方向卡里的记忆点(某个动作的反馈、完成的那一刻)在这里做出来;动效遵循方向的调性。修改数据的动作一律经过逻辑模块,接口用桩代替,不接真实后端。
97
-
98
- 默认只深化**一个**选定方向。用户要求同时比较两三个方向的完整体验时,多个外壳共用同一个逻辑模块,逻辑只写一次。
99
-
100
- ### 3. 加一个状态抽屉
101
-
102
- LOGIC.md 里的“当前状态面板”和“引导演练”放进一个可开关的抽屉,供不写代码的人逐步走查业务规则:
103
-
104
- - 抽屉视觉上明显不属于设计本身(例如高对比的面板),和浮动切换条一样,不参与设计评判。
105
- - 抽屉里保持朴素:标签式的状态字段、标出刚变化的部分、按场景划分的演练按钮;不加动画。
106
- - 开始演练时重置到已知初始状态。
107
- - 生产构建中隐藏。
108
-
109
- ### 4. 承载
110
-
111
- - **没有现成项目**:单个 HTML,脚本内联,双击即可打开;放进对比页时加 `"interactive": true`,单张查看时就能直接操作。
112
- - **有现成项目**:挂在已有页面上,用 `?variant=` 切换;作为本机地址候选放进对比页。
113
-
114
- ## 接线(方式 A)
115
-
116
- 在路由上建一个切换组件:
117
-
118
- ```tsx
119
- // 伪代码——按项目框架改写
120
- const variant = searchParams.get('variant') ?? 'A';
121
- return (
122
- <>
123
- {variant === 'A' && <VariantA {...data} />}
124
- {variant === 'B' && <VariantB {...data} />}
125
- {variant === 'C' && <VariantC {...data} />}
126
- <PrototypeSwitcher variants={['A','B','C']} current={variant} />
127
- </>
128
- );
129
- ```
130
-
131
- 已有页面:现有数据获取都放在切换组件之上,各方向只替换渲染的子树。一次性路由:同一个切换组件挂在 `prototype` 路由下。
132
-
133
- ## 浮动切换条(方式 A)
134
-
135
- 屏幕底部居中、固定位置的小条,三部分:
136
-
137
- - **左箭头**:切到上一个方向(循环)。
138
- - **方向标签**:当前方向的编号,方向有名字时一并显示,例如 `B — 侧栏布局`。
139
- - **右箭头**:切到下一个方向(循环)。
140
-
141
- 行为:
142
-
143
- - 点箭头时用框架的路由更新 URL 参数(Next 用 `router.replace`,React Router 用 `navigate` 等),保证方向可分享、刷新不丢。
144
- - 键盘 `←` `→` 也能切换。焦点在 `<input>`、`<textarea>` 或 `[contenteditable]` 上时不拦截方向键。
145
- - 视觉上明显区别于页面(例如高对比胶囊、轻阴影),一看就不属于被评判的设计。
146
- - 生产构建中隐藏——用 `process.env.NODE_ENV !== 'production'` 或等价判断,避免误合并后把切换条发给用户。
147
-
148
- 切换条做成一个共享组件,放在项目存放共享界面组件的位置。对比页适合并排比较;切换条适合在真实页面里来回看,开发服务器禁止被嵌入时也只能靠它。
149
-
150
- ## 交给用户
151
-
152
- 给出对比页路径、页面地址和 `?variant=` 的取值;第二段还要说明状态抽屉怎么打开、有哪些演练场景。用户有空时会翻看。最有价值的反馈常常是 **“我要 B 的顶栏配 C 的侧栏”**——那才是他们真正想要的设计。
153
-
154
- 交付说明里写清:哪些是模拟数据、生成图片、未接入的动作;实际查看过哪些视口;哪一步没做以及原因。
155
-
156
- ## 记录结论,收起原型
157
-
158
- 用户选定后,先记录结论——选了哪个方向、为什么、用户的喜欢与不喜欢——更新到 `ui-direction.md`,并把影响需求的部分写进任务的需求文档。然后按 [SKILL](SKILL.md) 的规则收起原型。所有方向、切换组件、对比页和 manifest 进入一次性分支,作为一手资料保存,不进主分支:
159
-
160
- - **方式 A**:主分支上去掉所有方向和切换条,现有页面保持原样。
161
- - **方式 B**:主分支上去掉一次性路由和切换条。
162
- - **第二段**:验证过的逻辑模块搬进正式代码;页面外壳留在一次性分支。
163
-
164
- 正式界面交给 atw-ui,按 `ui-direction.md` 在正式代码里重新实现。留在主分支的方向组件和切换条很快会腐烂,还会误导下一个读代码的人。
165
-
166
- ## 反模式
167
-
168
- - **方向之间只差颜色或文案。** 那是微调,不是原型。真正的方向在结构上互不相同。
169
- - **按明暗分方向。** “一个亮、一个暗、一个暖”是最常见的失败;每个方向要有自己的色彩身份。
170
- - **默认左右分栏。** 一轮里最多一个方向用左右分栏,并写出为什么非它不可。
171
- - **方向之间共享太多代码。** 共享 `<Header>` 可以;共享 `<Layout>` 就失去意义了。每个方向都应该能推翻布局。
172
- - **把方向接到真实的写操作上。** 只读原型没问题;需要修改数据时经过逻辑模块、指向桩。问题是“它应该长什么样、用起来对不对”,不是“后端通不通”。
173
- - **把业务逻辑写进页面事件里。** 第二段的规则必须在纯模块里,否则既不能搬走,也没法在状态抽屉里走查。
174
- - **把原型直接提升为正式代码。** 原型代码是在原型约束下写的(没有测试、错误处理很少)。正式实现交给 atw-ui 和实现阶段重新写。