@mieweb/ui 0.11.0-dev.37 → 0.11.0-dev.39
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.
- package/agent/README.md +1 -1
- package/agent/agents/mieweb-ui-design.agent.md +13 -7
- package/agent/agents/mieweb-ui-install.agent.md +7 -5
- package/agent/agents/mieweb-ui-migration.agent.md +144 -0
- package/agent/evals/README.md +74 -0
- package/agent/evals/a11y.md +183 -0
- package/agent/evals/i18n.md +185 -0
- package/agent/evals/install.md +200 -0
- package/agent/evals/migration.md +202 -0
- package/agent/evals/runs/2026-11-02.md +53 -0
- package/agent/evals/selection.md +212 -0
- package/agent/evals/styling.md +220 -0
- package/agent/skills/mieweb-ui-a11y-checklist/SKILL.md +2 -0
- package/agent/skills/mieweb-ui-catalog/SKILL.md +5 -5
- package/agent/skills/mieweb-ui-catalog/selection-guidance.md +3 -2
- package/agent/skills/mieweb-ui-tailwind4/SKILL.md +5 -2
- package/package.json +1 -1
package/agent/README.md
CHANGED
|
@@ -22,7 +22,7 @@ governing spec: later tickets cite it instead of re-deciding.
|
|
|
22
22
|
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
23
23
|
| [mieweb-ui.instructions.md](mieweb-ui.instructions.md) | The rules template. Copied verbatim to the consumer's `.github/instructions/` (VS Code Copilot auto-applies it via the `applyTo` frontmatter) and embedded, minus frontmatter, in a marked block in the consumer's `AGENTS.md` (the cross-tool convention). |
|
|
24
24
|
| [init-agent.mjs](init-agent.mjs) | The `mieweb-ui` bin. Idempotent — rerun after upgrading `@mieweb/ui` to refresh all targets. `--experimental-agents` additionally installs the agent team below. |
|
|
25
|
-
| [agents/](agents/) | Agent templates: `mieweb-ui-design` (orchestrator) + `mieweb-ui-styling` + `mieweb-ui-install` + `mieweb-ui-a11y` + `mieweb-ui-i18n`. Installed to the consumer's `.github/agents/` behind `--experimental-agents`.
|
|
25
|
+
| [agents/](agents/) | Agent templates: `mieweb-ui-design` (orchestrator) + `mieweb-ui-styling` + `mieweb-ui-install` + `mieweb-ui-a11y` + `mieweb-ui-i18n` + `mieweb-ui-migration`. Installed to the consumer's `.github/agents/` behind `--experimental-agents`. |
|
|
26
26
|
| [skills/](skills/) | Skill templates: `mieweb-ui-catalog`, `mieweb-ui-tokens`, `mieweb-ui-icons` (generated — `pnpm agent:skills`, never hand-edit) + `mieweb-ui-brands`, `mieweb-ui-tailwind4`, `mieweb-ui-a11y-checklist`, `mieweb-ui-i18n-checklist` (hand-written). Installed to `.github/skills/` behind `--experimental-agents`. |
|
|
27
27
|
| `evals/` _(Phase 2+)_ | Golden-question eval sets per specialist; the regression harness for agent knowledge. |
|
|
28
28
|
|
|
@@ -19,6 +19,10 @@ handoffs:
|
|
|
19
19
|
agent: MIE UI i18n Agent
|
|
20
20
|
prompt: Audit the code discussed above for internationalization and RTL compliance (string externalization, locale-bundle completeness, Intl formatting, logical properties) and report findings.
|
|
21
21
|
send: false
|
|
22
|
+
- label: Migration/compliance audit
|
|
23
|
+
agent: MIE UI Migration Agent
|
|
24
|
+
prompt: Audit the code discussed above for @mieweb/ui compliance (raw HTML elements, custom modal/card/badge patterns, hand-rolled icons, CSS foundation) and report findings with a prioritized replacement plan.
|
|
25
|
+
send: false
|
|
22
26
|
---
|
|
23
27
|
|
|
24
28
|
# MIE UI Design Agent (orchestrator)
|
|
@@ -48,14 +52,16 @@ comparison tables) and `mieweb-ui-icons` (icon aliases and conventions):
|
|
|
48
52
|
|
|
49
53
|
## Route to specialists
|
|
50
54
|
|
|
51
|
-
| Question is about…
|
|
52
|
-
|
|
|
53
|
-
| install / peer deps / preset / safelist / `@source`
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
|
55
|
+
| Question is about… | Delegate to |
|
|
56
|
+
| ---------------------------------------------------- | ---------------------- |
|
|
57
|
+
| install / peer deps / preset / safelist / `@source` | MIE UI Install Agent |
|
|
58
|
+
| wiring headless modules (ViewSet, SuperChat) to data | MIE UI Install Agent |
|
|
59
|
+
| tokens, CSS vars, Tailwind classes, brands, dark | MIE UI Styling Agent |
|
|
60
|
+
| ARIA, keyboard nav, screen readers, contrast | MIE UI A11y Agent |
|
|
61
|
+
| translations, locale bundles, Intl formats, RTL | MIE UI i18n Agent |
|
|
62
|
+
| migrating code to @mieweb/ui, raw-HTML compliance | MIE UI Migration Agent |
|
|
57
63
|
|
|
58
|
-
More specialists (
|
|
64
|
+
More specialists (Grids, DataVis, Views,
|
|
59
65
|
SuperChat, Rich Text) land in later phases; until one ships, answer its domain
|
|
60
66
|
from the skills and the component docs, or defer (below).
|
|
61
67
|
|
|
@@ -51,11 +51,13 @@ diagnose from evidence, then report a minimal fix — you do not edit files
|
|
|
51
51
|
|
|
52
52
|
## Peer-dependency triage
|
|
53
53
|
|
|
54
|
-
`react`/`react-dom`
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
the
|
|
54
|
+
Required peers: `react`/`react-dom` (>=18) **and** the five `@kerebron/*`
|
|
55
|
+
runtime packages (`editor`, `editor-kits`, `extension-basic-editor`,
|
|
56
|
+
`extension-menu`, `wasm`) — the main-barrel `Textarea` rides the Kerebron
|
|
57
|
+
engine. Everything else is optional and entry-scoped — before telling anyone
|
|
58
|
+
to install a package, check whether they actually import the entry that needs
|
|
59
|
+
it (catalog skill table). Under pnpm, remind consumers that peers are not
|
|
60
|
+
hoisted; required peers belong in the app's own `package.json`.
|
|
59
61
|
|
|
60
62
|
## Redirects
|
|
61
63
|
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: MIE UI Migration Agent
|
|
3
|
+
description: Migration and compliance auditor for bringing codebases onto @mieweb/ui — raw-HTML-to-component pattern enforcement (badge spans, card divs, raw buttons, tables to DataVis NITRO), hand-rolled SVG to lucide-react, CSS foundation checks, and legacy-framework migration planning (Meteor/Blaze to React). Invoke to audit a file, page, or project for @mieweb/ui compliance or to plan a migration.
|
|
4
|
+
tools: ['search', 'codebase', 'fetch']
|
|
5
|
+
handoffs:
|
|
6
|
+
- label: Apply Fixes
|
|
7
|
+
agent: agent
|
|
8
|
+
prompt: Apply the @mieweb/ui compliance fixes identified in the audit above — replace the flagged raw elements and patterns with the prescribed @mieweb/ui components, preserving existing functionality and event handlers.
|
|
9
|
+
send: false
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# MIE UI Migration Agent
|
|
13
|
+
|
|
14
|
+
You are the migration and compliance auditor for the **@mieweb/ui** design
|
|
15
|
+
system. You bring legacy code into compliance: every UI element must use a
|
|
16
|
+
`@mieweb/ui` component when one exists — no raw `<button>`, `<input>`,
|
|
17
|
+
`<select>`, `<table>`, `<textarea>`, or custom modal/card/badge markup. You
|
|
18
|
+
are **read-only**: you audit, plan, and prescribe — the **Apply Fixes**
|
|
19
|
+
handoff performs the edits.
|
|
20
|
+
|
|
21
|
+
## Your sources of truth (never inline-duplicate them)
|
|
22
|
+
|
|
23
|
+
- **`mieweb-ui-catalog` skill** — the component inventory and selection
|
|
24
|
+
guidance; every replacement you prescribe must exist there. It is the
|
|
25
|
+
raw-element → component mapping (`<button>` → `Button`, card divs →
|
|
26
|
+
`Card`/`CardContent`, badge spans → `Badge`, modal divs → `Modal`, …).
|
|
27
|
+
- **`mieweb-ui-tailwind4` skill** — the CSS foundation a migrated project
|
|
28
|
+
needs (`@source` directive, `@custom-variant dark`, `@theme` fallbacks,
|
|
29
|
+
`@tailwindcss/postcss`).
|
|
30
|
+
- **`mieweb-ui-icons` skill** — the lucide-react aliases that replace
|
|
31
|
+
hand-rolled `<svg>` and icon fonts.
|
|
32
|
+
- The installed `mieweb-ui.instructions.md` — the policy you enforce
|
|
33
|
+
(NITRO-first for tables, tokens not hardcoded colors, lucide-react icons).
|
|
34
|
+
|
|
35
|
+
## The prime directive: patterns, not just imports
|
|
36
|
+
|
|
37
|
+
Compliance is not "does the file import @mieweb/ui". Raw HTML that serves
|
|
38
|
+
the same purpose as a component is a violation even when the file already
|
|
39
|
+
imports the library:
|
|
40
|
+
|
|
41
|
+
- `<span className="rounded-full bg-blue-100 px-2 …">` is a `Badge`.
|
|
42
|
+
- `<div className="rounded-lg border p-4 shadow">` is a `Card`.
|
|
43
|
+
- `<div className="fixed inset-0 bg-black/50">…` is a `Modal`.
|
|
44
|
+
- A hand-rolled `<svg>` or icon-font glyph is a `lucide-react` icon.
|
|
45
|
+
- Any `<table>` the user will sort, filter, page, or export is
|
|
46
|
+
**DataVis NITRO** (`Table` only for a few static rows; `AGGrid` is
|
|
47
|
+
deprecated — never migrate _to_ it).
|
|
48
|
+
|
|
49
|
+
## Audit workflow
|
|
50
|
+
|
|
51
|
+
1. **Scope the audit.** A file, a page, or a whole project — confirm which,
|
|
52
|
+
then read the files before reporting. Exclude test files from violation
|
|
53
|
+
counts.
|
|
54
|
+
2. **Grep for raw elements** — `<button`, `<input`, `<select`, `<textarea`,
|
|
55
|
+
`<table`/`<thead`/`<tbody`/`<tr`/`<td`/`<th`, `<form` controls. Also grep
|
|
56
|
+
the **dynamic forms**: literal `type="date"` misses
|
|
57
|
+
`type={cond ? 'date' : 'text'}` — search `type={` and other
|
|
58
|
+
prop-expression variants too.
|
|
59
|
+
3. **Grep for patterns** — badge/pill/tag spans, card-like divs
|
|
60
|
+
(`rounded…border…shadow`), modal/overlay divs (`fixed inset-0`), inline
|
|
61
|
+
`<svg>` and icon-font classes, hand-rolled spinners/progress bars,
|
|
62
|
+
custom tab/breadcrumb/pagination markup.
|
|
63
|
+
4. **Check the CSS foundation** (project-level audits): identify the
|
|
64
|
+
consumer's CSS mode first, then audit against that mode's checklist in
|
|
65
|
+
the `mieweb-ui-tailwind4` skill — Tailwind 4 (`@source` for
|
|
66
|
+
`@mieweb/ui/dist`, `@custom-variant dark`, `@theme` fallbacks,
|
|
67
|
+
`@tailwindcss/postcss`), Tailwind 3 (preset + safelist + `content`
|
|
68
|
+
coverage), or precompiled CSS (`styles.css`/`init.css` import — never
|
|
69
|
+
prescribe Tailwind tooling to it). Validate the dark-mode toggle
|
|
70
|
+
against the `@custom-variant` actually in effect (a single-hook toggle
|
|
71
|
+
against `init.css` is valid); setting both `.dark` and `data-theme` is
|
|
72
|
+
the recommendation for new code, not a violation when one hook matches.
|
|
73
|
+
5. **Build the resolution plan**, prioritized: layout shell (`AppHeader`,
|
|
74
|
+
`Sidebar`, `SiteFooter`) → buttons → form elements → cards & modals →
|
|
75
|
+
tables (NITRO) → feedback (`Badge`, `Toast`, `Spinner`) → navigation
|
|
76
|
+
(`Tabs`, `Breadcrumb`, `Pagination`). Replacements preserve existing
|
|
77
|
+
functionality and event handlers.
|
|
78
|
+
6. **Detect gaps.** A pattern with no `@mieweb/ui` equivalent is not a
|
|
79
|
+
violation — report it with the tier recommendation: compose from existing
|
|
80
|
+
primitives; build locally in library style (CVA variants, `forwardRef`,
|
|
81
|
+
theme CSS variables, dark mode, ARIA); headless-module contract if it
|
|
82
|
+
renders a caller-owned collection; contribute upstream once stable.
|
|
83
|
+
7. **Report, then hand off.** Findings in the format below; offer
|
|
84
|
+
**Apply Fixes** for the edits.
|
|
85
|
+
|
|
86
|
+
## Audit output format
|
|
87
|
+
|
|
88
|
+
### 🧭 @mieweb/ui compliance audit for `<scope>`
|
|
89
|
+
|
|
90
|
+
| # | Category | File | Line | Violation | Replacement |
|
|
91
|
+
| --- | -------- | ---- | ---- | --------- | ----------- |
|
|
92
|
+
|
|
93
|
+
Order findings: raw elements, then patterns, then CSS foundation, then gaps.
|
|
94
|
+
After the table, the compliance summary:
|
|
95
|
+
|
|
96
|
+
| Category | Count | Status |
|
|
97
|
+
| ----------------------- | ----- | ------ |
|
|
98
|
+
| Raw `<button>` | X | ❌ |
|
|
99
|
+
| Raw form elements | X | ❌ |
|
|
100
|
+
| Raw `<table>` | X | ❌ |
|
|
101
|
+
| Custom modal/card/badge | X | ❌ |
|
|
102
|
+
| Hand-rolled icons | X | ❌ |
|
|
103
|
+
| CSS foundation | — | ✅/❌ |
|
|
104
|
+
| Gaps (no equivalent) | N | 📝 |
|
|
105
|
+
|
|
106
|
+
Close with what passes, any judgment calls, and the **Apply Fixes** handoff.
|
|
107
|
+
|
|
108
|
+
## Migration planning (beyond single-file audits)
|
|
109
|
+
|
|
110
|
+
For whole-app migrations (e.g. Meteor 2 + Blaze → Meteor 3 + React +
|
|
111
|
+
@mieweb/ui), plan in this order: scaffold → install deps → the three
|
|
112
|
+
critical CSS/PostCSS/Tailwind config files → verify Tailwind renders →
|
|
113
|
+
shared hooks (`useTheme`, `useBrand`) → layout shell → features one at a
|
|
114
|
+
time, auth first → verify dark mode, brand switching, and `tsc --noEmit`.
|
|
115
|
+
Meteor 3 specifics: all methods async, collection ops use `*Async()`
|
|
116
|
+
variants. Verify each migrated feature before starting the next.
|
|
117
|
+
|
|
118
|
+
## Redirects
|
|
119
|
+
|
|
120
|
+
- "Which component should I use?" for new (non-migration) work → **MIE UI
|
|
121
|
+
Design Agent** (your mapping covers replacements; open-ended selection is
|
|
122
|
+
theirs).
|
|
123
|
+
- Broken styling after install, unstyled components, Tailwind wiring →
|
|
124
|
+
**MIE UI Install Agent** (you flag the missing foundation; they debug it).
|
|
125
|
+
- Token/brand/dark-mode policy questions → **MIE UI Styling Agent**.
|
|
126
|
+
- ARIA, keyboard navigation, focus, contrast → **MIE UI A11y Agent** (your
|
|
127
|
+
replacements inherit library a11y; auditing what remains is theirs).
|
|
128
|
+
- String externalization, locale bundles, RTL → **MIE UI i18n Agent**.
|
|
129
|
+
|
|
130
|
+
## Rules
|
|
131
|
+
|
|
132
|
+
1. Evidence over checklists: cite file and line for every finding; read the
|
|
133
|
+
code before flagging it.
|
|
134
|
+
2. **Patterns, not just imports** — a compliant import list proves nothing;
|
|
135
|
+
grep for the raw markup the components replace.
|
|
136
|
+
3. Grep dynamic forms: prop expressions (`type={…}`, spread props,
|
|
137
|
+
conditional classes) hide violations that literal-string greps miss.
|
|
138
|
+
4. Never prescribe a component or prop you cannot verify in the catalog
|
|
139
|
+
skill, the published component docs (https://ui.mieweb.org), or the
|
|
140
|
+
package's public types — the catalog is a selection inventory, not an
|
|
141
|
+
API reference; a gap honestly reported beats an invented replacement.
|
|
142
|
+
5. Replacements must preserve behavior — event handlers, controlled state,
|
|
143
|
+
form semantics. Flag any replacement that would change behavior as a
|
|
144
|
+
judgment call instead of silently prescribing it.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Agent team evals
|
|
2
|
+
|
|
3
|
+
Golden-question eval sets for the MIE UI agent team (#545, seeded by #587).
|
|
4
|
+
Each file covers one specialist domain with 20+ entries sourced from the real
|
|
5
|
+
adoption corpus — [lessons/](../../lessons/README.md), the generated and
|
|
6
|
+
hand-written [agent/skills/](../skills/), the installed
|
|
7
|
+
[mieweb-ui.instructions.md](../mieweb-ui.instructions.md), and past consumer
|
|
8
|
+
issues in this repo.
|
|
9
|
+
|
|
10
|
+
These files are maintainer-side quality tooling. They are **not** shipped by
|
|
11
|
+
`init-agent.mjs` — consumers get agents and skills, not the exam answers.
|
|
12
|
+
|
|
13
|
+
## Files
|
|
14
|
+
|
|
15
|
+
| File | Domain | Primary agent |
|
|
16
|
+
| ------------------------------ | ------------------------------------ | ---------------------- |
|
|
17
|
+
| [selection.md](./selection.md) | Component selection / catalog | MIE UI Design Agent |
|
|
18
|
+
| [styling.md](./styling.md) | Styling, tokens, brands, dark mode | MIE UI Styling Agent |
|
|
19
|
+
| [install.md](./install.md) | Install, CSS foundation, wiring | MIE UI Install Agent |
|
|
20
|
+
| [a11y.md](./a11y.md) | Accessibility | MIE UI A11y Agent |
|
|
21
|
+
| [i18n.md](./i18n.md) | Internationalization / RTL | MIE UI i18n Agent |
|
|
22
|
+
| [migration.md](./migration.md) | Migration / compliance (incl. icons) | MIE UI Migration Agent |
|
|
23
|
+
|
|
24
|
+
## Entry format
|
|
25
|
+
|
|
26
|
+
```markdown
|
|
27
|
+
### SEL-3 — Raw table replacement
|
|
28
|
+
|
|
29
|
+
- **Ask:** "What @mieweb/ui component replaces a raw `<table>`?"
|
|
30
|
+
- **Expect:** `Table` + composition slots for static rows; `DataVisNitroGrid`
|
|
31
|
+
once sorting/filtering/paging/export is needed; never hand-roll grid features.
|
|
32
|
+
- **Agent:** MIE UI Design Agent
|
|
33
|
+
- **Source:** mieweb-ui.instructions.md — Rules 1, 3
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
- **Ask** — the question, phrased the way a consumer actually asks it.
|
|
37
|
+
- **Expect** — the key points a correct answer must contain. Not a transcript:
|
|
38
|
+
an answer passes if every Expect point is present and nothing contradicts
|
|
39
|
+
the corpus. Missing key points downgrade per the scoring procedure below
|
|
40
|
+
(PARTIAL, or FAIL when the answer is wrong overall); inventing APIs or
|
|
41
|
+
prescribing forbidden tooling is always FAIL.
|
|
42
|
+
- **Agent** — the specialist that should end up answering. When the question
|
|
43
|
+
is posed to the MIE UI Design Agent, correct routing to this agent (or a
|
|
44
|
+
correct direct answer where the orchestrator owns the domain, e.g.
|
|
45
|
+
selection) is part of the pass criteria.
|
|
46
|
+
- **Source** — where the known-good answer lives, so graders can re-verify
|
|
47
|
+
and corpus fixes have a target.
|
|
48
|
+
|
|
49
|
+
## Running a manual eval
|
|
50
|
+
|
|
51
|
+
1. Install the team into a sandbox app:
|
|
52
|
+
`node <ui-repo>/agent/init-agent.mjs init-agent --experimental-agents`
|
|
53
|
+
(run from the sandbox root; verify `pwd` first).
|
|
54
|
+
2. Open the installed agent for the domain under test (or start from the
|
|
55
|
+
MIE UI Design Agent to also score routing).
|
|
56
|
+
3. Ask a sample of questions from the file — a stratified sample of 3–5 per
|
|
57
|
+
domain is a meaningful smoke; the full set is for release-gating runs.
|
|
58
|
+
4. Score each answer PASS / PARTIAL / FAIL against **Expect**:
|
|
59
|
+
- PASS — all key points present, no corpus contradictions.
|
|
60
|
+
- PARTIAL — correct direction but a key point missing.
|
|
61
|
+
- FAIL — wrong, invented, or missing answer; misrouted.
|
|
62
|
+
5. File every PARTIAL/FAIL as a corpus fix: if the knowledge exists but the
|
|
63
|
+
agent missed it, fix the agent/skill prompt; if the knowledge is absent,
|
|
64
|
+
add it to `lessons/` (and regenerate skills with `pnpm agent:skills` when
|
|
65
|
+
the fix lands in generated inputs).
|
|
66
|
+
|
|
67
|
+
## Maintaining the sets
|
|
68
|
+
|
|
69
|
+
- Add entries when a real consumer question or issue exposes a gap — cite the
|
|
70
|
+
issue number in **Source**.
|
|
71
|
+
- Update entries when the corpus changes (component retirements, new rules);
|
|
72
|
+
stale Expect text is worse than no entry.
|
|
73
|
+
- Keep answers grounded: every Expect point must be verifiable in the cited
|
|
74
|
+
source. Do not write aspirational answers.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# Evals — Accessibility
|
|
2
|
+
|
|
3
|
+
Primary agent: **MIE UI A11y Agent**. See [README.md](./README.md) for format
|
|
4
|
+
and scoring.
|
|
5
|
+
|
|
6
|
+
### A11Y-1 — Icon-only button name
|
|
7
|
+
|
|
8
|
+
- **Ask:** "Is `aria-label` enough for an icon-only button, or do I need
|
|
9
|
+
visible text?"
|
|
10
|
+
- **Expect:** `aria-label` is sufficient but must be descriptive
|
|
11
|
+
(`aria-label="Save"`, never "icon"/"button"); icon-only controls always
|
|
12
|
+
need one; decorative icons get `aria-hidden="true"`.
|
|
13
|
+
- **Agent:** MIE UI A11y Agent
|
|
14
|
+
- **Source:** agent/skills/mieweb-ui-a11y-checklist/SKILL.md — Audit (1); mieweb-ui.instructions.md — Rule 2
|
|
15
|
+
|
|
16
|
+
### A11Y-2 — Drag-and-drop keyboard support
|
|
17
|
+
|
|
18
|
+
- **Ask:** "My list reorders by drag-and-drop. Do I need keyboard support?"
|
|
19
|
+
- **Expect:** Yes — `useDragReorder` with at least one keyboard path:
|
|
20
|
+
`keyboard: true` + `rowProps(id)` spread on rows (Alt+↑/↓) and/or visible
|
|
21
|
+
`moveButtonProps` buttons (either alone is supported). Also render the
|
|
22
|
+
hook's `announcement` in a polite `sr-only` live region so reorders are
|
|
23
|
+
announced.
|
|
24
|
+
- **Agent:** MIE UI A11y Agent
|
|
25
|
+
- **Source:** agent/skills/mieweb-ui-a11y-checklist/SKILL.md — Audit (2), toolkit; src/hooks/useDragReorder.ts
|
|
26
|
+
|
|
27
|
+
### A11Y-3 — Modal focus restore
|
|
28
|
+
|
|
29
|
+
- **Ask:** "Modal traps focus and closes on Escape. Anything else?"
|
|
30
|
+
- **Expect:** Return focus to the trigger on close — the focus trap doesn't
|
|
31
|
+
restore focus itself; track the trigger ref and focus it in `onOpenChange`
|
|
32
|
+
when the next-open value is `false` (Modal has no `onClose` prop).
|
|
33
|
+
- **Agent:** MIE UI A11y Agent
|
|
34
|
+
- **Source:** agent/skills/mieweb-ui-a11y-checklist/SKILL.md — Audit (3), toolkit; src/components/Modal — `ModalProps`
|
|
35
|
+
|
|
36
|
+
### A11Y-4 — Announcement chattiness
|
|
37
|
+
|
|
38
|
+
- **Ask:** "Should a live region announce the item count on every keystroke?"
|
|
39
|
+
- **Expect:** No — announce meaningful changes only; debounce or scope to
|
|
40
|
+
commits (e.g. reorders). `role="status"`/`aria-live="polite"` for passive
|
|
41
|
+
updates, `role="alert"` for errors.
|
|
42
|
+
- **Agent:** MIE UI A11y Agent
|
|
43
|
+
- **Source:** agent/skills/mieweb-ui-a11y-checklist/SKILL.md — Audit (4)
|
|
44
|
+
|
|
45
|
+
### A11Y-5 — White on primary-500
|
|
46
|
+
|
|
47
|
+
- **Ask:** "Does white text on `bg-primary-500` (BlueHive) pass AA?"
|
|
48
|
+
- **Expect:** No — 2.65:1, and it still fails at primary-700. Use
|
|
49
|
+
`<Button variant="primary">` (AA-safe shade internally); never hardcode
|
|
50
|
+
colors for button-like elements.
|
|
51
|
+
- **Agent:** MIE UI A11y Agent
|
|
52
|
+
- **Source:** agent/skills/mieweb-ui-a11y-checklist/SKILL.md — Known AA contrast traps
|
|
53
|
+
|
|
54
|
+
### A11Y-6 — Interactive element checklist
|
|
55
|
+
|
|
56
|
+
- **Ask:** "What makes an interactive element accessible here?"
|
|
57
|
+
- **Expect:** Accessible name (visible text, `aria-label`, or
|
|
58
|
+
`aria-labelledby`), semantic HTML (no clickable divs), announced dynamic
|
|
59
|
+
updates (Toast/Alert), logical tab order, focus indicators never removed.
|
|
60
|
+
- **Agent:** MIE UI A11y Agent
|
|
61
|
+
- **Source:** mieweb-ui.instructions.md — Rule 9
|
|
62
|
+
|
|
63
|
+
### A11Y-7 — Muted text trap
|
|
64
|
+
|
|
65
|
+
- **Ask:** "Is `text-neutral-500` on `bg-neutral-100` OK for small text?"
|
|
66
|
+
- **Expect:** No — 4.34:1 fails AA for small text; use `text-neutral-600`. In
|
|
67
|
+
dark mode pair `dark:text-neutral-400` with a dark surface like
|
|
68
|
+
`dark:bg-neutral-800`; verify per brand.
|
|
69
|
+
- **Agent:** MIE UI A11y Agent
|
|
70
|
+
- **Source:** agent/skills/mieweb-ui-a11y-checklist/SKILL.md — Known AA contrast traps
|
|
71
|
+
|
|
72
|
+
### A11Y-8 — Live announcements
|
|
73
|
+
|
|
74
|
+
- **Ask:** "How do I announce a state change to screen readers?"
|
|
75
|
+
- **Expect:** `const [announcement, announce] = useLiveAnnouncement()` and
|
|
76
|
+
render `<div aria-live="polite" className="sr-only">{announcement}</div>`;
|
|
77
|
+
call `announce()` on meaningful changes.
|
|
78
|
+
- **Agent:** MIE UI A11y Agent
|
|
79
|
+
- **Source:** agent/skills/mieweb-ui-a11y-checklist/SKILL.md — toolkit
|
|
80
|
+
|
|
81
|
+
### A11Y-9 — Loading states
|
|
82
|
+
|
|
83
|
+
- **Ask:** "Custom CSS spinner for loading, or a component?"
|
|
84
|
+
- **Expect:** Library components only: `Spinner` (inline), `Skeleton`
|
|
85
|
+
(placeholder), `LoadingPage` (full page). Never hand-roll.
|
|
86
|
+
- **Agent:** MIE UI A11y Agent
|
|
87
|
+
- **Source:** mieweb-ui.instructions.md — Rule 8
|
|
88
|
+
|
|
89
|
+
### A11Y-10 — Clickable div
|
|
90
|
+
|
|
91
|
+
- **Ask:** "My clickable div lacks `role=\"button\"` and `tabIndex`. Add
|
|
92
|
+
them?"
|
|
93
|
+
- **Expect:** No — replace it with `Button` (or the right semantic
|
|
94
|
+
component); don't bolt ARIA onto divs when a real component exists.
|
|
95
|
+
- **Agent:** MIE UI A11y Agent
|
|
96
|
+
- **Source:** agent/skills/mieweb-ui-a11y-checklist/SKILL.md — Audit (2)
|
|
97
|
+
|
|
98
|
+
### A11Y-11 — Hidden file input
|
|
99
|
+
|
|
100
|
+
- **Ask:** "A hidden `<input type=\"file\">` sits behind a styled drop zone.
|
|
101
|
+
Keyboard story?"
|
|
102
|
+
- **Expect:** It must stay keyboard-openable — wire keyboard handlers that
|
|
103
|
+
trigger the input's `click()`, or use `DropzoneOverlay`/`FileManager`.
|
|
104
|
+
- **Agent:** MIE UI A11y Agent
|
|
105
|
+
- **Source:** agent/skills/mieweb-ui-a11y-checklist/SKILL.md — Audit (2)
|
|
106
|
+
|
|
107
|
+
### A11Y-12 — Scrollable region
|
|
108
|
+
|
|
109
|
+
- **Ask:** "How do I make an overflow container keyboard-accessible?"
|
|
110
|
+
- **Expect:** `tabIndex={0}` + `role="region"` + `aria-label`, and it must be
|
|
111
|
+
the single scroll container (no nested scrolling children).
|
|
112
|
+
- **Agent:** MIE UI A11y Agent
|
|
113
|
+
- **Source:** agent/skills/mieweb-ui-a11y-checklist/SKILL.md — toolkit
|
|
114
|
+
|
|
115
|
+
### A11Y-13 — Dark-mode hover contrast
|
|
116
|
+
|
|
117
|
+
- **Ask:** "Tab hover states look fine in light mode — do I need to check
|
|
118
|
+
dark mode separately?"
|
|
119
|
+
- **Expect:** Yes — hover/active states must pass AA in **both** themes;
|
|
120
|
+
dark-mode hover shades have regressed before (Tabs, outline Button). Use
|
|
121
|
+
token pairs from the a11y checklist and verify per theme.
|
|
122
|
+
- **Agent:** MIE UI A11y Agent
|
|
123
|
+
- **Source:** issues #512, #511; agent/skills/mieweb-ui-a11y-checklist/SKILL.md — contrast traps
|
|
124
|
+
|
|
125
|
+
### A11Y-14 — Toasts and dynamic updates
|
|
126
|
+
|
|
127
|
+
- **Ask:** "Do async save results need announcing?"
|
|
128
|
+
- **Expect:** Yes — dynamic updates are announced via `Toast`/`Alert` (which
|
|
129
|
+
carry live-region semantics), not silent inline text swaps.
|
|
130
|
+
- **Agent:** MIE UI A11y Agent
|
|
131
|
+
- **Source:** mieweb-ui.instructions.md — Rule 9
|
|
132
|
+
|
|
133
|
+
### A11Y-15 — Focus indicators
|
|
134
|
+
|
|
135
|
+
- **Ask:** "Can I remove the focus ring? The designer finds it ugly."
|
|
136
|
+
- **Expect:** No — focus indicators are never removed; restyle via tokens if
|
|
137
|
+
needed, keep them visible (including in dark mode).
|
|
138
|
+
- **Agent:** MIE UI A11y Agent
|
|
139
|
+
- **Source:** mieweb-ui.instructions.md — Rule 9
|
|
140
|
+
|
|
141
|
+
### A11Y-16 — Semantic landmarks
|
|
142
|
+
|
|
143
|
+
- **Ask:** "Is a div-based layout fine if the CSS is right?"
|
|
144
|
+
- **Expect:** No — use semantic HTML (`nav`, `main`, `button`, …); screen
|
|
145
|
+
readers navigate by landmarks and roles, not by class names.
|
|
146
|
+
- **Agent:** MIE UI A11y Agent
|
|
147
|
+
- **Source:** mieweb-ui.instructions.md — Rule 9
|
|
148
|
+
|
|
149
|
+
### A11Y-17 — Exit animations
|
|
150
|
+
|
|
151
|
+
- **Ask:** "During an exit animation, the screen reader still reads the
|
|
152
|
+
leaving element. Is that expected?"
|
|
153
|
+
- **Expect:** It happens today but isn't acceptable — exiting children must be
|
|
154
|
+
`aria-hidden` and `inert` for the duration. `AnimatedPresence` does **not**
|
|
155
|
+
yet do this automatically (open #474); hand-rolled exits must handle it
|
|
156
|
+
themselves.
|
|
157
|
+
- **Agent:** MIE UI A11y Agent
|
|
158
|
+
- **Source:** issue #474 (open); agent/skills/mieweb-ui-a11y-checklist/SKILL.md — exit animations
|
|
159
|
+
|
|
160
|
+
### A11Y-18 — Icon-only Button pattern
|
|
161
|
+
|
|
162
|
+
- **Ask:** "What's the canonical icon-only button?"
|
|
163
|
+
- **Expect:** `<Button size="icon" aria-label="...">` — the `aria-label` is
|
|
164
|
+
required, not optional.
|
|
165
|
+
- **Agent:** MIE UI A11y Agent
|
|
166
|
+
- **Source:** mieweb-ui.instructions.md — Rule 2
|
|
167
|
+
|
|
168
|
+
### A11Y-19 — Tab order
|
|
169
|
+
|
|
170
|
+
- **Ask:** "Does visual order vs DOM order matter for keyboard users?"
|
|
171
|
+
- **Expect:** Yes — tab order must be logical; don't reorder purely with CSS
|
|
172
|
+
so that focus jumps around, and don't use positive `tabIndex` to patch it.
|
|
173
|
+
- **Agent:** MIE UI A11y Agent
|
|
174
|
+
- **Source:** mieweb-ui.instructions.md — Rule 9
|
|
175
|
+
|
|
176
|
+
### A11Y-20 — Verifying contrast per brand
|
|
177
|
+
|
|
178
|
+
- **Ask:** "Contrast passes on the default palette. Done?"
|
|
179
|
+
- **Expect:** No — brands redefine the primary scale, so brand-dependent
|
|
180
|
+
pairs must be re-verified per brand (the checklist's traps are stated for
|
|
181
|
+
the default palette/BlueHive).
|
|
182
|
+
- **Agent:** MIE UI A11y Agent
|
|
183
|
+
- **Source:** agent/skills/mieweb-ui-a11y-checklist/SKILL.md — Known AA contrast traps
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# Evals — Internationalization / RTL
|
|
2
|
+
|
|
3
|
+
Primary agent: **MIE UI i18n Agent**. See [README.md](./README.md) for format
|
|
4
|
+
and scoring.
|
|
5
|
+
|
|
6
|
+
### I18N-1 — Hardcoded strings
|
|
7
|
+
|
|
8
|
+
- **Ask:** "I wrote `<Button>Save</Button>`. Is that OK?"
|
|
9
|
+
- **Expect:** No — every user-facing string goes through `t()`:
|
|
10
|
+
`<Button>{t('common.save')}</Button>`. Includes aria-labels, placeholders,
|
|
11
|
+
and error messages.
|
|
12
|
+
- **Agent:** MIE UI i18n Agent
|
|
13
|
+
- **Source:** agent/skills/mieweb-ui-i18n-checklist/SKILL.md — Audit (1)
|
|
14
|
+
|
|
15
|
+
### I18N-2 — Missing keys ship silently
|
|
16
|
+
|
|
17
|
+
- **Ask:** "I added a locale bundle but missed some keys. Will anything
|
|
18
|
+
break visibly?"
|
|
19
|
+
- **Expect:** No — missing keys silently fall back to `fallbackLng`, so they
|
|
20
|
+
ship invisibly. Every bundle must cover every logical key of the canonical
|
|
21
|
+
bundle in the same commit.
|
|
22
|
+
- **Agent:** MIE UI i18n Agent
|
|
23
|
+
- **Source:** agent/skills/mieweb-ui-i18n-checklist/SKILL.md — Audit (2)
|
|
24
|
+
|
|
25
|
+
### I18N-3 — Auditing locale completeness
|
|
26
|
+
|
|
27
|
+
- **Ask:** "How do I check a locale bundle is complete?"
|
|
28
|
+
- **Expect:** Diff logical keys against the canonical bundle, stripping
|
|
29
|
+
plural suffixes (`_one`, `_other`, …) but preserving context suffixes
|
|
30
|
+
(`invite_admin` vs `invite_guest` stay distinct) — then separately verify
|
|
31
|
+
each pluralized key carries all plural forms that locale's CLDR rules
|
|
32
|
+
require (e.g. Arabic needs more than `_one`/`_other`).
|
|
33
|
+
- **Agent:** MIE UI i18n Agent
|
|
34
|
+
- **Source:** agent/skills/mieweb-ui-i18n-checklist/SKILL.md — Audit (2)
|
|
35
|
+
|
|
36
|
+
### I18N-4 — Hardcoded locale in formatting
|
|
37
|
+
|
|
38
|
+
- **Ask:** "Is `date.toLocaleDateString('en-US', …)` fine?"
|
|
39
|
+
- **Expect:** No — that pins every user to en-US. Call it without a hardcoded
|
|
40
|
+
tag, using the active language via `useLocale()` (where `LocaleProvider` is
|
|
41
|
+
in scope) or `i18n.language`.
|
|
42
|
+
- **Agent:** MIE UI i18n Agent
|
|
43
|
+
- **Source:** agent/skills/mieweb-ui-i18n-checklist/SKILL.md — Audit (3)
|
|
44
|
+
|
|
45
|
+
### I18N-5 — String concatenation
|
|
46
|
+
|
|
47
|
+
- **Ask:** "Can I build messages like `t('greeting') + name` or
|
|
48
|
+
`` `${t('count')} items` ``?"
|
|
49
|
+
- **Expect:** No — concatenation breaks word order across languages. Use
|
|
50
|
+
interpolation: `t('greeting', { name })`; `t('items', { count })` for
|
|
51
|
+
plurals.
|
|
52
|
+
- **Agent:** MIE UI i18n Agent
|
|
53
|
+
- **Source:** agent/skills/mieweb-ui-i18n-checklist/SKILL.md — Audit (3)
|
|
54
|
+
|
|
55
|
+
### I18N-6 — Plurals
|
|
56
|
+
|
|
57
|
+
- **Ask:** "How do I translate '3 items' vs '1 item'?"
|
|
58
|
+
- **Expect:** One logical key with `count` interpolation; bundles carry CLDR
|
|
59
|
+
plural forms (`_one`, `_other`, …) — never an in-code
|
|
60
|
+
`count === 1 ? … : …` branch.
|
|
61
|
+
- **Agent:** MIE UI i18n Agent
|
|
62
|
+
- **Source:** agent/skills/mieweb-ui-i18n-checklist/SKILL.md — Audit (2), (3)
|
|
63
|
+
|
|
64
|
+
### I18N-7 — Physical margin classes
|
|
65
|
+
|
|
66
|
+
- **Ask:** "Does `className=\"ml-4\"` work in RTL?"
|
|
67
|
+
- **Expect:** No — use logical classes: `ms-4`, `ps-*`, `start-*`,
|
|
68
|
+
`text-start`; never `ml-*`, `pl-*`, `left-*`, `right-*`, `text-left`.
|
|
69
|
+
- **Agent:** MIE UI i18n Agent
|
|
70
|
+
- **Source:** agent/skills/mieweb-ui-i18n-checklist/SKILL.md — RTL checklist; mieweb-ui.instructions.md — Rule 10
|
|
71
|
+
|
|
72
|
+
### I18N-8 — Flipping icons
|
|
73
|
+
|
|
74
|
+
- **Ask:** "Do chevrons flip automatically in RTL?"
|
|
75
|
+
- **Expect:** No — add `rtl:-scale-x-100` to directional chevrons/arrows; do
|
|
76
|
+
NOT flip decorative icons (checkmarks, media controls, up/down arrows).
|
|
77
|
+
- **Agent:** MIE UI i18n Agent
|
|
78
|
+
- **Source:** agent/skills/mieweb-ui-i18n-checklist/SKILL.md — RTL checklist
|
|
79
|
+
|
|
80
|
+
### I18N-9 — Arrow-key direction
|
|
81
|
+
|
|
82
|
+
- **Ask:** "My keyboard handler uses ArrowLeft/ArrowRight. RTL concern?"
|
|
83
|
+
- **Expect:** Yes — arrow keys follow **visual** direction: check
|
|
84
|
+
`isRtl(event.currentTarget)` in the handler and swap the semantics.
|
|
85
|
+
- **Agent:** MIE UI i18n Agent
|
|
86
|
+
- **Source:** agent/skills/mieweb-ui-i18n-checklist/SKILL.md — RTL checklist
|
|
87
|
+
|
|
88
|
+
### I18N-10 — isRtl vs useDirection
|
|
89
|
+
|
|
90
|
+
- **Ask:** "When `isRtl()` vs `useDirection(ref)`?"
|
|
91
|
+
- **Expect:** `isRtl()` is a one-shot snapshot for event handlers;
|
|
92
|
+
`useDirection(ref)` is reactive, for when direction drives rendering. Never
|
|
93
|
+
store an `isRtl` result across renders — it stales.
|
|
94
|
+
- **Agent:** MIE UI i18n Agent
|
|
95
|
+
- **Source:** agent/skills/mieweb-ui-i18n-checklist/SKILL.md — direction toolkit
|
|
96
|
+
|
|
97
|
+
### I18N-11 — Portals and direction
|
|
98
|
+
|
|
99
|
+
- **Ask:** "How does a portaled Tooltip know the direction?"
|
|
100
|
+
- **Expect:** Portals escape local `dir` overrides — read direction from a
|
|
101
|
+
non-portaled ref via `useDirection(ref)`, not from the portaled node.
|
|
102
|
+
- **Agent:** MIE UI i18n Agent
|
|
103
|
+
- **Source:** agent/skills/mieweb-ui-i18n-checklist/SKILL.md — RTL checklist
|
|
104
|
+
|
|
105
|
+
### I18N-12 — Hardcoded BCP-47 tags
|
|
106
|
+
|
|
107
|
+
- **Ask:** "Can I pass `'en-US'` to `Intl.NumberFormat`?"
|
|
108
|
+
- **Expect:** No — drive Intl APIs from the active language, never hardcoded
|
|
109
|
+
tags.
|
|
110
|
+
- **Agent:** MIE UI i18n Agent
|
|
111
|
+
- **Source:** mieweb-ui.instructions.md — Rule 10
|
|
112
|
+
|
|
113
|
+
### I18N-13 — Manual currency formatting
|
|
114
|
+
|
|
115
|
+
- **Ask:** "Is `'$' + amount.toFixed(2)` acceptable?"
|
|
116
|
+
- **Expect:** No — use `Intl.NumberFormat` with
|
|
117
|
+
`{ style: 'currency', currency }` under the active locale; manual string
|
|
118
|
+
formatting breaks symbols, separators, and placement.
|
|
119
|
+
- **Agent:** MIE UI i18n Agent
|
|
120
|
+
- **Source:** mieweb-ui.instructions.md — Rule 10; agent/skills/mieweb-ui-i18n-checklist/SKILL.md — Audit (3)
|
|
121
|
+
|
|
122
|
+
### I18N-14 — Adding a locale
|
|
123
|
+
|
|
124
|
+
- **Ask:** "What's the full procedure to add a new locale?"
|
|
125
|
+
- **Expect:** Add `<locale>.json` beside existing bundles covering every
|
|
126
|
+
logical key with that locale's CLDR plural forms; register in i18next
|
|
127
|
+
`resources`; expose in the language selector; on change call
|
|
128
|
+
`i18n.changeLanguage(code)` and set `dir` via `isRtlLocale()`; verify Intl
|
|
129
|
+
output.
|
|
130
|
+
- **Agent:** MIE UI i18n Agent
|
|
131
|
+
- **Source:** agent/skills/mieweb-ui-i18n-checklist/SKILL.md — Adding a locale
|
|
132
|
+
|
|
133
|
+
### I18N-15 — Physical inline styles
|
|
134
|
+
|
|
135
|
+
- **Ask:** "My inline styles use `marginLeft` and `textAlign: 'left'`. Caught
|
|
136
|
+
by the class greps?"
|
|
137
|
+
- **Expect:** No — inline physical styles evade class greps and silently
|
|
138
|
+
break RTL. Use `marginInlineStart`, `insetInlineStart`,
|
|
139
|
+
`textAlign: 'start'`.
|
|
140
|
+
- **Agent:** MIE UI i18n Agent
|
|
141
|
+
- **Source:** agent/skills/mieweb-ui-i18n-checklist/SKILL.md — RTL checklist
|
|
142
|
+
|
|
143
|
+
### I18N-16 — Key naming
|
|
144
|
+
|
|
145
|
+
- **Ask:** "Can I use the English text as the translation key?"
|
|
146
|
+
- **Expect:** Use logical keys (`common.save`), not English sentences —
|
|
147
|
+
bundles are keyed by meaning, and plural/context suffixes attach to logical
|
|
148
|
+
keys.
|
|
149
|
+
- **Agent:** MIE UI i18n Agent
|
|
150
|
+
- **Source:** agent/skills/mieweb-ui-i18n-checklist/SKILL.md — Audit (1), (2)
|
|
151
|
+
|
|
152
|
+
### I18N-17 — Non-visible strings
|
|
153
|
+
|
|
154
|
+
- **Ask:** "Do aria-labels, placeholders, and toast messages need `t()` too?"
|
|
155
|
+
- **Expect:** Yes — every user-facing string, including assistive-tech-only
|
|
156
|
+
text, placeholders, and error/notification messages.
|
|
157
|
+
- **Agent:** MIE UI i18n Agent
|
|
158
|
+
- **Source:** agent/skills/mieweb-ui-i18n-checklist/SKILL.md — Audit (1)
|
|
159
|
+
|
|
160
|
+
### I18N-18 — Setting dir on language change
|
|
161
|
+
|
|
162
|
+
- **Ask:** "The user switches to Arabic. What besides `changeLanguage`?"
|
|
163
|
+
- **Expect:** Set the document `dir` on every language change via
|
|
164
|
+
`isRtlLocale()` — translations without `dir` leave the layout LTR.
|
|
165
|
+
- **Agent:** MIE UI i18n Agent
|
|
166
|
+
- **Source:** agent/skills/mieweb-ui-i18n-checklist/SKILL.md — Adding a locale
|
|
167
|
+
|
|
168
|
+
### I18N-19 — RTL audit mechanics
|
|
169
|
+
|
|
170
|
+
- **Ask:** "How do I audit a codebase for RTL violations?"
|
|
171
|
+
- **Expect:** Grep for physical classes (`ml-`, `mr-`, `pl-`, `pr-`,
|
|
172
|
+
`left-`, `right-`, `text-left`, `text-right`) **and** check what greps
|
|
173
|
+
miss: inline physical styles, dynamic/conditional class strings, and
|
|
174
|
+
directional keyboard handlers.
|
|
175
|
+
- **Agent:** MIE UI i18n Agent
|
|
176
|
+
- **Source:** agent/skills/mieweb-ui-i18n-checklist/SKILL.md — RTL checklist
|
|
177
|
+
|
|
178
|
+
### I18N-20 — Scope of Rule 10
|
|
179
|
+
|
|
180
|
+
- **Ask:** "What does the i18n rule actually require?"
|
|
181
|
+
- **Expect:** All user-facing text externalized through `t()`; dates,
|
|
182
|
+
numbers, and currency via Intl under the active language; logical CSS
|
|
183
|
+
properties/classes for RTL; no hardcoded locale tags.
|
|
184
|
+
- **Agent:** MIE UI i18n Agent
|
|
185
|
+
- **Source:** mieweb-ui.instructions.md — Rule 10
|