@zenuml/core 3.47.8 → 3.48.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 (204) hide show
  1. package/dist/cloud-icons-eHuugVSv.js.map +1 -0
  2. package/dist/zenuml.esm.mjs +2153 -2156
  3. package/dist/zenuml.esm.mjs.map +1 -0
  4. package/dist/zenuml.js +82 -82
  5. package/dist/zenuml.js.map +1 -0
  6. package/package.json +11 -1
  7. package/src/cli/zenuml.ts +1164 -0
  8. package/.agents/skills/babysit-pr/SKILL.md +0 -223
  9. package/.agents/skills/babysit-pr/agents/openai.yaml +0 -7
  10. package/.agents/skills/dia-scoring/SKILL.md +0 -139
  11. package/.agents/skills/dia-scoring/agents/openai.yaml +0 -7
  12. package/.agents/skills/dia-scoring/references/selectors-and-keys.md +0 -253
  13. package/.agents/skills/land-pr/SKILL.md +0 -120
  14. package/.agents/skills/propagate-core-release/SKILL.md +0 -205
  15. package/.agents/skills/propagate-core-release/agents/openai.yaml +0 -7
  16. package/.agents/skills/propagate-core-release/references/downstreams.md +0 -42
  17. package/.agents/skills/ship-branch/SKILL.md +0 -105
  18. package/.agents/skills/submit-branch/SKILL.md +0 -76
  19. package/.agents/skills/validate-branch/SKILL.md +0 -72
  20. package/.claude/commands/README.md +0 -162
  21. package/.claude/commands/analyze.md +0 -101
  22. package/.claude/commands/clarify.md +0 -158
  23. package/.claude/commands/code-review.md +0 -322
  24. package/.claude/commands/constitution.md +0 -73
  25. package/.claude/commands/create-docs.md +0 -309
  26. package/.claude/commands/full-context.md +0 -121
  27. package/.claude/commands/gemini-consult.md +0 -164
  28. package/.claude/commands/handoff.md +0 -146
  29. package/.claude/commands/implement.md +0 -56
  30. package/.claude/commands/plan.md +0 -43
  31. package/.claude/commands/refactor.md +0 -188
  32. package/.claude/commands/specify.md +0 -21
  33. package/.claude/commands/tasks.md +0 -62
  34. package/.claude/commands/update-docs.md +0 -314
  35. package/.claude/hooks/README.md +0 -270
  36. package/.claude/hooks/config/sensitive-patterns.json +0 -86
  37. package/.claude/hooks/gemini-context-injector.sh +0 -129
  38. package/.claude/hooks/mcp-security-scan.sh +0 -147
  39. package/.claude/hooks/notify.sh +0 -103
  40. package/.claude/hooks/setup/hook-setup.md +0 -96
  41. package/.claude/hooks/setup/settings.json.template +0 -63
  42. package/.claude/hooks/sounds/complete.wav +0 -0
  43. package/.claude/hooks/sounds/input-needed.wav +0 -0
  44. package/.claude/hooks/subagent-context-injector.sh +0 -65
  45. package/.claude/skills/babysit-pr/SKILL.md +0 -223
  46. package/.claude/skills/babysit-pr/agents/openai.yaml +0 -7
  47. package/.claude/skills/dia-scoring/SKILL.md +0 -139
  48. package/.claude/skills/dia-scoring/agents/openai.yaml +0 -7
  49. package/.claude/skills/dia-scoring/references/selectors-and-keys.md +0 -253
  50. package/.claude/skills/emoji-eval/SKILL.md +0 -187
  51. package/.claude/skills/land-pr/SKILL.md +0 -120
  52. package/.claude/skills/propagate-core-release/SKILL.md +0 -205
  53. package/.claude/skills/propagate-core-release/agents/openai.yaml +0 -7
  54. package/.claude/skills/propagate-core-release/references/downstreams.md +0 -42
  55. package/.claude/skills/ship-branch/SKILL.md +0 -105
  56. package/.claude/skills/submit-branch/SKILL.md +0 -76
  57. package/.claude/skills/validate-branch/SKILL.md +0 -72
  58. package/.claude/skills/zenuml-ux-research/SKILL.md +0 -183
  59. package/.claude/skills/zenuml-ux-research/references/assertion-catalog.md +0 -261
  60. package/.claude/skills/zenuml-ux-research/references/best-practices-overview.md +0 -56
  61. package/.claude/skills/zenuml-ux-research/references/report-template.md +0 -89
  62. package/.claude/skills/zenuml-ux-research/references/scenarios/edit-message-label.md +0 -37
  63. package/.claude/skills/zenuml-ux-research/references/scenarios/insert-message.md +0 -36
  64. package/.claude/skills/zenuml-ux-research/references/scenarios/insert-participant.md +0 -31
  65. package/.claude/skills/zenuml-ux-research/references/scenarios/rename-participant.md +0 -33
  66. package/.claude/skills/zenuml-ux-research/references/scenarios/undo-insert.md +0 -35
  67. package/.devcontainer/devcontainer.json +0 -21
  68. package/.dockerignore +0 -19
  69. package/.eslintrc.js +0 -39
  70. package/.git-blame-ignore-revs +0 -6
  71. package/.kiro/hooks/README.md +0 -38
  72. package/.kiro/hooks/session-sound-notification.js +0 -44
  73. package/.kiro/hooks/session-sound-notification.json +0 -23
  74. package/.mcp.json.example +0 -17
  75. package/.nvmrc +0 -1
  76. package/.prettierignore +0 -4
  77. package/.prettierrc +0 -1
  78. package/.specify/memory/constitution.md +0 -33
  79. package/.specify/scripts/bash/check-prerequisites.sh +0 -166
  80. package/.specify/scripts/bash/common.sh +0 -113
  81. package/.specify/scripts/bash/create-new-feature.sh +0 -97
  82. package/.specify/scripts/bash/setup-plan.sh +0 -60
  83. package/.specify/scripts/bash/update-agent-context.sh +0 -728
  84. package/.specify/templates/agent-file-template.md +0 -23
  85. package/.specify/templates/plan-template.md +0 -219
  86. package/.specify/templates/spec-template.md +0 -116
  87. package/.specify/templates/tasks-template.md +0 -127
  88. package/.storybook/main.ts +0 -25
  89. package/.storybook/preview.ts +0 -29
  90. package/.watchmanconfig +0 -3
  91. package/AGENTS.md +0 -26
  92. package/CLAUDE.md +0 -124
  93. package/DEPLOYMENT.md +0 -62
  94. package/Dockerfile +0 -36
  95. package/IMPLEMENTATION_PLAN.md +0 -163
  96. package/Integration/vanilla-js/index.html +0 -42
  97. package/MCP-ASSISTANT-RULES.md +0 -85
  98. package/README_CN.md +0 -15
  99. package/TUTORIAL.md +0 -116
  100. package/antlr/antlr-4.11.1-complete.jar +0 -0
  101. package/bun.lock +0 -1544
  102. package/bunfig.toml +0 -52
  103. package/docs/UNICODE_SUPPORT.md +0 -179
  104. package/docs/ai-context/deployment-infrastructure.md +0 -21
  105. package/docs/ai-context/docs-overview.md +0 -89
  106. package/docs/ai-context/handoff.md +0 -174
  107. package/docs/ai-context/project-structure.md +0 -160
  108. package/docs/ai-context/system-integration.md +0 -21
  109. package/docs/asciidoc/contributor.adoc +0 -54
  110. package/docs/asciidoc/create-my-own-theme.adoc +0 -149
  111. package/docs/asciidoc/images/creation-component.png +0 -0
  112. package/docs/asciidoc/images/creation-rtl.png +0 -0
  113. package/docs/asciidoc/images/message-arrow-rtl.png +0 -0
  114. package/docs/asciidoc/images/occurrence.png +0 -0
  115. package/docs/asciidoc/images/return-message-conflict.png +0 -0
  116. package/docs/asciidoc/images/shift-up-half-the-height.png +0 -0
  117. package/docs/asciidoc/images/three-layer-info-arch.png +0 -0
  118. package/docs/asciidoc/images/vertical-alignment.svg +0 -1
  119. package/docs/asciidoc/images/vertically-aligning.png +0 -0
  120. package/docs/asciidoc/index.adoc +0 -277
  121. package/docs/asciidoc/theme-debug-web-app.png +0 -0
  122. package/docs/asciidoc/tutorial.adoc +0 -22
  123. package/docs/asciidoc/user-css.png +0 -0
  124. package/docs/async-vs-sync-parser-rules.md +0 -81
  125. package/docs/divider-parser-allow-spaces.md +0 -38
  126. package/docs/highlighting-messages.md +0 -52
  127. package/docs/images/editor-sample.png +0 -0
  128. package/docs/inherited-vs-provided-from.md +0 -64
  129. package/docs/parser/Assignment.md +0 -8
  130. package/docs/parser/PARSER_IMPROVEMENTS_CC.md +0 -425
  131. package/docs/parser/grammar_review_gemini.md +0 -116
  132. package/docs/participants-function.md +0 -25
  133. package/docs/responsive-participant-margin.md +0 -52
  134. package/docs/starter.md +0 -9
  135. package/docs/superpowers/plans/2026-03-27-e2e-test-reorg.md +0 -698
  136. package/docs/superpowers/plans/2026-03-30-emoji-support.md +0 -1220
  137. package/docs/superpowers/plans/2026-03-30-self-correcting-scoring.md +0 -206
  138. package/docs/superpowers/plans/2026-04-15-keyboard-editing-on-diagram.md +0 -1992
  139. package/docs/superpowers/plans/2026-04-15-zenuml-ux-research-skill.md +0 -1452
  140. package/docs/ux-research/.gitkeep +0 -0
  141. package/docs/ux-research/2026-04-15-rename-participant.md +0 -156
  142. package/docs/ux-research/2026-04-18-insert-participant.md +0 -151
  143. package/docs/width-translate-and-offsets.md +0 -62
  144. package/docs/xss.md +0 -59
  145. package/e2e/data/compare-cases.js +0 -1090
  146. package/e2e/data/diff-algorithm.js +0 -199
  147. package/e2e/fixtures/create-message.html +0 -26
  148. package/e2e/fixtures/editable-label.html +0 -35
  149. package/e2e/fixtures/editable-span.html +0 -122
  150. package/e2e/fixtures/empty-diagram.html +0 -23
  151. package/e2e/fixtures/fixture.html +0 -31
  152. package/e2e/fixtures/insert-participant.html +0 -23
  153. package/e2e/fixtures/reorder-cross-fragment.html +0 -31
  154. package/e2e/fixtures/reorder-fragment.html +0 -29
  155. package/e2e/fixtures/reorder-message.html +0 -27
  156. package/e2e/fixtures/svg-test.html +0 -21
  157. package/e2e/fixtures/type-switch.html +0 -29
  158. package/e2e/tools/canonical-history.html +0 -908
  159. package/e2e/tools/compare-case.html +0 -371
  160. package/e2e/tools/compare.html +0 -35
  161. package/e2e/tools/native-diff-ext/background.js +0 -60
  162. package/e2e/tools/native-diff-ext/bridge.js +0 -26
  163. package/e2e/tools/native-diff-ext/content.js +0 -194
  164. package/e2e/tools/svg-preview.html +0 -56
  165. package/embed.html +0 -193
  166. package/eslint.config.mjs +0 -35
  167. package/firebase-debug.log +0 -108
  168. package/iframe-container-demo/diagram.html +0 -124
  169. package/iframe-container-demo/host.html +0 -817
  170. package/index.html +0 -771
  171. package/mermaid-zenuml-async-spa-auth.png +0 -0
  172. package/mermaid-zenuml-async-spa-auth.snapshot.md +0 -96
  173. package/newsletter/unicode-support-announcement.md +0 -134
  174. package/playground/creation.html +0 -53
  175. package/playground/message.html +0 -63
  176. package/playwright.config.ts +0 -40
  177. package/renderer.html +0 -366
  178. package/scripts/analyze-compare-case/collect-data.mjs +0 -1134
  179. package/scripts/analyze-compare-case/config.mjs +0 -102
  180. package/scripts/analyze-compare-case/geometry.mjs +0 -101
  181. package/scripts/analyze-compare-case/native-diff.mjs +0 -224
  182. package/scripts/analyze-compare-case/output.mjs +0 -74
  183. package/scripts/analyze-compare-case/panel-diff.mjs +0 -114
  184. package/scripts/analyze-compare-case/report.mjs +0 -162
  185. package/scripts/analyze-compare-case/residual-scopes.mjs +0 -347
  186. package/scripts/analyze-compare-case/scoring.mjs +0 -829
  187. package/scripts/analyze-compare-case.mjs +0 -149
  188. package/scripts/bump-version.js +0 -117
  189. package/scripts/snapshot-dual.js +0 -173
  190. package/scripts/update-snapshots.js +0 -70
  191. package/skills/dia-scoring/SKILL.md +0 -129
  192. package/skills/dia-scoring/agents/openai.yaml +0 -7
  193. package/skills/dia-scoring/references/selectors-and-keys.md +0 -253
  194. package/tailwind.config.js +0 -126
  195. package/test-compression.html +0 -274
  196. package/test-mermaid-zenuml.html +0 -57
  197. package/test-setup.ts +0 -124
  198. package/test-url-params.html +0 -192
  199. package/tsconfig.app.json +0 -31
  200. package/tsconfig.node.json +0 -24
  201. package/tsconfig.test.json +0 -9
  202. package/vite.config.lib.ts +0 -93
  203. package/vite.config.ts +0 -84
  204. package/wrangler.toml +0 -18
@@ -1,1452 +0,0 @@
1
- # ZenUML UX Research Skill Implementation Plan
2
-
3
- > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
-
5
- **Goal:** Build a project-local Claude Code skill at `zenuml-core/.claude/skills/zenuml-ux-research/` that audits a single ZenUML interaction goal per run, writes a gap-only report to `docs/ux-research/`, and is validated by two calibration scenarios.
6
-
7
- **Architecture:** Data-driven skill: thin `SKILL.md` procedure + `references/` data files (scenarios, assertion catalog, best-practices overview, report template). Live walkthrough via `claude-in-chrome` MCP tools; targeted static analysis via Grep on `src/`. Hypothesis-first, gap-only reports. Playwright regression snippets emitted but not run.
8
-
9
- **Tech Stack:** Markdown (skill and data files), `claude-in-chrome` MCP tools (walkthrough), Read/Grep (static analysis), WebSearch (hypothesis formation). No new runtime code.
10
-
11
- **Spec reference:** `docs/superpowers/specs/2026-04-15-zenuml-ux-research-skill-design.md`
12
-
13
- ---
14
-
15
- ## Preconditions
16
-
17
- Before starting Task 1, the implementer should:
18
-
19
- 1. Be in the `zenuml-core` working directory (`/Users/penxia/ai-personal/zenuml-core`).
20
- 2. Create a dedicated feature branch for this work:
21
- ```bash
22
- cd /Users/penxia/ai-personal/zenuml-core
23
- git checkout -b feat/zenuml-ux-research-skill
24
- ```
25
- 3. Confirm `claude-in-chrome` MCP tools are loadable via `ToolSearch` in this session (they are deferred; Task 13 will load them).
26
- 4. Confirm `bun run dev` succeeds locally on port 4000. Do not leave the dev server running yet — Task 13 will start it when needed.
27
-
28
- All commits in this plan go to the feature branch `feat/zenuml-ux-research-skill`. Do **NOT** push to `main`. Do **NOT** open a PR until the entire plan is complete and the user reviews it.
29
-
30
- ---
31
-
32
- ## File Structure
33
-
34
- Files this plan will create (all under `zenuml-core/`):
35
-
36
- | Path | Responsibility |
37
- |---|---|
38
- | `.claude/skills/zenuml-ux-research/SKILL.md` | Workflow procedure, error handling, invocation rules |
39
- | `.claude/skills/zenuml-ux-research/references/assertion-catalog.md` | ~25 atomic best-practice rules across 7 categories |
40
- | `.claude/skills/zenuml-ux-research/references/scenarios/insert-participant.md` | Seed scenario 1 |
41
- | `.claude/skills/zenuml-ux-research/references/scenarios/rename-participant.md` | Seed scenario 2 |
42
- | `.claude/skills/zenuml-ux-research/references/scenarios/insert-message.md` | Seed scenario 3 |
43
- | `.claude/skills/zenuml-ux-research/references/scenarios/edit-message-label.md` | Seed scenario 4 |
44
- | `.claude/skills/zenuml-ux-research/references/scenarios/undo-insert.md` | Seed scenario 5 |
45
- | `.claude/skills/zenuml-ux-research/references/best-practices-overview.md` | Short narrative framing text-first vs drag-first tool families |
46
- | `.claude/skills/zenuml-ux-research/references/report-template.md` | Template rendered into each gap report |
47
- | `.claude/skills/zenuml-ux-research/examples/sample-report.md` | Hand-verified worked example from the known-gap calibration run |
48
- | `docs/ux-research/.gitkeep` | Ensures the report output directory exists in git |
49
-
50
- Files this plan will NOT modify: anything under `src/`, `tests/`, `docs/superpowers/specs/`, root config files, CLAUDE.md, AGENTS.md, existing skills.
51
-
52
- ---
53
-
54
- ## Task 1: Bootstrap skill directory and SKILL.md skeleton
55
-
56
- **Files:**
57
- - Create: `zenuml-core/.claude/skills/zenuml-ux-research/SKILL.md`
58
- - Create (empty): `zenuml-core/.claude/skills/zenuml-ux-research/references/scenarios/` directory
59
- - Create (empty): `zenuml-core/.claude/skills/zenuml-ux-research/examples/` directory
60
-
61
- **Rationale:** Start with a minimal but valid SKILL.md so the skill is at least discoverable while the rest of the references are being filled in. Frontmatter only — procedure is written in Task 10.
62
-
63
- - [ ] **Step 1: Create directory tree**
64
-
65
- ```bash
66
- mkdir -p /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/references/scenarios
67
- mkdir -p /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/examples
68
- ```
69
-
70
- - [ ] **Step 2: Write SKILL.md skeleton**
71
-
72
- Create `zenuml-core/.claude/skills/zenuml-ux-research/SKILL.md` with:
73
-
74
- ```markdown
75
- ---
76
- name: zenuml-ux-research
77
- description: Audit one ZenUML user interaction scenario at a time (e.g., inserting a message, renaming a participant) against diagramming-tool best practices. Uses claude-in-chrome to walk through the flow in a live browser and writes a gap-only markdown report to docs/ux-research/. Use when the user says "audit ux of", "zenuml ux research", "analyze interaction for zenuml", "run ux research on", or "/zenuml-ux-research". Produces a research report, not an audit pass/fail matrix.
78
- ---
79
-
80
- # ZenUML UX Research
81
-
82
- Skill scaffolding — full workflow, data files, and error handling are written by Tasks 2–10 of the implementation plan at `docs/superpowers/plans/2026-04-15-zenuml-ux-research-skill.md`. Do not invoke this skill end-to-end until Task 10 is complete.
83
- ```
84
-
85
- - [ ] **Step 3: Verify file exists**
86
-
87
- ```bash
88
- ls /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/SKILL.md
89
- ```
90
- Expected: path is listed (no error).
91
-
92
- - [ ] **Step 4: Commit**
93
-
94
- ```bash
95
- cd /Users/penxia/ai-personal/zenuml-core
96
- git add .claude/skills/zenuml-ux-research/SKILL.md
97
- git commit -m "feat(skill): bootstrap zenuml-ux-research skill directory"
98
- ```
99
-
100
- ---
101
-
102
- ## Task 2: Write `references/best-practices-overview.md`
103
-
104
- **Files:**
105
- - Create: `zenuml-core/.claude/skills/zenuml-ux-research/references/best-practices-overview.md`
106
-
107
- **Rationale:** Short narrative context on tool families. This is NOT the checklist — that's `assertion-catalog.md`. This file is for humans and for LLM hypothesis formation, framing why certain interactions are expected.
108
-
109
- - [ ] **Step 1: Write the file**
110
-
111
- Create `zenuml-core/.claude/skills/zenuml-ux-research/references/best-practices-overview.md`:
112
-
113
- ````markdown
114
- # Diagramming Tool UX — Best-Practice Overview
115
-
116
- This document frames the interaction-design context the ZenUML UX research skill reasons about. It is **not** a checklist. Atomic, testable rules live in `assertion-catalog.md`. This file provides the *why* behind the rules.
117
-
118
- ## Two tool families
119
-
120
- Diagramming tools split along a single axis: **what is the primary input method for the user who is actively creating diagram content?**
121
-
122
- ### Text-first (DSL-driven)
123
-
124
- The user types structured text; the rendered diagram is a side-effect.
125
-
126
- Examples: **Mermaid Live**, **PlantUML editors**, **D2 Playground**, **ZenUML**.
127
-
128
- Typical strengths:
129
- - Keyboard-first by construction.
130
- - Versionable, diffable, pasteable content.
131
- - Fast iteration for users who know the DSL.
132
-
133
- Typical weaknesses:
134
- - Discoverability for new users is poor ("what's the syntax for a loop?").
135
- - Visual affordances (clicking a participant to rename it, dragging to reorder) are bolted on, not native.
136
- - Round-trip between "I see a shape on the canvas" and "I edit the text that produced it" is often clunky.
137
-
138
- ### Drag-first (graphical, canvas-driven)
139
-
140
- The user drags shapes; a model is built behind the scenes.
141
-
142
- Examples: **Lucidchart**, **draw.io (diagrams.net)**, **Figma**, **Miro**, **tldraw**, **Excalidraw**.
143
-
144
- Typical strengths:
145
- - New-user discoverability is very high.
146
- - Inline editing on the canvas is the default path.
147
- - Rich direct-manipulation gestures (drag, marquee, snap).
148
-
149
- Typical weaknesses:
150
- - Power-user keyboard flows are often worse than text-first tools.
151
- - Hard to version or diff the output.
152
- - Harder to reuse content across diagrams.
153
-
154
- ### Hybrids
155
-
156
- Some tools occupy the middle and are the most instructive comparisons for ZenUML, which is fundamentally text-first but is growing canvas affordances:
157
-
158
- - **Mermaid Live** — text-first with live preview and basic canvas interactions (click-to-select in generated SVG, no canvas editing).
159
- - **tldraw** / **Excalidraw** — drag-first, but with aggressive keyboard shortcuts and inline editing patterns that text-first tools can borrow.
160
- - **Notion databases / Airtable** — not diagramming, but their inline edit + Tab-to-sibling patterns are the gold standard for keyboard-first editing in any grid/canvas context.
161
- - **Miro sticky note flows** — the current "speed of thought" standard for inserting, renaming, and connecting items without touching a mouse.
162
-
163
- ## Why this matters for ZenUML
164
-
165
- ZenUML is text-first but is moving toward canvas-embedded editing. That means every scenario this skill audits has at least two valid interaction paths — DSL and canvas — and the user experience should be coherent across both. The assertion catalog is structured so that each rule is testable in either path; the walkthrough tries the most discoverable new-user path first and notes alternative paths second.
166
-
167
- ## How this overview is used by the skill
168
-
169
- During Phase B (hypothesis formation), the skill reads this overview to calibrate expectations: for a text-first tool, "you can always fall back to the DSL editor" is a valid mitigation; "this requires a mouse" is a valid finding worth recording, because ZenUML's history of DSL-first users means keyboard-only paths matter disproportionately.
170
- ````
171
-
172
- - [ ] **Step 2: Verify file content**
173
-
174
- ```bash
175
- head -30 /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/references/best-practices-overview.md
176
- ```
177
- Expected: the first 30 lines of the file display, starting with `# Diagramming Tool UX — Best-Practice Overview`.
178
-
179
- - [ ] **Step 3: Commit**
180
-
181
- ```bash
182
- cd /Users/penxia/ai-personal/zenuml-core
183
- git add .claude/skills/zenuml-ux-research/references/best-practices-overview.md
184
- git commit -m "feat(skill): add best-practices overview for zenuml-ux-research"
185
- ```
186
-
187
- ---
188
-
189
- ## Task 3: Write `references/assertion-catalog.md`
190
-
191
- **Files:**
192
- - Create: `zenuml-core/.claude/skills/zenuml-ux-research/references/assertion-catalog.md`
193
-
194
- **Rationale:** The catalog is a reference library of atomic, testable assertions with stable IDs. Every gap in a report can cite an ID; every scenario can prime its hypotheses from the categories here. This file is used heavily during Phase B (hypothesis formation) and Phase D (gap labeling).
195
-
196
- This task writes all ~25 rules in full. No placeholders.
197
-
198
- - [ ] **Step 1: Write the file**
199
-
200
- Create `zenuml-core/.claude/skills/zenuml-ux-research/references/assertion-catalog.md`:
201
-
202
- ````markdown
203
- # ZenUML UX Assertion Catalog
204
-
205
- Atomic, testable best-practice rules for diagramming-tool interactions. Each rule has a stable ID that may be cited in gap reports. The catalog is a **reference library and hypothesis primer**, not a checklist — the skill does NOT grind through all rules on every run.
206
-
207
- ## Catalog structure
208
-
209
- Each rule has:
210
-
211
- - **ID** — stable, citable (e.g., `KBD-03`). Category prefix + two-digit number. Never renumber.
212
- - **Rule** — one sentence describing the expected behavior.
213
- - **Exemplars** — 2–3 tools where the rule is observed.
214
- - **Rationale** — why the rule matters.
215
- - **Applies when** — precondition that must hold for the rule to be meaningful.
216
- - **Check** — concrete, observable outcome the skill can verify (optional for subjective rules).
217
- - **Severity** — `low`, `med`, `high`.
218
-
219
- New rules are appended; IDs are never reused.
220
-
221
- ---
222
-
223
- ## SEL — Selection model
224
-
225
- ### SEL-01
226
- **Rule:** Clicking an item on the canvas selects it exclusively, deselecting anything else that was selected.
227
- **Exemplars:** Figma, tldraw, draw.io.
228
- **Rationale:** The standard single-select model users expect from any canvas editor; anything else forces the user to explicitly clear prior selection.
229
- **Applies when:** The canvas has at least one selectable item and the user clicks it with a single unmodified click.
230
- **Check:** Before click: zero or more items selected. After click: only the clicked item is selected.
231
- **Severity:** high
232
-
233
- ### SEL-02
234
- **Rule:** Clicking empty canvas area deselects all items.
235
- **Exemplars:** Figma, tldraw, Excalidraw.
236
- **Rationale:** Gives the user an always-available "get out of selection" gesture that does not require keyboard.
237
- **Applies when:** At least one item is selected and the user clicks an area of the canvas with no item under the cursor.
238
- **Check:** After click: zero items selected.
239
- **Severity:** med
240
-
241
- ### SEL-03
242
- **Rule:** Selected items have a visible, persistent selection indicator (outline, highlight, or handles).
243
- **Exemplars:** Figma (blue outline), tldraw (dashed outline), draw.io (handles).
244
- **Rationale:** Without visual feedback, selection state is invisible and any subsequent keyboard action feels random.
245
- **Applies when:** One or more items are selected.
246
- **Check:** The selected item's bounding box has a visually distinct marker compared to its non-selected state.
247
- **Severity:** high
248
-
249
- ### SEL-04
250
- **Rule:** Selection state is exposed to assistive technologies via `aria-selected` or equivalent.
251
- **Exemplars:** VS Code editor, GitHub file tree.
252
- **Rationale:** Screen-reader users need programmatic access to selection. Day 1 this rule is observational (the skill notes whether the attribute is present); it is not a hard fail.
253
- **Applies when:** One or more items are selected.
254
- **Check:** Inspect DOM for `aria-selected="true"` on the selected element or its representative.
255
- **Severity:** low
256
-
257
- ---
258
-
259
- ## KBD — Keyboard interaction
260
-
261
- ### KBD-01
262
- **Rule:** Tab moves focus INTO the diagram composite widget from the surrounding page; Shift+Tab moves focus OUT.
263
- **Exemplars:** VS Code tree view, GitHub file tree, Figma.
264
- **Rationale:** The diagram is one Tab stop from the page's perspective; arrow keys navigate inside. This is the ARIA composite-widget convention.
265
- **Applies when:** Focus is on the element immediately before or after the diagram in tab order.
266
- **Check:** Press Tab; focus lands on the diagram root. Press Tab again from inside; focus leaves the diagram.
267
- **Severity:** high
268
-
269
- ### KBD-02
270
- **Rule:** Arrow keys navigate between items inside the diagram composite widget when it has focus.
271
- **Exemplars:** Figma (arrows move selection), tldraw, Excalidraw.
272
- **Rationale:** Once inside the widget, the user needs a keyboard-only way to move the cursor/selection across items.
273
- **Applies when:** Focus is inside the diagram and at least one item is selectable.
274
- **Check:** Press an arrow key; focus or selection visibly moves to an adjacent item.
275
- **Severity:** high
276
-
277
- ### KBD-03
278
- **Rule:** Enter on a selected canvas item enters edit mode with the cursor at the end of the item's label.
279
- **Exemplars:** Figma (text layers), Notion (table cells), tldraw (shapes), VS Code (F2 rename).
280
- **Rationale:** Keyboard-first editing; no mouse round-trip after selection. The most-expected canvas-editor keybinding after Tab/Arrow.
281
- **Applies when:** A single selectable item is selected and the diagram widget has focus.
282
- **Check:** After selection, send Enter. Within 300ms the item's label should become an editable input, focused, with the caret at the end of the existing text.
283
- **Severity:** high
284
-
285
- ### KBD-04
286
- **Rule:** Escape while an item is in edit mode cancels the edit without committing changes.
287
- **Exemplars:** Figma, Notion, tldraw, VS Code rename.
288
- **Rationale:** Undoing an in-flight edit should never require actually committing then undoing. Escape is the universal cancel.
289
- **Applies when:** An item is currently in edit mode and the input has unsaved changes.
290
- **Check:** Enter edit mode, modify text, press Escape. Label reverts to pre-edit value; item exits edit mode.
291
- **Severity:** high
292
-
293
- ### KBD-05
294
- **Rule:** Escape on a selected (but not editing) item either deselects or exits the widget; it should not silently do nothing.
295
- **Exemplars:** Figma, tldraw.
296
- **Rationale:** Escape is the "get me out" key. Silent no-op leaves the user uncertain about what's selected.
297
- **Applies when:** Focus is inside the diagram and exactly one item is selected (not in edit mode).
298
- **Check:** Press Escape. Selection clears OR focus leaves the diagram widget.
299
- **Severity:** med
300
-
301
- ### KBD-06
302
- **Rule:** Tab inside edit mode commits the current edit and spawns a new sibling in edit mode (Miro pattern).
303
- **Exemplars:** Miro sticky notes, Notion database rows, Linear issue creation.
304
- **Rationale:** Speed-of-flow creation for power users. Not universally expected but is the gold standard when present.
305
- **Applies when:** An item is in edit mode.
306
- **Check:** Type label, press Tab. Edit commits; a new sibling of the same type appears next in order, already in edit mode with focus.
307
- **Severity:** med
308
-
309
- ---
310
-
311
- ## EDT — Inline editing
312
-
313
- ### EDT-01
314
- **Rule:** Entering edit mode replaces the label rendering with a focused, editable input in the same visual position.
315
- **Exemplars:** Figma, Notion, tldraw.
316
- **Rationale:** Prevents layout shift and makes the edit feel like direct manipulation rather than a modal.
317
- **Applies when:** An item is entering edit mode by any means (Enter, double-click, toolbar).
318
- **Check:** The input element is visible at the label's prior position; no modal or popover opens; the input has focus.
319
- **Severity:** high
320
-
321
- ### EDT-02
322
- **Rule:** On edit mode entry via Enter, the caret is placed at the end of the existing text with no pre-selection.
323
- **Exemplars:** Notion cell edit, Linear issue title edit.
324
- **Rationale:** Appending to an existing label (the common case) should not require arrow-right; deleting the whole label should be an explicit second step.
325
- **Applies when:** Edit mode was entered via Enter on a selected item with an existing, non-empty label.
326
- **Check:** After entering edit mode, caret is at end-of-text; no characters are pre-selected.
327
- **Severity:** med
328
-
329
- ### EDT-03
330
- **Rule:** Edit mode entered on a newly inserted item places an empty input with focus, ready to accept typing.
331
- **Exemplars:** Miro sticky notes, Notion new row, tldraw new shape.
332
- **Rationale:** New items should not require a second click to start typing.
333
- **Applies when:** A new item was just inserted and is expected to be named.
334
- **Check:** Immediately after insertion, the item is in edit mode with an empty input and keyboard focus.
335
- **Severity:** high
336
-
337
- ### EDT-04
338
- **Rule:** Committing an edit (Enter or blur) persists the change; cancelling (Escape) discards without side-effects.
339
- **Exemplars:** Figma, Notion, VS Code rename.
340
- **Rationale:** The commit/cancel contract is the most-trusted UX primitive in inline editing; violating it silently loses user work.
341
- **Applies when:** An item is in edit mode.
342
- **Check:** Make an edit. Press Enter → change persists in the DSL and on the canvas. Separately, make an edit and press Escape → change is fully discarded.
343
- **Severity:** high
344
-
345
- ---
346
-
347
- ## FOC — Focus management
348
-
349
- ### FOC-01
350
- **Rule:** After inserting a new item via keyboard, focus lands on the new item in edit mode.
351
- **Exemplars:** Miro stickies, tldraw new shapes, Excalidraw text boxes.
352
- **Rationale:** The user's next likely action on a new item is to name it. Requiring a separate selection step is friction.
353
- **Applies when:** An insertion was triggered via keyboard (shortcut, Tab-to-sibling, Enter on a "plus" affordance).
354
- **Check:** Immediately after insertion, the new item is selected AND in edit mode AND has keyboard focus.
355
- **Severity:** high
356
-
357
- ### FOC-02
358
- **Rule:** After deleting an item, focus moves to a predictable sibling (previous if any, else next, else parent).
359
- **Exemplars:** VS Code file explorer, Linear list delete, Notion row delete.
360
- **Rationale:** Focus-left-hanging after delete is one of the top accessibility complaints in web apps; any sibling is better than the document root.
361
- **Applies when:** An item is deleted while the diagram widget has focus.
362
- **Check:** After delete, a sibling or parent element has focus (not `document.body`, not `:focus-visible` on nothing).
363
- **Severity:** med
364
-
365
- ### FOC-03
366
- **Rule:** Undo restores selection and focus to the pre-operation state, not just the data.
367
- **Exemplars:** Figma undo, Linear undo.
368
- **Rationale:** The point of undo is to undo what the user *experienced*, which includes selection and focus. Undoing data without selection is disorienting.
369
- **Applies when:** Undo was triggered after an operation that changed selection or focus.
370
- **Check:** Before operation: selection = X. After operation: selection = Y. After undo: selection = X.
371
- **Severity:** med
372
-
373
- ### FOC-04
374
- **Rule:** Focus indicator is always visible when keyboard-focused; `:focus-visible` suppression is not applied to the entire widget.
375
- **Exemplars:** any WAI-ARIA-compliant widget.
376
- **Rationale:** A keyboard user should always know where focus is.
377
- **Applies when:** A focusable element inside the diagram is focused via keyboard navigation.
378
- **Check:** Inspect the focused element; it has a visible focus outline or equivalent.
379
- **Severity:** med
380
-
381
- ---
382
-
383
- ## INS — Insertion affordances
384
-
385
- ### INS-01
386
- **Rule:** A new item can be inserted without opening or touching the DSL editor pane directly.
387
- **Exemplars:** Mermaid Live (no, this is a known weakness; cited as a negative exemplar), tldraw (yes), Figma (yes).
388
- **Rationale:** For a tool that is text-first but growing canvas editing, the canvas should be a primary creation surface. Falling back to the DSL is acceptable; being forced into it is a gap.
389
- **Applies when:** A scenario's target state requires inserting a new participant, message, note, or other item.
390
- **Check:** The skill must find at least one insertion path that does not require editing the DSL editor text area.
391
- **Severity:** high
392
-
393
- ### INS-02
394
- **Rule:** The primary insertion affordance is discoverable by a new user within ~10 seconds of looking at the canvas.
395
- **Exemplars:** tldraw (visible toolbar), Figma (visible plus button).
396
- **Rationale:** Discoverability is the gateway to every other interaction; hidden affordances turn new users away.
397
- **Applies when:** A scenario involves inserting something.
398
- **Check:** Subjective; the skill records whether the insertion affordance was obvious on first look and, if not, how long it took to find.
399
- **Severity:** med
400
-
401
- ### INS-03
402
- **Rule:** Insertion has at least one keyboard-only path.
403
- **Exemplars:** Miro (Tab-to-sibling), Linear (Cmd+Enter on issues).
404
- **Rationale:** Text-first tool users are keyboard-native; a mouse-only insertion affordance loses them.
405
- **Applies when:** A scenario involves inserting something.
406
- **Check:** The skill must find at least one path from "blank state" to "new item present" that uses only the keyboard.
407
- **Severity:** high
408
-
409
- ---
410
-
411
- ## UND — Undo / redo
412
-
413
- ### UND-01
414
- **Rule:** Ctrl/Cmd+Z undoes the last logical operation.
415
- **Exemplars:** every text editor, every canvas editor.
416
- **Rationale:** The universal baseline.
417
- **Applies when:** At least one undoable operation has occurred.
418
- **Check:** Perform operation X. Press Ctrl/Cmd+Z. State reverts to pre-X.
419
- **Severity:** high
420
-
421
- ### UND-02
422
- **Rule:** Undo/redo granularity matches a logical user action, not individual keystrokes during a label edit.
423
- **Exemplars:** Figma undo, Notion undo, Linear undo.
424
- **Rationale:** One undo should undo one perceived action. Undoing character-by-character turns Ctrl+Z into an "erase this text" macro, which is worse than useless.
425
- **Applies when:** A label was edited and then undo was pressed.
426
- **Check:** Edit a label from `A` to `Alice`. Press Ctrl/Cmd+Z once. The label returns to `A`, not `Alic`.
427
- **Severity:** high
428
-
429
- ### UND-03
430
- **Rule:** Undo restores the selection to the item that was operated on, not an arbitrary state.
431
- **Exemplars:** Figma, Linear.
432
- **Rationale:** Undo should put the user back where they can immediately re-try or explore, which requires selection to match.
433
- **Applies when:** An operation that affected selection is being undone.
434
- **Check:** Before: select X, modify X. After undo: X is selected again.
435
- **Severity:** med
436
-
437
- ---
438
-
439
- ## FBK — Visual feedback
440
-
441
- ### FBK-01
442
- **Rule:** Hover states are visible on interactive elements.
443
- **Exemplars:** every canvas editor.
444
- **Rationale:** Hover is the pre-interaction affordance; its absence forces trial-and-error clicks.
445
- **Applies when:** A clickable or draggable element exists on the canvas.
446
- **Check:** Hover over the element; visual state changes (cursor, outline, tint).
447
- **Severity:** low
448
-
449
- ### FBK-02
450
- **Rule:** Invalid actions show immediate non-blocking feedback rather than silently failing.
451
- **Exemplars:** Figma toast, Linear inline errors.
452
- **Rationale:** Silent failure trains users to distrust the tool; even a toast is better than nothing.
453
- **Applies when:** The user attempts an operation that is not currently valid (e.g., delete with nothing selected).
454
- **Check:** Trigger an invalid operation. Observe any feedback within 500ms.
455
- **Severity:** med
456
-
457
- ### FBK-03
458
- **Rule:** Drop targets or alignment guides are shown during drag operations where applicable.
459
- **Exemplars:** Figma smart guides, tldraw snap lines.
460
- **Rationale:** Without guides, drag feels imprecise.
461
- **Applies when:** The scenario involves a drag operation.
462
- **Check:** During an active drag, alignment guides or drop indicators appear before release.
463
- **Severity:** low
464
- ````
465
-
466
- - [ ] **Step 2: Verify all categories and rules present**
467
-
468
- ```bash
469
- grep -c "^### " /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/references/assertion-catalog.md
470
- ```
471
- Expected: `27` (4 SEL + 6 KBD + 4 EDT + 4 FOC + 3 INS + 3 UND + 3 FBK = 27 rule headers).
472
-
473
- Also:
474
- ```bash
475
- grep "^## " /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/references/assertion-catalog.md | sort
476
- ```
477
- Expected output contains lines for: `## Catalog structure`, `## EDT — Inline editing`, `## FBK — Visual feedback`, `## FOC — Focus management`, `## INS — Insertion affordances`, `## KBD — Keyboard interaction`, `## SEL — Selection model`, `## UND — Undo / redo`.
478
-
479
- - [ ] **Step 3: Commit**
480
-
481
- ```bash
482
- cd /Users/penxia/ai-personal/zenuml-core
483
- git add .claude/skills/zenuml-ux-research/references/assertion-catalog.md
484
- git commit -m "feat(skill): seed zenuml-ux-research assertion catalog (27 rules, 7 categories)"
485
- ```
486
-
487
- ---
488
-
489
- ## Task 4: Write scenario `insert-participant.md`
490
-
491
- **Files:**
492
- - Create: `zenuml-core/.claude/skills/zenuml-ux-research/references/scenarios/insert-participant.md`
493
-
494
- - [ ] **Step 1: Write the file**
495
-
496
- ````markdown
497
- ---
498
- id: insert-participant
499
- title: Insert a participant on a blank diagram
500
- ---
501
-
502
- ## User intent
503
- The user opens ZenUML to a blank diagram and wants to add one participant named `Alice` so they can start modelling.
504
-
505
- ## Starting DSL
506
- ```
507
- ```
508
-
509
- ## Target DSL
510
- ```
511
- Alice
512
- ```
513
-
514
- ## Relevant assertion categories
515
- INS, FOC, EDT, KBD
516
-
517
- ## Walkthrough hints (not prescriptive)
518
- - Blank canvas is the highest-stakes discoverability test — the skill should record how long it takes to find the insertion affordance.
519
- - Candidate insertion paths to try in order:
520
- 1. Click on the canvas background.
521
- 2. Look for a visible "+" or "Add participant" affordance.
522
- 3. Keyboard: try pressing Enter or `p` on an empty canvas.
523
- 4. Fall back to typing directly into the DSL editor pane.
524
- - The moment the user successfully names the new participant `Alice` is the scenario's end state.
525
-
526
- ## Known issues to watch for (optional)
527
- - If the only path is direct DSL editing, that itself is a finding (violates INS-01).
528
- ````
529
-
530
- - [ ] **Step 2: Verify file**
531
-
532
- ```bash
533
- ls /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/references/scenarios/insert-participant.md
534
- ```
535
- Expected: path listed.
536
-
537
- - [ ] **Step 3: Commit**
538
-
539
- ```bash
540
- cd /Users/penxia/ai-personal/zenuml-core
541
- git add .claude/skills/zenuml-ux-research/references/scenarios/insert-participant.md
542
- git commit -m "feat(skill): add insert-participant scenario"
543
- ```
544
-
545
- ---
546
-
547
- ## Task 5: Write scenario `rename-participant.md`
548
-
549
- **Files:**
550
- - Create: `zenuml-core/.claude/skills/zenuml-ux-research/references/scenarios/rename-participant.md`
551
-
552
- - [ ] **Step 1: Write the file**
553
-
554
- ````markdown
555
- ---
556
- id: rename-participant
557
- title: Rename a participant via keyboard
558
- ---
559
-
560
- ## User intent
561
- The user has a participant `A` on the canvas and wants to rename it to `Alice` without leaving the keyboard.
562
-
563
- ## Starting DSL
564
- ```
565
- A
566
- ```
567
-
568
- ## Target DSL
569
- ```
570
- Alice
571
- ```
572
-
573
- ## Relevant assertion categories
574
- KBD, EDT, SEL, FOC
575
-
576
- ## Walkthrough hints (not prescriptive)
577
- - This scenario is the canonical test of KBD-03 (Enter enters edit mode) and EDT-02 (caret at end of text).
578
- - Candidate paths to try in order:
579
- 1. Tab into the diagram widget, arrow-key to select `A`, press Enter, type `lice`, press Enter.
580
- 2. Click `A` to select, press Enter, retype.
581
- 3. Double-click `A` to enter edit mode.
582
- 4. Fall back to editing the DSL editor directly.
583
- - Watch specifically for: whether Enter does anything on the selected participant; whether the caret is placed at the end or the whole label is pre-selected; whether Escape cancels cleanly.
584
-
585
- ## Known issues to watch for (optional)
586
- - If Enter does nothing on a selected participant, that is a KBD-03 violation at high severity.
587
- - If only mouse double-click works, that is a KBD-only violation (no mouse-free path).
588
- ````
589
-
590
- - [ ] **Step 2: Verify file**
591
-
592
- ```bash
593
- ls /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/references/scenarios/rename-participant.md
594
- ```
595
- Expected: path listed.
596
-
597
- - [ ] **Step 3: Commit**
598
-
599
- ```bash
600
- cd /Users/penxia/ai-personal/zenuml-core
601
- git add .claude/skills/zenuml-ux-research/references/scenarios/rename-participant.md
602
- git commit -m "feat(skill): add rename-participant scenario"
603
- ```
604
-
605
- ---
606
-
607
- ## Task 6: Write scenario `insert-message.md`
608
-
609
- **Files:**
610
- - Create: `zenuml-core/.claude/skills/zenuml-ux-research/references/scenarios/insert-message.md`
611
-
612
- - [ ] **Step 1: Write the file**
613
-
614
- ````markdown
615
- ---
616
- id: insert-message
617
- title: Insert a synchronous message between two participants
618
- ---
619
-
620
- ## User intent
621
- The user has two participants `A` and `B` on the canvas and wants to add a synchronous message from `A` to `B` with the label `hello`.
622
-
623
- ## Starting DSL
624
- ```
625
- A
626
- B
627
- ```
628
-
629
- ## Target DSL
630
- ```
631
- A
632
- B
633
- A->B: hello
634
- ```
635
-
636
- ## Relevant assertion categories
637
- INS, KBD, EDT, FOC, FBK
638
-
639
- ## Walkthrough hints (not prescriptive)
640
- - This is the most common creation action in any sequence diagramming tool; it is the load-bearing scenario for canvas-first editing of ZenUML.
641
- - Candidate paths to try in order:
642
- 1. Click `A`, look for a "send message" affordance or toolbar button, draw/click toward `B`.
643
- 2. Hover between `A` and `B` in the lifeline area for an inline "+" affordance.
644
- 3. Keyboard: Tab into widget, select `A`, press a hotkey for "new message".
645
- 4. Fall back to typing `A->B: hello` into the DSL editor.
646
- - Watch specifically for: whether a canvas-first path exists at all, whether message creation automatically enters label edit mode on the new message, whether Escape during message creation cancels cleanly.
647
-
648
- ## Known issues to watch for (optional)
649
- - If the canvas has no message-creation affordance at all, that is an INS-01 violation at high severity.
650
- - If the new message is not in edit mode immediately on creation, that is an EDT-03 / FOC-01 violation.
651
- ````
652
-
653
- - [ ] **Step 2: Verify file**
654
-
655
- ```bash
656
- ls /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/references/scenarios/insert-message.md
657
- ```
658
- Expected: path listed.
659
-
660
- - [ ] **Step 3: Commit**
661
-
662
- ```bash
663
- cd /Users/penxia/ai-personal/zenuml-core
664
- git add .claude/skills/zenuml-ux-research/references/scenarios/insert-message.md
665
- git commit -m "feat(skill): add insert-message scenario"
666
- ```
667
-
668
- ---
669
-
670
- ## Task 7: Write scenario `edit-message-label.md`
671
-
672
- **Files:**
673
- - Create: `zenuml-core/.claude/skills/zenuml-ux-research/references/scenarios/edit-message-label.md`
674
-
675
- - [ ] **Step 1: Write the file**
676
-
677
- ````markdown
678
- ---
679
- id: edit-message-label
680
- title: Edit an existing message label
681
- ---
682
-
683
- ## User intent
684
- The user has a message `A->B: hello` on the canvas and wants to change the label to `hi`.
685
-
686
- ## Starting DSL
687
- ```
688
- A
689
- B
690
- A->B: hello
691
- ```
692
-
693
- ## Target DSL
694
- ```
695
- A
696
- B
697
- A->B: hi
698
- ```
699
-
700
- ## Relevant assertion categories
701
- EDT, KBD, SEL, FOC, UND
702
-
703
- ## Walkthrough hints (not prescriptive)
704
- - This scenario exercises the inline-edit contract on an existing piece of DSL, not a new one.
705
- - Candidate paths to try in order:
706
- 1. Click the message label `hello` once to select, press Enter, retype.
707
- 2. Double-click the message label.
708
- 3. Keyboard: navigate to the message via arrows, press Enter.
709
- 4. Fall back to editing the DSL editor directly.
710
- - Watch specifically for: undo granularity when the user types `hi` then changes their mind (one undo should revert the whole label, not one character at a time).
711
-
712
- ## Known issues to watch for (optional)
713
- - If undo is character-level during a label edit, that is a UND-02 violation.
714
- - If clicking the message selects the wrong thing (e.g., the arrow instead of the label), that is a SEL-01 violation.
715
- ````
716
-
717
- - [ ] **Step 2: Verify file**
718
-
719
- ```bash
720
- ls /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/references/scenarios/edit-message-label.md
721
- ```
722
- Expected: path listed.
723
-
724
- - [ ] **Step 3: Commit**
725
-
726
- ```bash
727
- cd /Users/penxia/ai-personal/zenuml-core
728
- git add .claude/skills/zenuml-ux-research/references/scenarios/edit-message-label.md
729
- git commit -m "feat(skill): add edit-message-label scenario"
730
- ```
731
-
732
- ---
733
-
734
- ## Task 8: Write scenario `undo-insert.md`
735
-
736
- **Files:**
737
- - Create: `zenuml-core/.claude/skills/zenuml-ux-research/references/scenarios/undo-insert.md`
738
-
739
- - [ ] **Step 1: Write the file**
740
-
741
- ````markdown
742
- ---
743
- id: undo-insert
744
- title: Undo a just-inserted message
745
- ---
746
-
747
- ## User intent
748
- The user has two participants `A` and `B`, inserts a message `A->B: hello`, then immediately presses Ctrl/Cmd+Z to undo. The expected result is that the message is removed and the state is back to just the two participants.
749
-
750
- ## Starting DSL
751
- ```
752
- A
753
- B
754
- ```
755
-
756
- ## Target DSL
757
- ```
758
- A
759
- B
760
- ```
761
- (after: insert `A->B: hello`, then undo)
762
-
763
- ## Relevant assertion categories
764
- UND, FOC, SEL, KBD
765
-
766
- ## Walkthrough hints (not prescriptive)
767
- - This scenario exercises the full insertion-then-undo round trip.
768
- - Steps:
769
- 1. Follow the `insert-message` scenario's walkthrough to get to the post-insert state.
770
- 2. Press Ctrl+Z (or Cmd+Z on macOS).
771
- 3. Observe: is the message removed? Is the DSL editor reverted? Is selection/focus restored to whatever it was before the insert?
772
- - Watch specifically for: undo granularity (one Ctrl+Z should undo the whole insert, not the individual keystrokes of the label edit) and focus restoration (FOC-03).
773
-
774
- ## Known issues to watch for (optional)
775
- - If the undo leaves the label partially typed, UND-02 is violated.
776
- - If focus ends up on the document body after undo, FOC-03 is violated.
777
- ````
778
-
779
- - [ ] **Step 2: Verify file**
780
-
781
- ```bash
782
- ls /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/references/scenarios/undo-insert.md
783
- ```
784
- Expected: path listed.
785
-
786
- - [ ] **Step 3: Commit**
787
-
788
- ```bash
789
- cd /Users/penxia/ai-personal/zenuml-core
790
- git add .claude/skills/zenuml-ux-research/references/scenarios/undo-insert.md
791
- git commit -m "feat(skill): add undo-insert scenario"
792
- ```
793
-
794
- ---
795
-
796
- ## Task 9: Write `references/report-template.md`
797
-
798
- **Files:**
799
- - Create: `zenuml-core/.claude/skills/zenuml-ux-research/references/report-template.md`
800
-
801
- **Rationale:** The template is what Phase F renders into each gap report. SKILL.md's procedure prose will reference this file by name. Template uses `{{placeholder}}` syntax the skill fills in at render time.
802
-
803
- - [ ] **Step 1: Write the file**
804
-
805
- Create `zenuml-core/.claude/skills/zenuml-ux-research/references/report-template.md`:
806
-
807
- `````markdown
808
- ---
809
- scenario_id: {{scenario_id}}
810
- scenario_title: {{scenario_title}}
811
- run_date: {{run_date}}
812
- zenuml_core_sha: {{zenuml_core_sha}}
813
- audited_url: {{audited_url}}
814
- skill_version: 0.1.0
815
- gap_count: { high: {{gap_count_high}}, med: {{gap_count_med}}, low: {{gap_count_low}} }
816
- ---
817
-
818
- # UX Research — {{scenario_title}}
819
-
820
- ## Executive summary
821
-
822
- {{executive_summary}}
823
-
824
- ## Scenario recap
825
-
826
- **User intent:** {{user_intent}}
827
-
828
- **Starting DSL:**
829
- ```
830
- {{starting_dsl}}
831
- ```
832
-
833
- **Target DSL:**
834
- ```
835
- {{target_dsl}}
836
- ```
837
-
838
- ## Observed walkthrough
839
-
840
- {{walkthrough_numbered_steps}}
841
-
842
- ## Gaps
843
-
844
- {{gap_blocks}}
845
-
846
- > Each gap block uses this structure:
847
- >
848
- > ```
849
- > ### Gap N — <short headline>
850
- > **Severity:** <low|med|high>
851
- > **Catalog ID:** <id or "novel — candidate for new rule">
852
- > **Observed:** <verbatim>
853
- > **Expected:** <from hypothesis>
854
- > **Exemplars:** <tools where expected behavior is seen>
855
- > **Rationale:** <why this matters>
856
- > **Suggested fix:** <grep result: file:line; or "no code path found">
857
- > ```
858
- >
859
- > (Blockquote is for documentation inside the template — the rendered report omits it.)
860
-
861
- ## Coverage
862
-
863
- Tested hypotheses (no gap found):
864
- {{coverage_tested}}
865
-
866
- Not tested (out of scope for this scenario):
867
- {{coverage_out_of_scope}}
868
-
869
- Skipped (couldn't form a testable hypothesis):
870
- {{coverage_skipped}}
871
-
872
- ## Best-practice sources
873
-
874
- **Bundled catalog IDs referenced:**
875
- {{bundled_sources}}
876
-
877
- **Web sources fetched during this run:**
878
- {{web_sources}}
879
-
880
- ## Playwright regression snippet
881
-
882
- Paste into `zenuml-core/tests/ux/{{scenario_id}}.spec.ts` once the gap is fixed. The skill emits this snippet; it does not run it.
883
-
884
- ```typescript
885
- {{playwright_snippet}}
886
- ```
887
-
888
- ---
889
-
890
- ## Zero-gap rendering
891
-
892
- If the scenario produced zero gaps, render the report omitting the **Gaps** and **Playwright regression snippet** sections. The **Observed walkthrough** section becomes a single line:
893
-
894
- > No gaps observed on zenuml-core @ {{zenuml_core_sha}}.
895
-
896
- All other sections (metadata, executive summary, scenario recap, coverage, best-practice sources) still render.
897
- `````
898
-
899
- - [ ] **Step 2: Verify file content**
900
-
901
- ```bash
902
- grep -c "{{" /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/references/report-template.md
903
- ```
904
- Expected: at least 15 (one per placeholder).
905
-
906
- - [ ] **Step 3: Commit**
907
-
908
- ```bash
909
- cd /Users/penxia/ai-personal/zenuml-core
910
- git add .claude/skills/zenuml-ux-research/references/report-template.md
911
- git commit -m "feat(skill): add zenuml-ux-research report template"
912
- ```
913
-
914
- ---
915
-
916
- ## Task 10: Write `SKILL.md` (full procedure)
917
-
918
- **Files:**
919
- - Modify: `zenuml-core/.claude/skills/zenuml-ux-research/SKILL.md`
920
-
921
- **Rationale:** Task 1 created a skeleton. This task fully replaces it with the procedure prose, error handling, and invocation instructions. SKILL.md is the file Claude Code loads when the skill is invoked, so everything the skill needs to do at runtime must be in here (or in a referenced file the skill reads on demand).
922
-
923
- - [ ] **Step 1: Read the current skeleton to confirm it exists**
924
-
925
- ```bash
926
- cat /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/SKILL.md
927
- ```
928
- Expected: the skeleton content from Task 1 displays.
929
-
930
- - [ ] **Step 2: Fully replace SKILL.md with the procedure**
931
-
932
- Overwrite `zenuml-core/.claude/skills/zenuml-ux-research/SKILL.md` with:
933
-
934
- `````markdown
935
- ---
936
- name: zenuml-ux-research
937
- description: Audit one ZenUML user interaction scenario at a time (e.g., inserting a message, renaming a participant) against diagramming-tool best practices. Uses claude-in-chrome to walk through the flow in a live browser and writes a gap-only markdown report to docs/ux-research/. Use when the user says "audit ux of", "zenuml ux research", "analyze interaction for zenuml", "run ux research on", or "/zenuml-ux-research". Produces a research report, not an audit pass/fail matrix.
938
- ---
939
-
940
- # ZenUML UX Research
941
-
942
- This skill audits a single ZenUML interaction scenario against diagramming-tool best practices and writes a gap-only markdown report. It is a research tool, not an audit or regression tool. Run it interactively, read the report, and act on it by hand. Never wire it into CI.
943
-
944
- ## When to invoke
945
-
946
- - User asks "audit ux of X", "zenuml ux research", "analyze interaction for X".
947
- - User runs `/zenuml-ux-research <scenario-id>` or `/zenuml-ux-research "free-text goal"`.
948
- - User asks for a specific gap analysis in the ZenUML editor experience.
949
-
950
- Do NOT invoke this skill for pixel-level comparison (that is `dia-scoring`), parser behavior, or build/deploy tasks.
951
-
952
- ## Invocation parameters
953
-
954
- - **Scenario identifier (positional):** either a catalog ID like `insert-message` or a free-text goal like `"audit how users insert a message between A and B"`.
955
- - **`--url <url>` (optional):** target URL. Default `http://localhost:4000`. Can point to a deployed staging URL.
956
- - **`--allow-prod` (optional):** required for any URL that is not `localhost`, `127.0.0.1`, or a known staging subdomain. The skill is read-only against the target, but this flag forces the human to confirm they know they're pointing at a real-users environment.
957
-
958
- ## Dependencies
959
-
960
- - `claude-in-chrome` MCP tools (for walkthrough). If these are not yet loaded in the session, the skill must instruct the user to load them via `ToolSearch` and stop; the walkthrough cannot run in text-only mode.
961
- - `ZenUML dev server or a reachable URL` (default `http://localhost:4000`).
962
- - `Read` / `Grep` tools (for static source analysis of `zenuml-core/src/`).
963
- - `WebSearch` / `WebFetch` tools (for targeted best-practice lookups; optional).
964
-
965
- ## Files this skill uses at runtime
966
-
967
- - `references/scenarios/<scenario-id>.md` — loaded at Phase A.
968
- - `references/assertion-catalog.md` — loaded at Phase B.
969
- - `references/best-practices-overview.md` — loaded at Phase B for narrative framing.
970
- - `references/report-template.md` — loaded at Phase F.
971
-
972
- ## Report output
973
-
974
- - Written to `zenuml-core/docs/ux-research/YYYY-MM-DD-<scenario-id>.md`.
975
- - Create the directory if it doesn't exist (`mkdir -p`).
976
- - On filename collision, append `-2`, `-3`, etc. Never overwrite.
977
- - Never commit the report automatically — the human decides.
978
-
979
- ## Workflow
980
-
981
- ### Phase A — Scenario resolution
982
-
983
- 1. Determine whether the invocation is a catalog ID or free-text.
984
- 2. **Catalog ID:**
985
- - Check that `references/scenarios/<id>.md` exists.
986
- - If not, list all available scenario filenames (glob `references/scenarios/*.md`) and stop.
987
- - Load the file. Verify it has front matter with `id` and `title`, plus headings for `User intent`, `Starting DSL`, `Target DSL`, `Relevant assertion categories`. If any are missing, print which field is missing from which file and stop.
988
- 3. **Free-text:**
989
- - Synthesize a scenario record with the same fields (id, title, user intent, starting DSL, target DSL, relevant categories).
990
- - Present the synthesized record to the user and wait for explicit confirmation.
991
- - Do NOT proceed on an unconfirmed synthesized scenario.
992
- 4. Check `--url` reachability with a quick HTTP GET.
993
- - If unreachable and the URL is local: print the exact fix command (`cd /Users/penxia/ai-personal/zenuml-core && bun run dev`) and stop.
994
- - If unreachable and the URL is remote: print the HTTP status and stop.
995
- - If reachable and the URL is non-local but does NOT have `--allow-prod`: warn and stop. Non-local URLs that look like known staging patterns (e.g., contain `staging`, `preview`, `github.io` for the gh-pages build) may proceed with a one-line warning but no hard stop.
996
- 5. Confirm `claude-in-chrome` tools are loaded. If not: instruct the user to load them via `ToolSearch` with query `"select:mcp__claude-in-chrome__tabs_context_mcp,mcp__claude-in-chrome__tabs_create_mcp,mcp__claude-in-chrome__navigate,mcp__claude-in-chrome__find,mcp__claude-in-chrome__computer,mcp__claude-in-chrome__read_page,mcp__claude-in-chrome__read_console_messages,mcp__claude-in-chrome__javascript_tool"` and stop.
997
-
998
- ### Phase B — Hypothesis formation
999
-
1000
- 1. Read the scenario's User intent.
1001
- 2. Read `references/best-practices-overview.md` for narrative framing.
1002
- 3. Scan `references/assertion-catalog.md` for rules whose category is in the scenario's Relevant assertion categories list. Treat these as **priors** — starting points for what you expect to see — not as a checklist.
1003
- 4. Form a short list of expectations in working memory. Example for `rename-participant`: "I expect Enter on selected participant to enter edit mode (KBD-03). I expect caret at end (EDT-02). I expect Escape to cancel (KBD-04). I expect undo granularity to be at the label level (UND-02)."
1004
- 5. **Hypotheses are NOT limited to the catalog.** Form open-ended expectations based on general best practices and common sense. If the scenario suggests territory the catalog is silent on, run **1–3** targeted `WebSearch` queries (e.g., "how does tldraw handle arrow-key navigation between shapes"). Keep the budget tight.
1005
-
1006
- ### Phase C — Browser walkthrough
1007
-
1008
- 1. `mcp__claude-in-chrome__tabs_context_mcp` → get current tab state (do not reuse existing tabs from prior sessions).
1009
- 2. `mcp__claude-in-chrome__tabs_create_mcp` → open a new tab.
1010
- 3. `mcp__claude-in-chrome__navigate` → navigate to the `--url`.
1011
- 4. Wait for the page to load. `mcp__claude-in-chrome__read_console_messages` at each interaction to catch runtime errors.
1012
- 5. **Seed the starting state** by interacting with the DSL editor pane to type the scenario's Starting DSL. This is setup, not walkthrough — failures here are infrastructure errors.
1013
- - If Starting DSL is empty, no seeding is needed.
1014
- - If seeding itself fails (e.g., the DSL editor is unreachable), stop, report "could not seed starting state via DSL editor" as a walkthrough-blocker, and do NOT write a report. This is worse than a gap — it's a dead environment.
1015
- 6. **Attempt to reach Target DSL via the most discoverable path a new user would try first.** Record each step:
1016
- - What was attempted (e.g., "clicked canvas area to the right of participant B")
1017
- - What happened (e.g., "no visible change; console warning: `[zenuml] unknown click target`")
1018
- - Whether it advanced toward Target DSL
1019
- 7. If the first path fails or hits friction, try 1–2 alternative paths (toolbar, keyboard shortcut, DSL edit). Record each.
1020
- 8. **Capture screenshots only at decision moments**, not every step — keeps reports readable. Use `mcp__claude-in-chrome__computer` for screenshots if the tool is available.
1021
- 9. **Hard stop after 3 failed attempts on the same step.** Record "could not perform step X after 3 attempts" and move on or stop. Do NOT loop.
1022
-
1023
- ### Phase D — Gap detection
1024
-
1025
- 1. For each observation, compare against the corresponding hypothesis.
1026
- 2. **If observation matches hypothesis: drop it. Do not record. Silence is correct.**
1027
- 3. **If observation diverges from hypothesis: record a gap.** Each gap has:
1028
- - Headline (short, e.g., "Enter on selected participant does nothing")
1029
- - Observed (verbatim)
1030
- - Expected (from hypothesis)
1031
- - Catalog ID (scan `references/assertion-catalog.md` for a rule whose `Applies when` and `Check` match; cite that ID. If no rule matches, label the gap `novel — candidate for new rule`.)
1032
- - Exemplars (from the catalog if cited, else from web search)
1033
- - Rationale
1034
- - Severity (`low`, `med`, `high`) — use the catalog rule's severity if cited, else judge based on impact
1035
- 4. Novel gaps are flagged but NOT auto-written to the catalog. The human reviews them and folds them in manually later.
1036
-
1037
- ### Phase E — Targeted static source analysis
1038
-
1039
- For each gap, use `Grep` on `/Users/penxia/ai-personal/zenuml-core/src/` to find the relevant code path:
1040
-
1041
- - For keyboard interactions: grep for the key name (`'Enter'`, `'Escape'`) and keydown listeners.
1042
- - For selection state: grep for `select`, `Selection`, `aria-selected`, and the Jotai atoms.
1043
- - For inline editing: grep for `contenteditable`, `input`, component names like `Participant`, `Message`.
1044
- - For undo/redo: grep for `undo`, `history`, `Jotai` atoms that track history state.
1045
-
1046
- Attach `file:line` pointers to each gap. If no handler is found, write `"no code path found — this is a missing implementation, not a misrouted one."` Often the most useful finding.
1047
-
1048
- ### Phase F — Report writing
1049
-
1050
- 1. Load `references/report-template.md`.
1051
- 2. Fill in all `{{placeholder}}` fields.
1052
- 3. Determine the output path:
1053
- - Today's date in `YYYY-MM-DD` format.
1054
- - Filename: `YYYY-MM-DD-<scenario-id>.md`.
1055
- - Full path: `/Users/penxia/ai-personal/zenuml-core/docs/ux-research/YYYY-MM-DD-<scenario-id>.md`.
1056
- 4. Create `docs/ux-research/` if it doesn't exist.
1057
- 5. If the filename already exists for today, append `-2`, `-3`, etc.
1058
- 6. Write the file.
1059
- 7. If gap count is zero, render the zero-gap form (omit Gaps and Playwright snippet sections, collapse the walkthrough to a one-line "No gaps observed on <sha>").
1060
-
1061
- ### Phase G — Hand-off
1062
-
1063
- 1. Print the report path.
1064
- 2. Print a one-line summary: `"Found N gaps (X high, Y med, Z low). Report at <path>."`
1065
- 3. Stop. Do NOT:
1066
- - auto-commit the report
1067
- - auto-fix any gap
1068
- - open a PR
1069
- - notify anyone
1070
- - run additional scenarios
1071
-
1072
- ## Error handling
1073
-
1074
- **Invocation-time (fail fast, clear instructions):**
1075
-
1076
- - Scenario ID not found → list `references/scenarios/*.md` filenames, stop.
1077
- - Free-text goal too ambiguous (e.g., can't infer starting or target DSL) → ask one clarifying question, re-confirm, only proceed on confirmation.
1078
- - Scenario file malformed → print file path and missing field, stop.
1079
- - `claude-in-chrome` tools not loaded → instruct user to load via ToolSearch (query shown above), stop.
1080
- - URL unreachable → print fix command, stop.
1081
- - Non-local URL without `--allow-prod` → warn and stop.
1082
-
1083
- **Walkthrough-time (observe and record, do not panic):**
1084
-
1085
- - Target state unreachable after 2–3 paths → this is itself a high-severity gap. Write a report with "scenario target is unreachable via discovered interaction paths" as the primary finding.
1086
- - Console error mid-walkthrough → captured, included in the walkthrough step, does not halt unless the app becomes unresponsive.
1087
- - Browser crash → stop, print observations so far, do NOT write a partial report.
1088
- - Screenshot failure → skipped, walkthrough step still recorded with `screenshot: failed`.
1089
- - Same step fails 3 times → stop retrying, record "could not perform step X", move on or stop.
1090
-
1091
- **Analysis-time (degrade gracefully):**
1092
-
1093
- - Static analysis finds no handler → say so explicitly.
1094
- - Web search returns nothing → fall back to catalog and common sense.
1095
- - Catalog has no matching rule → label gap `novel`, flag as growth candidate.
1096
-
1097
- **Output-time:**
1098
-
1099
- - `docs/ux-research/` does not exist → create it.
1100
- - Filename collision → append `-2`, `-3`, etc.
1101
- - Git SHA capture fails → write `unknown` in metadata. Do not abort.
1102
-
1103
- ## What this skill does NOT do
1104
-
1105
- - Retry failed walkthrough paths indefinitely.
1106
- - Auto-fix any gap.
1107
- - Commit the report, open a PR, notify anyone.
1108
- - Run multiple scenarios in one invocation.
1109
- - Run Playwright — only emits a snippet for the human to use.
1110
- - Touch production deploy state.
1111
-
1112
- ## Extending the skill
1113
-
1114
- - **New scenario:** drop a new file into `references/scenarios/`, matching the format of existing scenarios. The skill discovers it automatically.
1115
- - **New assertion rule:** append it to `references/assertion-catalog.md` with the next sequential ID in its category. Never renumber existing rules.
1116
- - **Catalog growth from novel gaps:** when a run flags a `novel` gap, the human reviews and, if appropriate, adds a new rule to the catalog by hand.
1117
- - **Calibration drift:** any substantial change to this SKILL.md should be followed by re-running both calibration scenarios (see the plan document).
1118
- `````
1119
-
1120
- - [ ] **Step 3: Verify the file is well-formed**
1121
-
1122
- ```bash
1123
- head -5 /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/SKILL.md
1124
- ```
1125
- Expected first line: `---`. Second line should start with `name: zenuml-ux-research`.
1126
-
1127
- ```bash
1128
- grep -c "^## " /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/SKILL.md
1129
- ```
1130
- Expected: at least 10 (top-level headings: When to invoke, Invocation parameters, Dependencies, Files this skill uses, Report output, Workflow, Error handling, What this skill does NOT do, Extending the skill, plus any inner `## ` headings).
1131
-
1132
- ```bash
1133
- grep -c "TBD\|TODO\|XXX\|FIXME" /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/SKILL.md
1134
- ```
1135
- Expected: `0`.
1136
-
1137
- - [ ] **Step 4: Commit**
1138
-
1139
- ```bash
1140
- cd /Users/penxia/ai-personal/zenuml-core
1141
- git add .claude/skills/zenuml-ux-research/SKILL.md
1142
- git commit -m "feat(skill): write full zenuml-ux-research SKILL.md procedure"
1143
- ```
1144
-
1145
- ---
1146
-
1147
- ## Task 11: Create `docs/ux-research/` output directory
1148
-
1149
- **Files:**
1150
- - Create: `zenuml-core/docs/ux-research/.gitkeep`
1151
-
1152
- **Rationale:** The skill creates the directory at runtime if missing, but having it in git from the start makes report PRs cleaner and lets the skill skip the `mkdir -p` step on first run.
1153
-
1154
- - [ ] **Step 1: Create directory and `.gitkeep`**
1155
-
1156
- ```bash
1157
- mkdir -p /Users/penxia/ai-personal/zenuml-core/docs/ux-research
1158
- touch /Users/penxia/ai-personal/zenuml-core/docs/ux-research/.gitkeep
1159
- ```
1160
-
1161
- - [ ] **Step 2: Verify**
1162
-
1163
- ```bash
1164
- ls -la /Users/penxia/ai-personal/zenuml-core/docs/ux-research/
1165
- ```
1166
- Expected: `.gitkeep` listed.
1167
-
1168
- - [ ] **Step 3: Commit**
1169
-
1170
- ```bash
1171
- cd /Users/penxia/ai-personal/zenuml-core
1172
- git add docs/ux-research/.gitkeep
1173
- git commit -m "chore: add docs/ux-research output directory for zenuml-ux-research skill"
1174
- ```
1175
-
1176
- ---
1177
-
1178
- ## Task 12: Static validation of the skill's data files
1179
-
1180
- **Files:** no changes; this task runs verification commands only.
1181
-
1182
- **Rationale:** Layer 1 of the test plan from the spec — verify that every scenario has required fields and every category referenced in a scenario resolves to a real category in the catalog. This is what the skill does at runtime on every invocation; running it manually here catches any drift introduced while writing the files.
1183
-
1184
- - [ ] **Step 1: Verify every scenario has required front-matter and headings**
1185
-
1186
- ```bash
1187
- cd /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/references/scenarios
1188
- for f in *.md; do
1189
- echo "=== $f ==="
1190
- grep -E "^(id|title):" "$f" || echo "MISSING FRONT MATTER"
1191
- grep -E "^## (User intent|Starting DSL|Target DSL|Relevant assertion categories)" "$f" || echo "MISSING HEADING"
1192
- done
1193
- ```
1194
- Expected: each of the 5 files prints `id`, `title`, and the four `## ` headings. No `MISSING` lines.
1195
-
1196
- - [ ] **Step 2: Verify every category referenced in a scenario resolves to a real category in the catalog**
1197
-
1198
- ```bash
1199
- cd /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/references
1200
- CATS=$(grep "^## [A-Z][A-Z][A-Z] " assertion-catalog.md | sed -E 's/## ([A-Z]+).*/\1/' | sort -u)
1201
- echo "Catalog categories: $CATS"
1202
- for f in scenarios/*.md; do
1203
- echo "=== $f ==="
1204
- # Extract the line after "## Relevant assertion categories" and check each token
1205
- REFS=$(awk '/^## Relevant assertion categories/{getline; print}' "$f" | tr -d ',' )
1206
- for ref in $REFS; do
1207
- if echo "$CATS" | grep -qw "$ref"; then
1208
- echo " OK: $ref"
1209
- else
1210
- echo " FAIL: $ref not in catalog"
1211
- fi
1212
- done
1213
- done
1214
- ```
1215
- Expected: every referenced category prints `OK`. No `FAIL` lines.
1216
-
1217
- - [ ] **Step 3: Verify catalog entries have required fields**
1218
-
1219
- ```bash
1220
- cd /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/references
1221
- # Each rule starts with "### <ID>" — count them and confirm each has Rule/Exemplars/Rationale/Severity
1222
- RULES=$(grep -c "^### [A-Z][A-Z][A-Z]-[0-9][0-9]" assertion-catalog.md)
1223
- echo "Rules found: $RULES"
1224
- for field in "Rule:" "Exemplars:" "Rationale:" "Applies when:" "Severity:"; do
1225
- COUNT=$(grep -cF "**$field**" assertion-catalog.md)
1226
- echo " $field appears $COUNT times"
1227
- done
1228
- ```
1229
- Expected: `Rules found` is 27 and each field count equals 27 (each rule must have every one of these fields).
1230
-
1231
- - [ ] **Step 4: If any failure above, fix inline and re-run the checks**
1232
-
1233
- Any `MISSING` or `FAIL` line is a blocker. Fix the referenced file by hand, re-run the checks, and do not proceed until all output is clean.
1234
-
1235
- - [ ] **Step 5: No commit**
1236
-
1237
- This task makes no changes; nothing to commit.
1238
-
1239
- ---
1240
-
1241
- ## Task 13: Run the known-gap calibration scenario
1242
-
1243
- **Files:** no file changes yet; a report will be generated into `docs/ux-research/` and a sample report created in Task 14.
1244
-
1245
- **Rationale:** Layer 2 of the test plan. This is the first real run of the skill end-to-end. The acceptance criterion is that the skill successfully executes Phases A–G and produces a report that catches at least one real, meaningful gap in the current zenuml-core build.
1246
-
1247
- **Pre-flight:** the implementer must choose ONE scenario from the seed five to use as the known-gap calibration. Typical choice is `rename-participant` because the scenario's explicit design target (Enter → edit mode) is the most likely place for a gap in a text-first tool. The actual calibration scenario should be chosen based on the implementer's five-minute manual check of current ZenUML behavior on `localhost:4000`.
1248
-
1249
- - [ ] **Step 1: Start the dev server in a separate terminal**
1250
-
1251
- ```bash
1252
- cd /Users/penxia/ai-personal/zenuml-core
1253
- bun run dev
1254
- ```
1255
- Expected: Vite boots and logs `http://localhost:4000` as the dev URL. Leave this terminal running.
1256
-
1257
- - [ ] **Step 2: In this Claude session, load the `claude-in-chrome` MCP tools**
1258
-
1259
- Use `ToolSearch` with query:
1260
- ```
1261
- select:mcp__claude-in-chrome__tabs_context_mcp,mcp__claude-in-chrome__tabs_create_mcp,mcp__claude-in-chrome__navigate,mcp__claude-in-chrome__find,mcp__claude-in-chrome__computer,mcp__claude-in-chrome__read_page,mcp__claude-in-chrome__read_console_messages,mcp__claude-in-chrome__javascript_tool
1262
- ```
1263
- Expected: the tool schemas are loaded and callable.
1264
-
1265
- - [ ] **Step 3: Manually pick the known-gap scenario**
1266
-
1267
- Pick one of `insert-participant`, `rename-participant`, `insert-message`, `edit-message-label`, `undo-insert`.
1268
-
1269
- Spend five minutes driving `http://localhost:4000` by hand to verify that the scenario does in fact have at least one real gap in current ZenUML behavior. Record which scenario you picked and which gap you expect the skill to find.
1270
-
1271
- If **none** of the five have a visible gap on the first manual pass, write that observation down as a finding for the spec author and pick the most-constrained scenario (`rename-participant`) anyway — the skill may catch something subtler than a five-minute manual pass.
1272
-
1273
- - [ ] **Step 4: Invoke the skill**
1274
-
1275
- In the Claude session, say:
1276
- ```
1277
- /zenuml-ux-research <picked-scenario-id>
1278
- ```
1279
- Expected behavior:
1280
- - Phase A loads the scenario, confirms the URL reachable.
1281
- - Phase B forms hypotheses from the catalog.
1282
- - Phase C walks through the scenario in the Chrome tab.
1283
- - Phase D records any gaps.
1284
- - Phase E greps `src/` for file:line pointers on each gap.
1285
- - Phase F writes the report to `docs/ux-research/2026-04-15-<scenario-id>.md`.
1286
- - Phase G prints the path and a one-line summary.
1287
-
1288
- - [ ] **Step 5: Verify the report was written**
1289
-
1290
- ```bash
1291
- ls /Users/penxia/ai-personal/zenuml-core/docs/ux-research/
1292
- cat /Users/penxia/ai-personal/zenuml-core/docs/ux-research/2026-04-15-<scenario-id>.md | head -50
1293
- ```
1294
- Expected: the report file exists and the first 50 lines render the front matter, executive summary, and start of the walkthrough.
1295
-
1296
- - [ ] **Step 6: Hand-verify the report catches the expected gap**
1297
-
1298
- Read the entire report. Acceptance:
1299
- - At least one gap in the Gaps section matches the gap you identified in Step 3.
1300
- - The gap's severity is reasonable.
1301
- - The gap cites a catalog ID (if one matches) or is labeled `novel`.
1302
- - The Suggested fix field points at a real file in `src/` (or says "no code path found" if the handler genuinely doesn't exist).
1303
- - The Coverage section has at least 3 bullets of tested hypotheses.
1304
-
1305
- **If acceptance fails**, the skill's procedure prose needs refinement. Document what failed in the plan's "Known issues" at the bottom of this file, revise SKILL.md, and re-run from Step 4. Do NOT declare the task complete until acceptance passes.
1306
-
1307
- - [ ] **Step 7: Commit the calibration report**
1308
-
1309
- ```bash
1310
- cd /Users/penxia/ai-personal/zenuml-core
1311
- git add docs/ux-research/2026-04-15-<scenario-id>.md
1312
- git commit -m "docs: calibration report for <scenario-id> (known-gap calibration)"
1313
- ```
1314
-
1315
- ---
1316
-
1317
- ## Task 14: Create `examples/sample-report.md` from the calibration run
1318
-
1319
- **Files:**
1320
- - Create: `zenuml-core/.claude/skills/zenuml-ux-research/examples/sample-report.md`
1321
-
1322
- **Rationale:** The hand-verified report from Task 13 becomes the skill's reference example — used as documentation and as a regression anchor. It is NOT used for automated diffing.
1323
-
1324
- - [ ] **Step 1: Copy the calibration report**
1325
-
1326
- ```bash
1327
- cp /Users/penxia/ai-personal/zenuml-core/docs/ux-research/2026-04-15-<scenario-id>.md \
1328
- /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/examples/sample-report.md
1329
- ```
1330
-
1331
- - [ ] **Step 2: Hand-edit for accuracy and clarity**
1332
-
1333
- Open `sample-report.md` and:
1334
- - Correct any sloppy phrasing.
1335
- - Make sure the executive summary is a tight 3–5 sentences.
1336
- - Make sure every gap block has all the required fields.
1337
- - Make sure the Coverage section lists real tested hypotheses (not placeholders).
1338
- - Add a short preamble comment at the top of the file: `<!-- Sample report generated from the known-gap calibration run of <scenario-id>. See docs/superpowers/plans/2026-04-15-zenuml-ux-research-skill.md Task 14. -->`
1339
-
1340
- - [ ] **Step 3: Verify**
1341
-
1342
- ```bash
1343
- head -5 /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research/examples/sample-report.md
1344
- ```
1345
- Expected: starts with the preamble comment followed by the metadata block.
1346
-
1347
- - [ ] **Step 4: Commit**
1348
-
1349
- ```bash
1350
- cd /Users/penxia/ai-personal/zenuml-core
1351
- git add .claude/skills/zenuml-ux-research/examples/sample-report.md
1352
- git commit -m "feat(skill): add hand-verified sample report from calibration"
1353
- ```
1354
-
1355
- ---
1356
-
1357
- ## Task 15: Run the known-clean calibration scenario
1358
-
1359
- **Files:** a second calibration report is generated into `docs/ux-research/`.
1360
-
1361
- **Rationale:** Layer 2 of the test plan — second calibration. This run verifies the skill does NOT hallucinate gaps on a flow that works correctly. The acceptance criterion is zero gaps (or only `low` severity non-blockers) with a populated Coverage section.
1362
-
1363
- - [ ] **Step 1: Pick a second scenario from the seed five**
1364
-
1365
- Choose a scenario different from the one used in Task 13. This scenario should target an interaction you believe works correctly in the current ZenUML build.
1366
-
1367
- Five-minute manual check: drive the scenario by hand on `http://localhost:4000`. Confirm no obvious UX issues.
1368
-
1369
- - [ ] **Step 2: Invoke the skill**
1370
-
1371
- ```
1372
- /zenuml-ux-research <second-scenario-id>
1373
- ```
1374
- Expected: skill runs end-to-end as in Task 13.
1375
-
1376
- - [ ] **Step 3: Verify the report**
1377
-
1378
- ```bash
1379
- cat /Users/penxia/ai-personal/zenuml-core/docs/ux-research/2026-04-15-<second-scenario-id>.md
1380
- ```
1381
- Acceptance:
1382
- - Report file exists.
1383
- - Gap count is zero, OR only `low` severity non-blockers. No `high`.
1384
- - Coverage section has at least 3 tested-hypothesis bullets.
1385
- - The executive summary makes it clear the flow was audited and found clean.
1386
-
1387
- **If the skill invented a high-severity gap that is not real**, hypothesis formation is too aggressive. Document what the hallucinated gap was, revise SKILL.md Phase B prose to calibrate, and re-run from Step 2.
1388
-
1389
- - [ ] **Step 4: Commit the clean calibration report**
1390
-
1391
- ```bash
1392
- cd /Users/penxia/ai-personal/zenuml-core
1393
- git add docs/ux-research/2026-04-15-<second-scenario-id>.md
1394
- git commit -m "docs: calibration report for <second-scenario-id> (known-clean calibration)"
1395
- ```
1396
-
1397
- ---
1398
-
1399
- ## Task 16: Final review and wrap-up
1400
-
1401
- **Files:** none
1402
-
1403
- - [ ] **Step 1: Verify git log shows all commits**
1404
-
1405
- ```bash
1406
- cd /Users/penxia/ai-personal/zenuml-core
1407
- git log --oneline feat/zenuml-ux-research-skill ^main | head -30
1408
- ```
1409
- Expected: ~15 commits covering Tasks 1–15 in order.
1410
-
1411
- - [ ] **Step 2: Verify the skill directory is complete**
1412
-
1413
- ```bash
1414
- find /Users/penxia/ai-personal/zenuml-core/.claude/skills/zenuml-ux-research -type f | sort
1415
- ```
1416
- Expected output:
1417
- ```
1418
- .../SKILL.md
1419
- .../examples/sample-report.md
1420
- .../references/assertion-catalog.md
1421
- .../references/best-practices-overview.md
1422
- .../references/report-template.md
1423
- .../references/scenarios/edit-message-label.md
1424
- .../references/scenarios/insert-message.md
1425
- .../references/scenarios/insert-participant.md
1426
- .../references/scenarios/rename-participant.md
1427
- .../references/scenarios/undo-insert.md
1428
- ```
1429
-
1430
- - [ ] **Step 3: Verify both calibration reports exist**
1431
-
1432
- ```bash
1433
- ls /Users/penxia/ai-personal/zenuml-core/docs/ux-research/
1434
- ```
1435
- Expected: two reports for today's date plus `.gitkeep`.
1436
-
1437
- - [ ] **Step 4: Hand-off to the user**
1438
-
1439
- Print a summary to the user:
1440
- - Feature branch name.
1441
- - Commit count.
1442
- - Path to the two calibration reports.
1443
- - Path to the sample report.
1444
- - A note: **the branch has not been pushed. The user decides whether to open a PR.**
1445
-
1446
- Do NOT run `git push`. Do NOT open a PR. The mental seal in the user's CLAUDE.md requires the human to approve any push to remote branches, and this skill is new enough that the user will likely want to review before sharing.
1447
-
1448
- ---
1449
-
1450
- ## Known issues (filled in during execution if needed)
1451
-
1452
- *None yet. If any task surfaces a problem, document it here with the task number and a one-line description.*